audiod: Don't unregister tasks, just set the error value.
[paraslash.git] / audiod.c
index bde2b1e1299a51548b727c13c2d32df760067fda..d3f45ec95f32b046910903af1f57351a5cb1998d 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;
@@ -212,20 +212,17 @@ static void kill_all_decoders(int error)
 
        FOR_EACH_SLOT(i) {
                struct slot_info *s = &slot[i];
-               if (s->wng && !s->wng->task.error) {
-                       PARA_INFO_LOG("unregistering writer node group in slot %d\n",
+               if (s->wng && s->wng->task.error >= 0) {
+                       PARA_INFO_LOG("deactivating wng in slot %d\n",
                                i);
-                       wng_unregister(s->wng);
                        s->wng->task.error = error;
                }
-               if (s->fc && !s->fc->task.error) {
-                       PARA_INFO_LOG("unregistering filter chain in slot %d\n", i);
-                       unregister_task(&s->fc->task);
+               if (s->fc && s->fc->task.error >= 0) {
+                       PARA_INFO_LOG("deactivatimg filter chain in slot %d\n", i);
                        s->fc->task.error = error;
                }
-               if (s->receiver_node && !s->receiver_node->task.error) {
-                       PARA_INFO_LOG("unregistering receiver_node in slot %d\n", i);
-                       unregister_task(&s->receiver_node->task);
+               if (s->receiver_node && s->receiver_node->task.error >= 0) {
+                       PARA_INFO_LOG("deactivating receiver_node in slot %d\n", i);
                        s->receiver_node->task.error = error;
                }
        }
@@ -268,6 +265,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 +274,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 +335,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 +650,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 +785,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();
@@ -976,34 +975,18 @@ static void set_stat_task_restart_barrier(void)
        tv_add(now, &delay, &stat_task->restart_barrier);
 }
 
-#if 0
-static void client_task_event_handler(__a_unused struct task *t)
-{
-       int i;
-
-       if (t->ret == -E_HANDSHAKE_COMPLETE)
-               return;
-       unregister_task(t);
-       close_stat_pipe();
-       if (t->ret != -E_SERVER_EOF)
-               stat_task->clock_diff_count = conf.clock_diff_count_arg;
-       set_stat_task_restart_barrier();
-       FOR_EACH_AUDIO_FORMAT(i)
-               afi[i].restart_barrier = stat_task->restart_barrier;
-}
-#endif
-
+/* restart the client task if necessary */
 static void status_pre_select(struct sched *s, struct task *t)
 {
        struct status_task *st = container_of(t, struct status_task, task);
        int ret;
 
-       if (st->ct || audiod_status == AUDIOD_OFF)
+       if (st->ct || audiod_status == AUDIOD_OFF) /* no need to restart */
                return;
        if (!st->clock_diff_count && tv_diff(now, &st->restart_barrier, NULL)
                        < 0)
                return;
-       if (st->clock_diff_count) {
+       if (st->clock_diff_count) { /* get status only one time */
                char *argv[] = {"audiod", "stat", "1", NULL};
                int argc = 3;
                if (tv_diff(now, &st->clock_diff_barrier, NULL) < 0)
@@ -1030,10 +1013,12 @@ static void status_post_select(__a_unused struct sched *s, struct task *t)
 
        if (!st->ct || st->ct->status != CL_RECEIVING)
                return;
-       if (st->ct && audiod_status == AUDIOD_OFF) {
-               unregister_task(&st->ct->task);
+       if (audiod_status == AUDIOD_OFF || st->ct->task.error < 0) {
+               if (st->ct->task.error >= 0)
+                       unregister_task(&st->ct->task);
+               if (audiod_status == AUDIOD_OFF)
+                       st->clock_diff_count = conf.clock_diff_count_arg;
                close_stat_pipe();
-               st->clock_diff_count = conf.clock_diff_count_arg;
                return;
        }
        bytes_left = for_each_line(st->ct->buf, st->ct->loaded,