/*
- * Copyright (C) 2005-2009 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2005-2010 Andre Noll <maan@systemlinux.org>
*
* Licensed under the GPL v2. For licencing details see COPYING.
*/
struct timeval restart_barrier;
/** Last time we received status data from para_server. */
struct timeval last_status_read;
+ size_t min_iqs;
/** The offset value announced by para_server. */
int offset_seconds;
/** The length of the current audio file as announced by para_server. */
* \sa struct status_task
*/
static struct status_task *stat_task = &status_task_struct;
-static struct timeval initial_delay_barrier;
/**
* the task for handling audiod commands
{
struct slot_info *s = &slot[slot_num];
struct audio_format_info *a;
- struct timeval restart_delay = {0, 200 * 1000};
if (s->format < 0 || !s->receiver_node)
return;
btr_free_node(s->receiver_node->btrn);
free(s->receiver_node);
s->receiver_node = NULL;
- tv_add(now, &restart_delay, &afi[s->format].restart_barrier);
}
static void writer_cleanup(struct writer_node *wn)
return slot_num;
}
-/* return: 0: Not running, 1: Running, -1: Running but eof (or error) */
-static int receiver_running(int format)
+static bool receiver_running(void)
{
- int i, ret = 0;
+ int i;
+ long unsigned ss1 = stat_task->server_stream_start.tv_sec;
FOR_EACH_SLOT(i) {
struct slot_info *s = &slot[i];
- if (s->format != format)
- continue;
+ long unsigned ss2 = s->server_stream_start.tv_sec;
+
if (!s->receiver_node)
continue;
if (s->receiver_node->task.error >= 0)
- return 1;
- ret = -1;
+ return true;
+ if (ss1 == ss2)
+ return true;
}
- return ret;
+ return false;
}
/**
/* whether a new instance of a decoder should be started. */
static bool must_start_decoder(void)
{
- int ret, cafn = stat_task->current_audio_format_num;
+ int cafn = stat_task->current_audio_format_num;
+ unsigned vs = stat_task->vss_status;
- if (cafn < 0 || !stat_task->ct)
+ if (cafn < 0)
return false;
- /* Do nothing if the 'N' flag is set or the 'P' flag is unset */
- if (stat_task->vss_status != VSS_STATUS_FLAG_PLAYING)
+ if (!stat_task->ct)
return false;
- ret = receiver_running(cafn);
- if (ret != 0) /* already running */
+ if (vs & VSS_STATUS_FLAG_NEXT)
+ return false;
+ if (!(vs & VSS_STATUS_FLAG_PLAYING))
+ return false;
+ if (receiver_running())
return false;
if (tv_diff(now, &afi[cafn].restart_barrier, NULL) < 0)
return false;
break;
case SI_STREAM_START:
if (sscanf(buf, "%lu.%lu", &sec, &usec) == 2) {
- struct timeval a_start, delay;
- delay.tv_sec = conf.stream_delay_arg / 1000;
- delay.tv_usec = (conf.stream_delay_arg % 1000) * 1000;
stat_task->server_stream_start.tv_sec = sec;
stat_task->server_stream_start.tv_usec = usec;
- if (compute_time_diff(NULL) > 2) {
- if (stat_task->sa_time_diff_sign < 0)
- tv_add(&stat_task->server_stream_start,
- &stat_task->sa_time_diff, &a_start);
- else
- tv_diff(&stat_task->server_stream_start,
- &stat_task->sa_time_diff, &a_start);
- tv_add(&a_start, &delay, &initial_delay_barrier);
- }
}
break;
case SI_CURRENT_TIME:
}
if (st->ct->status != CL_RECEIVING)
goto out;
- ret = btr_node_status(st->btrn, 0, BTR_NT_LEAF);
- if (ret <= 0)
+ 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)
+ if (sz != ret) {
+ btr_consume(st->btrn, sz - ret);
st->last_status_read = *now;
- else {
- 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);
- }
- btr_consume(st->btrn, sz - ret);
+ st->min_iqs = 0;
+ } else /* current status item crosses buffers */
+ st->min_iqs = sz + 1;
goto out;
}
if (tv_diff(now, &st->restart_barrier, NULL) < 0)