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;
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;
}
}
{
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
struct timeval tv = {sec, usec};
compute_time_diff(&tv);
}
- if (stat_task->clock_diff_count)
- stat_task->clock_diff_count--;
break;
case SI_FORMAT:
stat_task->current_audio_format_num = get_audio_format_num(
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();
status_item_list[SI_BASENAME]);
stat_client_write(stat_task->stat_item_values[SI_BASENAME],
SI_BASENAME);
- if (stat_task->clock_diff_count) {
- stat_task->clock_diff_barrier.tv_sec = now->tv_sec + 1;
- stat_task->clock_diff_barrier.tv_usec = now->tv_usec;
- }
}
/**
}
/* avoid busy loop if server is down */
-static void set_stat_task_restart_barrier(void)
+static void set_stat_task_restart_barrier(unsigned seconds)
{
- struct timeval delay = {5, 0};
+ struct timeval delay = {seconds, 0};
tv_add(now, &delay, &stat_task->restart_barrier);
}
/* restart the client task if necessary */
-static void status_pre_select(struct sched *s, struct task *t)
+static void status_pre_select(__a_unused 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) /* no need to restart */
+ if (audiod_status == AUDIOD_OFF) {
+ if (!st->ct)
+ return;
+ if (st->ct->task.error >= 0) {
+ st->ct->task.error = -E_AUDIOD_OFF;
+ return;
+ }
+ if (st->ct->task.error != -E_TASK_UNREGISTERED)
+ return;
+ close_stat_pipe();
+ st->clock_diff_count = conf.clock_diff_count_arg;
+ return;
+ }
+ if (st->ct) {
+ unsigned bytes_left;
+ if (st->ct->task.error < 0) {
+ if (st->ct->task.error != -E_TASK_UNREGISTERED)
+ return;
+ close_stat_pipe();
+ return;
+ }
+ if (st->ct->status != CL_RECEIVING)
+ return;
+ bytes_left = for_each_line(st->ct->buf, st->ct->loaded,
+ &check_stat_line, NULL);
+ if (st->ct->loaded != bytes_left) {
+ st->last_status_read = *now;
+ st->ct->loaded = bytes_left;
+ } else {
+ struct timeval diff;
+ tv_diff(now, &st->last_status_read, &diff);
+ if (diff.tv_sec > 61)
+ st->ct->task.error = -E_STATUS_TIMEOUT;
+ }
return;
- if (!st->clock_diff_count && tv_diff(now, &st->restart_barrier, NULL)
- < 0)
+ }
+ if (tv_diff(now, &st->restart_barrier, NULL) < 0)
return;
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)
- return;
PARA_INFO_LOG("clock diff count: %d\n", st->clock_diff_count);
- ret = client_open(argc, argv, &st->ct);
+ st->clock_diff_count--;
+ client_open(argc, argv, &st->ct);
+ set_stat_task_restart_barrier(2);
} else {
char *argv[] = {"audiod", "stat", NULL};
int argc = 2;
- ret = client_open(argc, argv, &st->ct);
- }
- set_stat_task_restart_barrier();
- if (ret < 0)
- return;
- s->timeout.tv_sec = 0;
- s->timeout.tv_usec = 1;
-}
-
-static void status_post_select(__a_unused struct sched *s, struct task *t)
-{
- struct status_task *st = container_of(t, struct status_task, task);
- unsigned bytes_left;
-
- if (!st->ct || st->ct->status != CL_RECEIVING)
- return;
- 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();
- return;
- }
- bytes_left = for_each_line(st->ct->buf, st->ct->loaded,
- &check_stat_line, NULL);
- if (st->ct->loaded != bytes_left) {
- st->last_status_read = *now;
- st->ct->loaded = bytes_left;
- } else {
- struct timeval diff;
- tv_diff(now, &st->last_status_read, &diff);
- if (diff.tv_sec > 61)
- close_stat_pipe();
+ client_open(argc, argv, &st->ct);
+ set_stat_task_restart_barrier(5);
}
+ st->last_status_read = *now;
}
static void init_status_task(struct status_task *st)
{
memset(st, 0, sizeof(struct status_task));
st->task.pre_select = status_pre_select;
- st->task.post_select = status_post_select;
st->sa_time_diff_sign = 1;
st->clock_diff_count = conf.clock_diff_count_arg;
st->current_audio_format_num = -1;