filter: Switch from linked lists to arrays.
authorAndre Noll <maan@systemlinux.org>
Mon, 31 Mar 2008 22:23:58 +0000 (00:23 +0200)
committerAndre Noll <maan@systemlinux.org>
Mon, 31 Mar 2008 22:23:58 +0000 (00:23 +0200)
The number of filters is known and never changes, so it's easier
to use arrays.

audiod.c
audiod_command.c
filter.c
filter.h
filter_chain.c
grab_client.c
grab_client.h

index e33f738..a76ee1f 100644 (file)
--- a/audiod.c
+++ b/audiod.c
@@ -41,9 +41,9 @@ struct audio_format_info {
        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;
@@ -268,6 +268,7 @@ static void open_filters(int slot_num)
 {
        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;
 
@@ -276,26 +277,27 @@ static void open_filters(int slot_num)
                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;
        }
@@ -336,7 +338,7 @@ static void open_writers(int slot_num)
                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
@@ -651,10 +653,10 @@ static int add_filter(int format, char *cmdline)
        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;
 }
 
@@ -786,7 +788,7 @@ static int init_filters(void)
        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();
index 875e455..0428bea 100644 (file)
@@ -294,9 +294,10 @@ static struct filter_node *find_filter_node(int slot_num, int format, int filter
                        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;
index 68c97b4..81d5df1 100644 (file)
--- a/filter.c
+++ b/filter.c
@@ -41,11 +41,13 @@ INIT_STDERR_LOGGING(conf.loglevel_arg);
 
 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;
        }
@@ -53,11 +55,13 @@ static void open_filters(void)
 
 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;
@@ -66,22 +70,17 @@ static int init_filter_chain(void)
        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;
 }
index 5cb7aaf..1b916ee 100644 (file)
--- a/filter.h
+++ b/filter.h
@@ -6,8 +6,35 @@
 
 /** \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.
         *
@@ -21,7 +48,7 @@ struct filter_chain {
         */
        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.
         *
@@ -48,37 +75,9 @@ struct 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.
@@ -130,11 +129,6 @@ struct filter_callback {
 };
 
 
-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.
  *
@@ -206,6 +200,11 @@ struct 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)
 {
index 9755392..798d58e 100644 (file)
@@ -62,7 +62,7 @@ static void close_callbacks(struct filter_node *fn)
 
        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);
        }
 }
@@ -113,7 +113,7 @@ void filter_pre_select(__a_unused struct sched *s, struct task *t)
        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;
@@ -123,12 +123,13 @@ again:
        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;
@@ -176,18 +177,19 @@ again:
  */
 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);
 }
 
 /*
index a3db5c6..e348ea2 100644 (file)
@@ -176,7 +176,7 @@ void activate_grab_client(struct grab_client *gc, struct filter_node *fn)
  * 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;
@@ -193,12 +193,10 @@ void activate_inactive_grab_clients(int slot_num, int audio_format_num,
                                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);
        }
index 9550afb..2832f09 100644 (file)
@@ -43,6 +43,7 @@ struct grab_client {
 };
 
 __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);