aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMax Kellermann <max@duempel.org>2009-12-25 14:27:32 +0100
committerMax Kellermann <max@duempel.org>2009-12-25 17:29:41 +0100
commitb54bde6f2b9f826cd7189182d733aada66c95dd8 (patch)
treef07f7b57f0d83879e6aa35ba3bbdaa06b4cbf4f1
parentd2051c7f50deff0532566c070aaf4fec5d774558 (diff)
downloadmpd-b54bde6f2b9f826cd7189182d733aada66c95dd8.tar.gz
mpd-b54bde6f2b9f826cd7189182d733aada66c95dd8.tar.xz
mpd-b54bde6f2b9f826cd7189182d733aada66c95dd8.zip
filter_plugin: allow open() to force an input format
Make the audio_format argument non-const. Allow the open() method to modify it, to indicate that it wants a different input audio format than the one specified. Check that condition in chain_filter_open(), and fail.
-rw-r--r--src/filter/chain_filter_plugin.c39
-rw-r--r--src/filter/convert_filter_plugin.c5
-rw-r--r--src/filter/normalize_filter_plugin.c18
-rw-r--r--src/filter/null_filter_plugin.c3
-rw-r--r--src/filter/route_filter_plugin.c3
-rw-r--r--src/filter/volume_filter_plugin.c12
-rw-r--r--src/filter_plugin.c13
-rw-r--r--src/filter_plugin.h11
8 files changed, 64 insertions, 40 deletions
diff --git a/src/filter/chain_filter_plugin.c b/src/filter/chain_filter_plugin.c
index edfa70f35..56fa3a5e1 100644
--- a/src/filter/chain_filter_plugin.c
+++ b/src/filter/chain_filter_plugin.c
@@ -23,6 +23,7 @@
#include "filter_plugin.h"
#include "filter_internal.h"
#include "filter_registry.h"
+#include "audio_format.h"
#include <assert.h>
@@ -33,6 +34,12 @@ struct filter_chain {
GSList *children;
};
+static inline GQuark
+filter_quark(void)
+{
+ return g_quark_from_static_string("filter");
+}
+
static struct filter *
chain_filter_init(G_GNUC_UNUSED const struct config_param *param,
G_GNUC_UNUSED GError **error_r)
@@ -92,16 +99,42 @@ chain_close_until(struct filter_chain *chain, const struct filter *until)
}
static const struct audio_format *
-chain_filter_open(struct filter *_filter,
- const struct audio_format *audio_format,
+chain_open_child(struct filter *filter,
+ const struct audio_format *prev_audio_format,
+ GError **error_r)
+{
+ struct audio_format conv_audio_format = *prev_audio_format;
+ const struct audio_format *next_audio_format;
+
+ next_audio_format = filter_open(filter, &conv_audio_format, error_r);
+ if (next_audio_format == NULL)
+ return NULL;
+
+ if (!audio_format_equals(&conv_audio_format, prev_audio_format)) {
+ struct audio_format_string s;
+
+ filter_close(filter);
+ g_set_error(error_r, filter_quark(), 0,
+ "Audio format not supported by filter '%s': %s",
+ filter->plugin->name,
+ audio_format_to_string(prev_audio_format, &s));
+ return NULL;
+ }
+
+ return next_audio_format;
+}
+
+static const struct audio_format *
+chain_filter_open(struct filter *_filter, struct audio_format *in_audio_format,
GError **error_r)
{
struct filter_chain *chain = (struct filter_chain *)_filter;
+ const struct audio_format *audio_format = in_audio_format;
for (GSList *i = chain->children; i != NULL; i = g_slist_next(i)) {
struct filter *filter = i->data;
- audio_format = filter_open(filter, audio_format, error_r);
+ audio_format = chain_open_child(filter, audio_format, error_r);
if (audio_format == NULL) {
/* rollback, close all children */
chain_close_until(chain, filter);
diff --git a/src/filter/convert_filter_plugin.c b/src/filter/convert_filter_plugin.c
index 982ec7c4c..87070fa3a 100644
--- a/src/filter/convert_filter_plugin.c
+++ b/src/filter/convert_filter_plugin.c
@@ -71,8 +71,7 @@ convert_filter_finish(struct filter *filter)
}
static const struct audio_format *
-convert_filter_open(struct filter *_filter,
- const struct audio_format *audio_format,
+convert_filter_open(struct filter *_filter, struct audio_format *audio_format,
G_GNUC_UNUSED GError **error_r)
{
struct convert_filter *filter = (struct convert_filter *)_filter;
@@ -82,7 +81,7 @@ convert_filter_open(struct filter *_filter,
filter->in_audio_format = filter->out_audio_format = *audio_format;
pcm_convert_init(&filter->state);
- return audio_format;
+ return &filter->in_audio_format;
}
static void
diff --git a/src/filter/normalize_filter_plugin.c b/src/filter/normalize_filter_plugin.c
index 2694646ee..4a8bde51d 100644
--- a/src/filter/normalize_filter_plugin.c
+++ b/src/filter/normalize_filter_plugin.c
@@ -61,23 +61,13 @@ normalize_filter_finish(struct filter *filter)
static const struct audio_format *
normalize_filter_open(struct filter *_filter,
- const struct audio_format *audio_format,
- GError **error_r)
+ struct audio_format *audio_format,
+ G_GNUC_UNUSED GError **error_r)
{
struct normalize_filter *filter = (struct normalize_filter *)_filter;
- if (audio_format->format != SAMPLE_FORMAT_S16) {
- g_set_error(error_r, normalize_quark(), 0,
- "Unsupported audio format");
- return false;
- }
-
- if (audio_format->reverse_endian) {
- g_set_error(error_r, normalize_quark(), 0,
- "Normalize for reverse endian "
- "samples is not implemented");
- return false;
- }
+ audio_format->format = SAMPLE_FORMAT_S16;
+ audio_format->reverse_endian = false;
filter->compressor = Compressor_new(0);
diff --git a/src/filter/null_filter_plugin.c b/src/filter/null_filter_plugin.c
index 5671ba907..d677780dc 100644
--- a/src/filter/null_filter_plugin.c
+++ b/src/filter/null_filter_plugin.c
@@ -54,8 +54,7 @@ null_filter_finish(struct filter *_filter)
}
static const struct audio_format *
-null_filter_open(struct filter *_filter,
- const struct audio_format *audio_format,
+null_filter_open(struct filter *_filter, struct audio_format *audio_format,
G_GNUC_UNUSED GError **error_r)
{
struct null_filter *filter = (struct null_filter *)_filter;
diff --git a/src/filter/route_filter_plugin.c b/src/filter/route_filter_plugin.c
index 7fef2bc12..d9ca149c8 100644
--- a/src/filter/route_filter_plugin.c
+++ b/src/filter/route_filter_plugin.c
@@ -248,8 +248,7 @@ route_filter_finish(struct filter *_filter)
}
static const struct audio_format *
-route_filter_open(struct filter *_filter,
- const struct audio_format *audio_format,
+route_filter_open(struct filter *_filter, struct audio_format *audio_format,
G_GNUC_UNUSED GError **error_r)
{
struct route_filter *filter = (struct route_filter *)_filter;
diff --git a/src/filter/volume_filter_plugin.c b/src/filter/volume_filter_plugin.c
index 11549784f..82eed3acc 100644
--- a/src/filter/volume_filter_plugin.c
+++ b/src/filter/volume_filter_plugin.c
@@ -69,18 +69,12 @@ volume_filter_finish(struct filter *filter)
}
static const struct audio_format *
-volume_filter_open(struct filter *_filter,
- const struct audio_format *audio_format,
- GError **error_r)
+volume_filter_open(struct filter *_filter, struct audio_format *audio_format,
+ G_GNUC_UNUSED GError **error_r)
{
struct volume_filter *filter = (struct volume_filter *)_filter;
- if (audio_format->reverse_endian) {
- g_set_error(error_r, volume_quark(), 0,
- "Software volume for reverse endian "
- "samples is not implemented");
- return false;
- }
+ audio_format->reverse_endian = false;
filter->audio_format = *audio_format;
pcm_buffer_init(&filter->buffer);
diff --git a/src/filter_plugin.c b/src/filter_plugin.c
index ecc4b5432..21cb2f277 100644
--- a/src/filter_plugin.c
+++ b/src/filter_plugin.c
@@ -74,18 +74,23 @@ filter_free(struct filter *filter)
}
const struct audio_format *
-filter_open(struct filter *filter, const struct audio_format *audio_format,
+filter_open(struct filter *filter, struct audio_format *audio_format,
GError **error_r)
{
+ const struct audio_format *out_audio_format;
+
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));
+ out_audio_format = filter->plugin->open(filter, audio_format, error_r);
+
+ assert(out_audio_format == NULL || audio_format_valid(audio_format));
+ assert(out_audio_format == NULL ||
+ audio_format_valid(out_audio_format));
- return audio_format;
+ return out_audio_format;
}
void
diff --git a/src/filter_plugin.h b/src/filter_plugin.h
index dc5903b59..cec15794f 100644
--- a/src/filter_plugin.h
+++ b/src/filter_plugin.h
@@ -50,10 +50,14 @@ struct filter_plugin {
/**
* Opens a filter.
+ *
+ * @param audio_format the audio format of incoming data; the
+ * plugin may modify the object to enforce another input
+ * format
*/
const struct audio_format *
(*open)(struct filter *filter,
- const struct audio_format *audio_format,
+ struct audio_format *audio_format,
GError **error_r);
/**
@@ -108,13 +112,14 @@ 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 data
+ * @param audio_format the audio format of incoming data; the plugin
+ * may modify the object to enforce another input format
* @param error location to store the error occuring, or NULL to
* ignore errors.
* @return the format of outgoing data
*/
const struct audio_format *
-filter_open(struct filter *filter, const struct audio_format *audio_format,
+filter_open(struct filter *filter, struct audio_format *audio_format,
GError **error_r);
/**