* \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;
+ if (vs & VSS_STATUS_FLAG_NEXT)
return false;
- ret = receiver_running(cafn);
- if (ret != 0) /* already running */
+ 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:
/** The socket file descriptor. */
int fd;
struct btr_pool *btrp;
+ struct timeval last_read_time;
};
static void udp_recv_pre_select(struct sched *s, struct task *t)
goto err;
if (ret == 0)
return;
- if (!FD_ISSET(purd->fd, &s->rfds))
+ if (!FD_ISSET(purd->fd, &s->rfds)) {
+ struct timeval tmp;
+ tv_add(&purd->last_read_time, &(struct timeval)EMBRACE(5, 0),
+ &tmp);
+ ret = -E_UDP_TIMEOUT;
+ if (tv_diff(now, &tmp, NULL) > 0)
+ goto err;
return;
+ }
iovcnt = btr_pool_get_buffers(purd->btrp, iov);
ret = -E_UDP_OVERRUN;
if (iovcnt == 0)
ret = udp_check_eof(packet_size, iov);
if (ret < 0)
goto err;
+ purd->last_read_time = *now;
if (iov[0].iov_len >= packet_size)
btr_add_output_pool(purd->btrp, packet_size, btrn);
else { /* both buffers contain data */
ret = mcast_receiver_setup(purd->fd, iface);
if (ret < 0) {
close(purd->fd);
- return ret;
+ goto err;
}
ret = mark_fd_nonblocking(purd->fd);
PARA_INFO_LOG("receiving from %s:%d, fd=%d\n", c->host_arg,
c->port_arg, purd->fd);
purd->btrp = btr_pool_new("udp_recv", 320 * 1024);
+ purd->last_read_time = *now;
return purd->fd;
err:
free(rn->private_data);