+ if (s->wng && s->wng->task.error != -E_TASK_UNREGISTERED)
+ return;
+ PARA_INFO_LOG("closing slot %d\n", slot_num);
+ wng_close(s->wng);
+ close_filters(s->fc);
+ free(s->fc);
+ close_receiver(slot_num);
+ clear_slot(slot_num);
+}
+
+/*
+ * Check if any receivers/filters/writers need to be started and do so if
+ * necessary.
+ */
+static void start_stop_decoders(struct sched *s)
+{
+ int i;
+
+ FOR_EACH_SLOT(i)
+ try_to_close_slot(i);
+ if (audiod_status != AUDIOD_ON || !stat_task->playing)
+ return kill_all_decoders(-E_NOT_PLAYING);
+ open_current_receiver(s);
+ FOR_EACH_SLOT(i) {
+ struct slot_info *sl = &slot[i];
+ struct audio_format_info *a;
+ struct timeval diff;
+
+ if (sl->format < 0)
+ continue;
+ a = &afi[sl->format];
+ if (!sl->receiver_node)
+ continue;
+ if ((!a->num_filters || sl->fc) && sl->wng)
+ continue; /* everything already started */
+ if (!a->num_filters) {
+ if (sl->receiver_node->loaded && !sl->wng) {
+ open_writers(i);
+ }
+ continue;
+ }
+ if (sl->receiver_node->loaded && !sl->fc) {
+ open_filters(i);
+ continue;
+ }
+ if (sl->wng || !sl->fc || !*sl->fc->out_loaded)
+ continue;
+ if (tv_diff(now, &initial_delay_barrier, &diff) > 0) {
+ open_writers(i);
+ continue;
+ }
+ PARA_INFO_LOG("initial delay: %lu ms left\n", tv2ms(&diff));
+ if (tv_diff(&s->timeout, &diff, NULL) > 0) {
+ s->timeout = diff;
+ }
+ }
+}
+
+
+/* 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);
+
+ if (audiod_status == AUDIOD_OFF) {
+ if (!st->ct)
+ goto out;
+ if (st->ct->task.error >= 0) {
+ st->ct->task.error = -E_AUDIOD_OFF;
+ goto out;
+ }
+ if (st->ct->task.error != -E_TASK_UNREGISTERED)
+ goto out;
+ close_stat_pipe();
+ st->clock_diff_count = conf.clock_diff_count_arg;
+ goto out;
+ }
+ if (st->ct) {
+ unsigned bytes_left;
+ if (st->ct->task.error < 0) {
+ if (st->ct->task.error != -E_TASK_UNREGISTERED)
+ goto out;
+ close_stat_pipe();
+ goto out;
+ }
+ if (st->ct->status != CL_RECEIVING)
+ goto out;
+ 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;
+ }
+ goto out;
+ }
+ if (tv_diff(now, &st->restart_barrier, NULL) < 0)
+ goto out;
+ if (st->clock_diff_count) { /* get status only one time */
+ char *argv[] = {"audiod", "stat", "1", NULL};
+ int argc = 3;
+ PARA_INFO_LOG("clock diff count: %d\n", st->clock_diff_count);
+ 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;
+ client_open(argc, argv, &st->ct);
+ set_stat_task_restart_barrier(5);
+ }
+ free(stat_item_values[SI_BASENAME]);
+ stat_item_values[SI_BASENAME] = make_message(
+ "%s: no connection to para_server\n",
+ status_item_list[SI_BASENAME]);
+ stat_client_write(stat_item_values[SI_BASENAME],
+ SI_BASENAME);
+ st->last_status_read = *now;
+out:
+ start_stop_decoders(s);