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.
This commit is contained in:
Max Kellermann 2009-12-25 14:27:32 +01:00
parent d2051c7f50
commit b54bde6f2b
8 changed files with 64 additions and 40 deletions

View File

@ -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);

View File

@ -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

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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);
return audio_format;
assert(out_audio_format == NULL || audio_format_valid(audio_format));
assert(out_audio_format == NULL ||
audio_format_valid(out_audio_format));
return out_audio_format;
}
void

View File

@ -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);
/**