-static void open_receiver(int format)
-{
- struct audio_format_info *a = &afi[format];
- struct slot_info *s;
- int ret, slot_num;
- struct receiver_node *rn;
-
- slot_num = get_empty_slot();
- if (slot_num < 0)
- clean_exit(EXIT_FAILURE, PARA_STRERROR(-slot_num));
- s = &slot[slot_num];
- s->format = format;
- s->receiver_node = para_calloc(sizeof(struct receiver_node));
- rn = s->receiver_node;
- rn->receiver = a->receiver;
- rn->conf = a->receiver_conf;
- ret = a->receiver->open(s->receiver_node);
- if (ret < 0) {
- PARA_ERROR_LOG("failed to open receiver (%s)\n",
- PARA_STRERROR(-ret));
- free(s->receiver_node);
- s->receiver_node = NULL;
- return;
- }
- PARA_NOTICE_LOG("started %s: %s receiver in slot %d\n",
- audio_formats[s->format], a->receiver->name, slot_num);
- rn->task.private_data = s->receiver_node;
- rn->task.pre_select = a->receiver->pre_select;
- rn->task.post_select = a->receiver->post_select;
- rn->task.event_handler = rn_event_handler;
- rn->task.flags = 0;
- sprintf(rn->task.status, "receiver node");
- register_task(&rn->task);
-}
-
-static int is_frozen(int format)
-{
- struct audio_format_info *a = &afi[format];
-
- return (tv_diff(now, &a->restart_barrier, NULL) > 0)? 0 : 1;
-}
-
-static void open_current_receiver(void)
-{
- int i;
-
- if (!af_status)
- return;
- i = get_audio_format_num(af_status);
- if (i < 0)
- return;
- if (decoder_running(i) || is_frozen(i))
- return;
- open_receiver(i);
-}
-
-static void compute_time_diff(const struct timeval *status_time)
-{
- struct timeval tmp, diff;
- static int count;
- int sign;
- const struct timeval max_deviation = {0, 500 * 1000};
- const int time_smooth = 5;
-
- sign = tv_diff(status_time, now, &diff);
-// PARA_NOTICE_LOG("%s: sign = %i, sa_time_diff_sign = %i\n", __func__,
-// sign, sa_time_diff_sign);
- if (!count) {
- sa_time_diff_sign = sign;
- sa_time_diff = diff;
- count++;
- return;
- }
- if (count > 5) {
- int s = tv_diff(&diff, &sa_time_diff, &tmp);
- if (tv_diff(&max_deviation, &tmp, NULL) < 0)
- PARA_WARNING_LOG("time diff jump: %lims\n",
- s * tv2ms(&tmp));
- }
- count++;
- sa_time_diff_sign = tv_convex_combination(
- sa_time_diff_sign * time_smooth, &sa_time_diff,
- count > 10? sign : sign * time_smooth, &diff,
- &tmp);
- sa_time_diff = tmp;
- PARA_DEBUG_LOG("time diff (cur/avg): %s%lums/%s%lums\n",
- sign > 0? "+" : "-",
- tv2ms(&diff),
- sa_time_diff_sign ? "+" : "-",
- tv2ms(&sa_time_diff)
- );
-}
-
-static void check_stat_line(char *line)
-{
- int itemnum;
- size_t ilen = 0;
- long unsigned sec, usec;
- char *tmp;
-
-// PARA_INFO_LOG("line: %s\n", line);
- if (!line)
- return;
- itemnum = stat_line_valid(line);
- if (itemnum < 0) {
- PARA_WARNING_LOG("invalid status line: %s\n", line);
- return;
- }
- tmp = make_message("%s\n", line);
- stat_client_write(tmp, itemnum);
- free(tmp);