/*
- * 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. */
* It has to to take into account that probably the stream was not started at
* the beginning of the file, that the clock between the server and the client
* host may differ and that playback of the stream was delayed, e.g. because
- * the prebuffer filter is used in the filter chain of the given slot.
+ * the prebuffer filter is used in the filter configuration of the given slot.
*
* If no writer is active in the given slot, or \a slot_num is negative
* (indicating that para_audiod runs in standby mode), an approximation based
btr_free_node(s->receiver_node->btrn);
free(s->receiver_node);
s->receiver_node = NULL;
+ tv_add(now, &(struct timeval)EMBRACE(0, 200 * 1000),
+ &a->restart_barrier);
}
static void writer_cleanup(struct writer_node *wn)
int cafn = stat_task->current_audio_format_num;
unsigned vs = stat_task->vss_status;
+ if (audiod_status != AUDIOD_ON)
+ return false;
if (cafn < 0)
return false;
if (!stat_task->ct)
* If udp is used to receive this audiod format, add fecdec as
* the first filter.
*/
- if (strcmp(afi[i].receiver->name, "udp") == 0) {
+ if (strcmp(afi[i].receiver->name, "udp") == 0 ||
+ strcmp(afi[i].receiver->name, "dccp") == 0) {
tmp = para_strdup("fecdec");
add_filter(i, tmp);
free(tmp);
para_fd_set(st->fd, &s->rfds, &s->max_fileno);
}
-static void signal_post_select(struct sched *s, struct task *t)
+static void signal_post_select(struct sched *s, __a_unused struct task *t)
{
- struct signal_task *st = container_of(t, struct signal_task, task);
-
- if (!FD_ISSET(st->fd, &s->rfds))
- return;
+ int signum;
- st->signum = para_next_signal();
- switch (st->signum) {
+ signum = para_next_signal(&s->rfds);
+ switch (signum) {
case SIGINT:
case SIGTERM:
case SIGHUP:
- PARA_EMERG_LOG("terminating on signal %d\n", st->signum);
+ PARA_EMERG_LOG("terminating on signal %d\n", signum);
clean_exit(EXIT_FAILURE, "caught deadly signal");
}
}
last_status_dump = *now;
}
- if (!FD_ISSET(ct->fd, &s->rfds))
- return;
- ret = handle_connect(ct->fd);
+ ret = handle_connect(ct->fd, &s->rfds);
if (ret < 0)
PARA_ERROR_LOG("%s\n", para_strerror(-ret));
+ audiod_status_dump();
}
static void init_command_task(struct command_task *ct)
ret = btr_node_status(st->btrn, 0, BTR_NT_LEAF);
if (ret > 0)
goto min_delay;
- if (!st->ct)
+ 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);
}
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;
}
+ 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 */