void *receiver_conf;
/** the number of filters that should be activated for this audio format */
unsigned int num_filters;
- /** pointer to the array of filters to be activated */
- struct filter **filters;
- /** pointer to the array of filter configurations */
+ /** Array of filter numbers to be activated. */
+ unsigned *filter_nums;
+ /** Pointer to the array of filter configurations. */
void **filter_conf;
/** the number of filters that should be activated for this audio format */
unsigned int num_writers;
{
struct slot_info *s = &slot[slot_num];
struct audio_format_info *a = &afi[s->format];
+ struct filter_node *fn;
int nf = a->num_filters;
int i;
return;
PARA_INFO_LOG("opening %s filters\n", audio_formats[s->format]);
s->fc = para_calloc(sizeof(struct filter_chain));
- INIT_LIST_HEAD(&s->fc->filters);
+ s->fc->filter_nodes = para_malloc(nf * sizeof(struct filter_chain));
s->fc->inbuf = s->receiver_node->buf;
s->fc->in_loaded = &s->receiver_node->loaded;
s->fc->input_error = &s->receiver_node->task.error;
s->fc->task.pre_select = filter_pre_select;
+ s->fc->task.post_select = NULL;
s->fc->task.error = 0;
+ s->fc->num_filters = nf;
s->receiver_node->output_error = &s->fc->task.error;
sprintf(s->fc->task.status, "filter chain");
- for (i = 0; i < nf; i++) {
- struct filter_node *fn = para_calloc(sizeof(struct filter_node));
+ FOR_EACH_FILTER_NODE(fn, s->fc, i) {
+ struct filter *f = filters + a->filter_nums[i];
+ fn->filter_num = a->filter_nums[i];
fn->conf = a->filter_conf[i];
fn->fc = s->fc;
- fn->filter = a->filters[i];
+ fn->loaded = 0;
INIT_LIST_HEAD(&fn->callbacks);
- list_add_tail(&fn->node, &s->fc->filters);
- fn->filter->open(fn);
+ f->open(fn);
PARA_NOTICE_LOG("%s filter %d/%d (%s) started in slot %d\n",
- audio_formats[s->format], i + 1, nf,
- fn->filter->name, slot_num);
+ audio_formats[s->format], i + 1, nf, f->name, slot_num);
s->fc->outbuf = fn->buf;
s->fc->out_loaded = &fn->loaded;
}
return;
}
s->wstime = *now;
- activate_inactive_grab_clients(slot_num, s->format, &s->fc->filters);
+ activate_inactive_grab_clients(slot_num, s->format, s->fc);
}
#if 0
filter_num = check_filter_arg(cmdline, &a->filter_conf[nf]);
if (filter_num < 0)
return filter_num;
- a->filters[nf] = &filters[filter_num];
+ a->filter_nums[nf] = filter_num;
a->num_filters++;
PARA_INFO_LOG("%s filter %d: %s\n", audio_formats[format], nf + 1,
- a->filters[nf]->name);
+ filters[filter_num].name);
return filter_num;
}
PARA_INFO_LOG("maximal number of filters: %d\n", nf);
FOR_EACH_AUDIO_FORMAT(i) {
afi[i].filter_conf = para_malloc(nf * sizeof(void *));
- afi[i].filters = para_malloc(nf * sizeof(struct filter *));
+ afi[i].filter_nums = para_malloc(nf * sizeof(unsigned));
}
if (!conf.no_default_filters_given)
return init_default_filters();
continue;
/* success */
j = 1;
- list_for_each_entry(fn, &s->fc->filters, node)
+ FOR_EACH_FILTER_NODE(fn, s->fc, j) {
if (filternum <= 0 || j++ == filternum)
break;
+ }
return fn;
}
return NULL;
static void open_filters(void)
{
+ int i;
struct filter_node *fn;
- list_for_each_entry(fn, &fc->filters, node) {
- fn->filter->open(fn);
- PARA_INFO_LOG("opened %s filter\n", fn->filter->name);
+ FOR_EACH_FILTER_NODE(fn, fc, i) {
+ struct filter *f = filters + fn->filter_num;
+ f->open(fn);
+ PARA_INFO_LOG("opened %s filter\n", f->name);
fc->outbuf = fn->buf;
fc->out_loaded = &fn->loaded;
}
static int init_filter_chain(void)
{
- int i, filter_num;
+ int i, ret;
struct filter_node *fn;
- INIT_LIST_HEAD(&fc->filters);
-
+ if (!conf.filter_given)
+ return -E_NO_FILTERS;
+ fc->num_filters = conf.filter_given;
+ fc->filter_nodes = para_malloc(fc->num_filters * sizeof(struct filter_node));
fc->inbuf = sit->buf;
fc->in_loaded = &sit->loaded;
fc->input_error = &sit->task.error;
fc->task.pre_select = filter_pre_select;
sprintf(fc->task.status, "filter chain");
- for (i = 0; i < conf.filter_given; i++) {
+ FOR_EACH_FILTER_NODE(fn, fc, i) {
char *fa = conf.filter_arg[i];
- fn = para_calloc(sizeof(struct filter_node));
- filter_num = check_filter_arg(fa, &fn->conf);
- if (filter_num < 0) {
- free(fn);
- return filter_num;
- }
+ fn = fc->filter_nodes + i;
+ ret = check_filter_arg(fa, &fn->conf);
+ if (ret < 0)
+ return ret;
+ fn->filter_num = ret;
fn->fc = fc;
INIT_LIST_HEAD(&fn->callbacks);
- fn->filter = &filters[filter_num];
- PARA_DEBUG_LOG("adding %s to filter chain\n", fn->filter->name);
- list_add_tail(&fn->node, &fc->filters);
+ PARA_DEBUG_LOG("filter #%d: %s\n", i, filters[fn->filter_num].name);
}
- if (list_empty(&fc->filters))
- return -E_NO_FILTERS;
open_filters();
return 1;
}
/** \file filter.h Filter-related structures and exported symbols from filter_chain.c. */
+
+/**
+ * Describes one running instance of a filter.
+*/
+struct filter_node {
+ /** The number in the array of available filters. */
+ unsigned filter_num;
+ /** The filter chain this filter node belongs to. */
+ struct filter_chain *fc;
+ /**
+ * Each filter may store any filter-specific information about the particular
+ * instance of the filter here.
+ */
+ void *private_data;
+ /** The output buffer. */
+ char *buf;
+ /** The size of the output buffer. */
+ size_t bufsize;
+ /** The number of bytes currently loaded in \a buf. */
+ size_t loaded;
+ /** The list of registered callbacks. */
+ struct list_head callbacks;
+ /** A pointer to the configuration of this instance. */
+ void *conf;
+};
+
/** Describes one running instance of a chain of filters */
struct filter_chain {
+ unsigned int num_filters;
/**
* The number of channels of the current stream.
*
*/
unsigned int samplerate;
/** The list containing all filter nodes in this filter chain. */
- struct list_head filters;
+ struct filter_node *filter_nodes;
/**
* The input buffer of the filter chain.
*
struct task task;
};
-/**
- * Describes one running instance of a filter.
-*/
-struct filter_node {
- /** A pointer to the corresponding filter struct. */
- struct filter *filter;
- /** The filter chain this filter node belongs to. */
- struct filter_chain *fc;
- /**
- * The position of the filter in the corresponding filter chain.
- *
- * All filters that make up the filter chains are organized in a doubly
- * linked list.
- */
- struct list_head node;
- /**
- * Each filter may store any filter-specific information about the particular
- * instance of the filter here.
- */
- void *private_data;
- /** The output buffer. */
- char *buf;
- /** The size of the output buffer. */
- size_t bufsize;
- /** The number of bytes currently loaded in \a buf. */
- size_t loaded;
- /** The list of registered callbacks. */
- struct list_head callbacks;
- /** A pointer to the configuration of this instance. */
- void *conf;
-};
+#define FOR_EACH_FILTER_NODE(fn, fc, i) for (i = 0; i < (fc)->num_filters \
+ && (fn = (fc)->filter_nodes + i); i++)
+
/**
* Used to manage grab clients.
};
-void close_filters(struct filter_chain *fc);
-void filter_init(struct filter *all_filters);
-int check_filter_arg(char *filter_arg, void **conf);
-void filter_pre_select(__a_unused struct sched *s, struct task *t);
-
/**
* The structure associated with a paraslash filter.
*
void *(*parse_config)(int argc, char **argv);
};
+void close_filters(struct filter_chain *fc);
+void filter_init(struct filter *all_filters);
+int check_filter_arg(char *filter_arg, void **conf);
+void filter_pre_select(__a_unused struct sched *s, struct task *t);
+
static inline void write_int16_host_endian(char *buf, int val)
{
list_for_each_entry_safe(fcb, tmp, &fn->callbacks, node) {
PARA_INFO_LOG("closing %s filter callback\n",
- fn->filter->name);
+ filters[fn->filter_num].name);
close_filter_callback(fcb);
}
}
struct filter_node *fn;
char *ib;
size_t *loaded;
- int conv, conv_total = 0;
+ int i, conv, conv_total = 0;
if (fc->output_error && *fc->output_error < 0) {
t->error = *fc->output_error;
ib = fc->inbuf;
loaded = fc->in_loaded;
conv = 0;
- list_for_each_entry(fn, &fc->filters, node) {
+ FOR_EACH_FILTER_NODE(fn, fc, i) {
+ struct filter *f = filters + fn->filter_num;
if (*loaded && fn->loaded < fn->bufsize) {
size_t size, old_fn_loaded = fn->loaded;
// PARA_DEBUG_LOG("fc %p loaded: %zd, calling %s convert\n",
// fc, *loaded, fn->filter->name);
- t->error = fn->filter->convert(ib, *loaded, fn);
+ t->error = f->convert(ib, *loaded, fn);
if (t->error < 0)
return;
size = t->error;
*/
void close_filters(struct filter_chain *fc)
{
- struct filter_node *fn, *tmp;
+ struct filter_node *fn;
+ int i;
if (!fc)
return;
PARA_NOTICE_LOG("closing filter chain %p\n", fc);
- list_for_each_entry_safe(fn, tmp, &fc->filters, node) {
+ FOR_EACH_FILTER_NODE(fn, fc, i) {
+ struct filter *f = filters + fn->filter_num;
close_callbacks(fn);
- PARA_INFO_LOG("closing %s filter\n", fn->filter->name);
- fn->filter->close(fn);
- list_del(&fn->node);
- free(fn);
+ PARA_INFO_LOG("closing %s filter\n", f->name);
+ f->close(fn);
}
+ free(fc->filter_nodes);
}
/*
* activate_grab_client.
*/
void activate_inactive_grab_clients(int slot_num, int audio_format_num,
- struct list_head *filter_list)
+ struct filter_chain *fc)
{
struct grab_client *gc, *tmp;
int i;
num_filters(gc->audio_format_num)
< gc->conf->filter_num_arg)
continue;
- i = 1;
- list_for_each_entry(fn, filter_list, node) {
+ FOR_EACH_FILTER_NODE(fn, fc, i) {
if (gc->conf->filter_num_arg <= 0
- || i == gc->conf->filter_num_arg)
+ || i == gc->conf->filter_num_arg + 1)
break;
- i++;
}
activate_grab_client(gc, fn);
}
};
__malloc struct grab_client *grab_client_new(int fd, char *line, int *err);
-void activate_inactive_grab_clients(int slot, int audio_format_num, struct list_head *filter_list);
+void activate_inactive_grab_clients(int slot_num, int audio_format_num,
+ struct filter_chain *fc);
void activate_grab_client(struct grab_client *gc, struct filter_node *fn);
void init_grabbing(void);