diff options
author | Max Kellermann <max@duempel.org> | 2009-07-03 01:02:53 +0200 |
---|---|---|
committer | Max Kellermann <max@duempel.org> | 2009-07-03 01:02:53 +0200 |
commit | 48f3e13beccec63de5322e2cc0c241527efeabef (patch) | |
tree | 8ec13aed180ef6e423e783d7a1ac803098f4d79d | |
parent | a923080d9b0d4866025404bcaf97111707d6fe23 (diff) | |
download | mpd-48f3e13beccec63de5322e2cc0c241527efeabef.tar.gz mpd-48f3e13beccec63de5322e2cc0c241527efeabef.tar.xz mpd-48f3e13beccec63de5322e2cc0c241527efeabef.zip |
filter: added new plugin API for filters
The filter API allows us to implement software volume as a pluggable
filter, and we will be able to integrate libraries like SoX.
-rw-r--r-- | Makefile.am | 6 | ||||
-rw-r--r-- | src/filter/null_filter_plugin.c | 93 | ||||
-rw-r--r-- | src/filter_internal.h | 38 | ||||
-rw-r--r-- | src/filter_plugin.c | 106 | ||||
-rw-r--r-- | src/filter_plugin.h | 145 | ||||
-rw-r--r-- | src/filter_registry.c | 39 | ||||
-rw-r--r-- | src/filter_registry.h | 34 |
7 files changed, 461 insertions, 0 deletions
diff --git a/Makefile.am b/Makefile.am index e51334e6e..0a5a1d505 100644 --- a/Makefile.am +++ b/Makefile.am @@ -42,6 +42,9 @@ mpd_headers = \ src/output_state.h \ src/output_print.h \ src/output_command.h \ + src/filter_internal.h \ + src/filter_plugin.h \ + src/filter_registry.h \ src/buffer2array.h \ src/command.h \ src/idle.h \ @@ -188,6 +191,9 @@ src_mpd_SOURCES = \ src/database.c \ src/dirvec.c \ src/fifo_buffer.c \ + src/filter_plugin.c \ + src/filter_registry.c \ + src/filter/null_filter_plugin.c \ src/update.c \ src/client.c \ src/listen.c \ diff --git a/src/filter/null_filter_plugin.c b/src/filter/null_filter_plugin.c new file mode 100644 index 000000000..689388558 --- /dev/null +++ b/src/filter/null_filter_plugin.c @@ -0,0 +1,93 @@ +/* + * 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. + */ + +/** \file + * + * This filter plugin does nothing. That is not quite useful, except + * for testing the filter core, or as a template for new filter + * plugins. + */ + +#include "filter_plugin.h" +#include "filter_internal.h" +#include "filter_registry.h" + +#include <assert.h> + +struct null_filter { + struct filter filter; +}; + +static struct filter * +null_filter_init(G_GNUC_UNUSED const struct config_param *param, + G_GNUC_UNUSED GError **error_r) +{ + struct null_filter *filter = g_new(struct null_filter, 1); + + filter_init(&filter->filter, &null_filter_plugin); + return &filter->filter; +} + +static void +null_filter_finish(struct filter *_filter) +{ + struct null_filter *filter = (struct null_filter *)_filter; + + g_free(filter); +} + +static const struct audio_format * +null_filter_open(struct filter *_filter, + const struct audio_format *audio_format, + G_GNUC_UNUSED GError **error_r) +{ + struct null_filter *filter = (struct null_filter *)_filter; + (void)filter; + + return audio_format; +} + +static void +null_filter_close(struct filter *_filter) +{ + struct null_filter *filter = (struct null_filter *)_filter; + (void)filter; +} + +static const void * +null_filter_filter(struct filter *_filter, + const void *src, size_t src_size, + size_t *dest_size_r, G_GNUC_UNUSED GError **error_r) +{ + struct null_filter *filter = (struct null_filter *)_filter; + (void)filter; + + /* return the unmodified source buffer */ + *dest_size_r = src_size; + return src; +} + +const struct filter_plugin null_filter_plugin = { + .name = "null", + .init = null_filter_init, + .finish = null_filter_finish, + .open = null_filter_open, + .close = null_filter_close, + .filter = null_filter_filter, +}; diff --git a/src/filter_internal.h b/src/filter_internal.h new file mode 100644 index 000000000..b086e31b1 --- /dev/null +++ b/src/filter_internal.h @@ -0,0 +1,38 @@ +/* + * 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. + */ + +/** \file + * + * Internal stuff for the filter core and filter plugins. + */ + +#ifndef MPD_FILTER_INTERNAL_H +#define MPD_FILTER_INTERNAL_H + +struct filter { + const struct filter_plugin *plugin; +}; + +static inline void +filter_init(struct filter *filter, const struct filter_plugin *plugin) +{ + filter->plugin = plugin; +} + +#endif diff --git a/src/filter_plugin.c b/src/filter_plugin.c new file mode 100644 index 000000000..e5c1d5cd8 --- /dev/null +++ b/src/filter_plugin.c @@ -0,0 +1,106 @@ +/* + * 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_plugin.h" +#include "filter_internal.h" +#include "filter_registry.h" +#include "conf.h" + +#ifndef NDEBUG +#include "audio_format.h" +#endif + +#include <assert.h> + +struct filter * +filter_new(const struct filter_plugin *plugin, + const struct config_param *param, GError **error_r) +{ + assert(plugin != NULL); + assert(error_r == NULL || *error_r == NULL); + + return plugin->init(param, error_r); +} + +struct filter * +filter_configured_new(const struct config_param *param, GError **error_r) +{ + const char *plugin_name; + const struct filter_plugin *plugin; + + assert(param != NULL); + assert(error_r == NULL || *error_r == NULL); + + plugin_name = config_get_block_string(param, "plugin", NULL); + if (plugin_name == NULL) + g_set_error(error_r, config_quark(), 0, + "No filter plugin specified"); + + plugin = filter_plugin_by_name(plugin_name); + if (plugin == NULL) + g_set_error(error_r, config_quark(), 0, + "No such filter plugin: %s", plugin_name); + + return filter_new(plugin, param, error_r); +} + +void +filter_free(struct filter *filter) +{ + assert(filter != NULL); + + filter->plugin->finish(filter); +} + +const struct audio_format * +filter_open(struct filter *filter, const struct audio_format *audio_format, + GError **error_r) +{ + assert(filter != NULL); + assert(audio_format != NULL); + assert(audio_format_valid(audio_format)); + assert(error_r == NULL || *error_r == NULL); + + audio_format = filter->plugin->open(filter, audio_format, error_r); + assert(audio_format == NULL || audio_format_valid(audio_format)); + + return audio_format; +} + +void +filter_close(struct filter *filter) +{ + assert(filter != NULL); + + filter->plugin->close(filter); +} + +const void * +filter_filter(struct filter *filter, const void *src, size_t src_size, + size_t *dest_size_r, + GError **error_r) +{ + assert(filter != NULL); + assert(src != NULL); + assert(src_size > 0); + assert(dest_size_r != NULL); + assert(error_r == NULL || *error_r == NULL); + + return filter->plugin->filter(filter, src, src_size, dest_size_r, error_r); +} diff --git a/src/filter_plugin.h b/src/filter_plugin.h new file mode 100644 index 000000000..0043246d1 --- /dev/null +++ b/src/filter_plugin.h @@ -0,0 +1,145 @@ +/* + * 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. + */ + +/** \file + * + * This header declares the filter_plugin class. It describes a + * plugin API for objects which filter raw PCM data. + */ + +#ifndef MPD_FILTER_PLUGIN_H +#define MPD_FILTER_PLUGIN_H + +#include <glib.h> + +#include <stdbool.h> +#include <stddef.h> + +struct config_param; +struct filter; + +struct filter_plugin { + const char *name; + + /** + * Allocates and configures a filter. + */ + struct filter *(*init)(const struct config_param *param, + GError **error_r); + + /** + * Free instance data. + */ + void (*finish)(struct filter *filter); + + /** + * Opens a filter. + */ + const struct audio_format * + (*open)(struct filter *filter, + const struct audio_format *audio_format, + GError **error_r); + + /** + * Closes a filter. + */ + void (*close)(struct filter *filter); + + /** + * Filters a block of PCM data. + */ + const void *(*filter)(struct filter *filter, + const void *src, size_t src_size, + size_t *dest_buffer_r, + GError **error_r); +}; + +/** + * Creates a new instance of the specified filter plugin. + * + * @param plugin the filter plugin + * @param param optional configuration section + * @param error location to store the error occuring, or NULL to + * ignore errors. + * @return a new filter object, or NULL on error + */ +struct filter * +filter_new(const struct filter_plugin *plugin, + const struct config_param *param, GError **error_r); + +/** + * Creates a new filter, loads configuration and the plugin name from + * the specified configuration section. + * + * @param param the configuration section + * @param error location to store the error occuring, or NULL to + * ignore errors. + * @return a new filter object, or NULL on error + */ +struct filter * +filter_configured_new(const struct config_param *param, GError **error_r); + +/** + * Deletes a filter. It must be closed prior to calling this + * function, see filter_close(). + * + * @param filter the filter object + */ +void +filter_free(struct filter *filter); + +/** + * Opens the filter, preparing it for filter_filter(). + * + * @param filter the filter object + * @param audio_format the audio format of incoming and outgoing data + * @param error location to store the error occuring, or NULL to + * ignore errors. + * @return true on success, false on error + */ +const struct audio_format * +filter_open(struct filter *filter, const struct audio_format *audio_format, + GError **error_r); + +/** + * Closes the filter. After that, you may call filter_open() again. + * + * @param filter the filter object + */ +void +filter_close(struct filter *filter); + +/** + * Filters a block of PCM data. + * + * @param filter the filter object + * @param src the input buffer + * @param src_size the size of #src_buffer in bytes + * @param dest_size_r the size of the returned buffer + * @param error location to store the error occuring, or NULL to + * ignore errors. + * @return the destination buffer on success (will be invalidated by + * filter_close() or filter_filter()), NULL on error + */ +const void * +filter_filter(struct filter *filter, const void *src, size_t src_size, + size_t *dest_size_r, + GError **error_r); + +#endif diff --git a/src/filter_registry.c b/src/filter_registry.c new file mode 100644 index 000000000..90ba6fe1c --- /dev/null +++ b/src/filter_registry.c @@ -0,0 +1,39 @@ +/* + * 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_registry.h" +#include "filter_plugin.h" + +#include <stddef.h> +#include <string.h> + +const struct filter_plugin *const filter_plugins[] = { + &null_filter_plugin, + NULL, +}; + +const struct filter_plugin * +filter_plugin_by_name(const char *name) +{ + for (unsigned i = 0; filter_plugins[i] != NULL; ++i) + if (strcmp(filter_plugins[i]->name, name) == 0) + return filter_plugins[i]; + + return NULL; +} diff --git a/src/filter_registry.h b/src/filter_registry.h new file mode 100644 index 000000000..e5988f96e --- /dev/null +++ b/src/filter_registry.h @@ -0,0 +1,34 @@ +/* + * 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. + */ + +/** \file + * + * This library manages all filter plugins which are enabled at + * compile time. + */ + +#ifndef MPD_FILTER_REGISTRY_H +#define MPD_FILTER_REGISTRY_H + +extern const struct filter_plugin null_filter_plugin; + +const struct filter_plugin * +filter_plugin_by_name(const char *name); + +#endif |