+ sl = slot + ret;
+ a = afi + sl->format;
+ if (a->num_filters)
+ open_filters(sl);
+ open_writers(sl);
+ activate_grab_clients();
+ btr_log_tree(sl->receiver_node->btrn, LL_NOTICE);
+}
+
+static void status_pre_select(struct sched *s, struct task *t)
+{
+ struct status_task *st = container_of(t, struct status_task, task);
+ int ret, cafn = stat_task->current_audio_format_num;
+
+ if (must_start_decoder())
+ goto min_delay;
+ ret = btr_node_status(st->btrn, 0, BTR_NT_LEAF);
+ if (ret > 0)
+ goto min_delay;
+ if (st->ct && audiod_status == AUDIOD_OFF)
+ goto min_delay;
+ if (!st->ct && audiod_status != AUDIOD_OFF)
+ sched_request_barrier_or_min_delay(&st->restart_barrier, s);
+ if (cafn >= 0)
+ sched_request_barrier(&afi[cafn].restart_barrier, s);
+ /*
+ * If para_server is playing we'd like to have a smooth time display
+ * even if we are running in standby mode. So we request a timeout that
+ * expires at the next full second.
+ */
+ if (stat_task->vss_status & VSS_STATUS_FLAG_PLAYING)
+ sched_request_timeout_ms(1000 - now->tv_usec / 1000, s);
+ return;
+min_delay:
+ sched_min_delay(s);
+}
+
+/* restart the client task if necessary */
+static void status_post_select(__a_unused 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) {
+ kill_btrn(st->ct->btrn, &st->ct->task, -E_AUDIOD_OFF);
+ goto out;
+ }
+ if (st->ct->task.error >= 0)
+ goto out;
+ close_stat_pipe();
+ st->clock_diff_count = conf.clock_diff_count_arg;
+ goto out;
+ }
+ if (st->ct) {
+ char *buf;
+ size_t sz;
+ int ret;
+ if (st->ct->task.error < 0) {
+ if (st->ct->task.error >= 0)
+ goto out;
+ close_stat_pipe();
+ goto out;
+ }
+ if (st->ct->status != CL_RECEIVING)
+ goto out;
+ ret = btr_node_status(st->btrn, st->min_iqs, BTR_NT_LEAF);
+ if (ret <= 0) {
+ struct timeval diff;
+ tv_diff(now, &st->last_status_read, &diff);
+ if (diff.tv_sec > 61)
+ kill_btrn(st->ct->btrn, &st->ct->task,
+ -E_STATUS_TIMEOUT);
+ goto out;
+ }
+ btr_merge(st->btrn, st->min_iqs);
+ sz = btr_next_buffer(st->btrn, &buf);
+ ret = for_each_stat_item(buf, sz, update_item);
+ if (ret < 0) {
+ kill_btrn(st->ct->btrn, &st->ct->task, ret);
+ goto out;
+ }
+ if (sz != ret) {
+ btr_consume(st->btrn, sz - ret);
+ st->last_status_read = *now;
+ st->min_iqs = 0;
+ } else /* current status item crosses buffers */
+ st->min_iqs = sz + 1;
+ goto out;
+ }
+ btr_drain(st->btrn);
+ st->current_audio_format_num = -1;
+ 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", "-p", "-n=1", NULL};
+ int argc = 5;
+ PARA_INFO_LOG("clock diff count: %d\n", st->clock_diff_count);
+ st->clock_diff_count--;
+ client_open(argc, argv, &st->ct, NULL, NULL, st->btrn);
+ set_stat_task_restart_barrier(2);
+
+ } else {
+ char *argv[] = {"audiod", "--", "stat", "-p", NULL};
+ int argc = 4;
+ client_open(argc, argv, &st->ct, NULL, NULL, st->btrn);
+ set_stat_task_restart_barrier(5);
+ }
+ free(stat_item_values[SI_BASENAME]);
+ stat_item_values[SI_BASENAME] = para_strdup(
+ "no connection to para_server");
+ stat_client_write_item(SI_BASENAME);
+ st->last_status_read = *now;
+out:
+ start_stop_decoders();