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:
parent
d2051c7f50
commit
b54bde6f2b
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user