unsigned loaded;
/** the associated task structure */
struct task task;
+ /** do not restart client command until this time */
+ struct timeval restart_barrier;
};
static struct status_task status_task_struct, *stat_task = &status_task_struct;
para_install_sighandler(SIGTERM);
para_install_sighandler(SIGCHLD);
para_install_sighandler(SIGHUP);
- signal(SIGPIPE, SIG_IGN);
+ para_install_sighandler(SIGPIPE);
+// signal(SIGPIPE, SIG_IGN);
}
static void audiod_status_dump(void)
close(stat_task->fd);
del_close_on_fork_list(stat_task->fd);
stat_task->fd = -1;
- kill_all_decoders();
+// kill_all_decoders();
for (i = 0; i < NUM_STAT_ITEMS; i++) {
free(stat_item_values[i]);
stat_item_values[i] = NULL;
s->fc->task.pre_select = filter_pre_select;
s->fc->task.event_handler = filter_event_handler;
s->fc->task.private_data = s->fc;
- s->fc->task.flags = 0;
s->fc->eof = 0;
s->receiver_node->output_eof = &s->fc->eof;
for (i = 0; i < a->num_writers; i++) {
s->wng->writer_nodes[i].conf = a->writer_conf[i];
s->wng->writer_nodes[i].writer = a->writers[i];
- sprintf(s->wng->writer_nodes[i].task.status, "writer_node");
}
ret = wng_open(s->wng);
if (ret < 0) {
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");
+ sprintf(rn->task.status, "%s receiver node", rn->receiver->name);
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)
+static int open_current_receiver(struct sched *s)
{
int i;
+ struct timeval diff;
if (!af_status)
- return;
+ return 0;
i = get_audio_format_num(af_status);
if (i < 0)
- return;
- if (decoder_running(i) || is_frozen(i))
- return;
+ return 0;
+ if (decoder_running(i))
+ return 0;
+ if (tv_diff(now, &afi[i].restart_barrier, &diff) < 0) {
+ s->timeout = diff;
+ return 0;
+ }
open_receiver(i);
+ return 1;
}
static void compute_time_diff(const struct timeval *status_time)
clear_slot(slot_num);
}
+/*
+ * Check if any receivers/filters/writers need to be started and do so if
+ * neccessary. Since the pre_select function didn't have a chance yet to put
+ * file descriptors into the fd sets given by s, make the upcoming select()
+ * return immediately to avoid a long timeout in case we started something.
+ */
static void audiod_pre_select(struct sched *s, __a_unused struct task *t)
{
int i;
+ struct timeval min_delay = {0, 1};
t->ret = 1;
now = &s->now;
if (audiod_status != AUDIOD_ON || !playing)
- kill_all_decoders();
- else if (playing)
- open_current_receiver();
+ return kill_all_decoders();
+ if (open_current_receiver(s))
+ s->timeout = min_delay;
FOR_EACH_SLOT(i) {
- struct slot_info *s = &slot[i];
+ struct slot_info *sl = &slot[i];
struct audio_format_info *a;
- if (s->format < 0)
+ if (sl->format < 0)
continue;
- a = &afi[s->format];
- if (!s->receiver_node)
+ a = &afi[sl->format];
+ if (!sl->receiver_node)
continue;
if (!a->num_filters) {
- if (s->receiver_node->loaded && !s->wng)
+ if (sl->receiver_node->loaded && !sl->wng) {
open_writers(i);
+ s->timeout = min_delay;
+ }
continue;
}
- if (s->receiver_node->loaded && !s->fc) {
+ if (sl->receiver_node->loaded && !sl->fc) {
open_filters(i);
+ s->timeout = min_delay;
continue;
}
- if (s->fc && *s->fc->out_loaded && !s->wng)
+ if (sl->fc && *sl->fc->out_loaded && !sl->wng) {
open_writers(i);
+ s->timeout = min_delay;
+ }
}
}
t->post_select = audiod_post_select;
t->event_handler = NULL;
t->private_data = t;
- t->flags = 0;
sprintf(t->status, "audiod task");
}
st->task.pre_select = signal_pre_select;
st->task.post_select = signal_post_select;
st->task.private_data = st;
- st->task.flags = 0;
sprintf(st->task.status, "signal task");
}
ct->task.post_select = command_post_select;
ct->task.event_handler = NULL;
ct->task.private_data = ct;
- ct->task.flags = 0;
ct->fd = audiod_get_socket(); /* doesn't return on errors */
sprintf(ct->task.status, "command task");
}
static void status_event_handler(__a_unused struct task *t)
{
+ struct timeval delay = {1, 0};
+ int i;
+ struct status_task *st = t->private_data;
+
PARA_ERROR_LOG("%s\n", PARA_STRERROR(-t->ret));
close_stat_pipe();
/* avoid busy loop if server is down */
- while (sleep(1) > 0) /* FIXME */
- ; /* try again*/
-
+ tv_add(now, &delay, &st->restart_barrier);
+ FOR_EACH_AUDIO_FORMAT(i)
+ afi[i].restart_barrier = st->restart_barrier;
}
static void status_pre_select(struct sched *s, struct task *t)
t->ret = 1;
if (st->fd >= 0 && audiod_status == AUDIOD_OFF)
close_stat_pipe();
- if (st->fd < 0 && audiod_status != AUDIOD_OFF) {
+ if (st->fd < 0 && audiod_status != AUDIOD_OFF
+ && tv_diff(now, &st->restart_barrier, NULL) > 0) {
st->fd = open_stat_pipe();
st->loaded = 0;
st->buf[0] = '\0';
static void init_status_task(struct status_task *st)
{
+ memset(st, 0, sizeof(struct status_task));
st->task.pre_select = status_pre_select;
st->task.post_select = status_post_select;
st->task.event_handler = status_event_handler;
st->task.private_data = st;
- st->task.flags = 0;
- st->loaded = 0;
st->fd = -1;
- st->buf[0] = '\0';
sprintf(st->task.status, "status task");
}
register_task(&cmd_task->task);
register_task(&stat_task->task);
register_task(audiod_task);
- s.default_timeout.tv_sec = 0;
+ s.default_timeout.tv_sec = 3;
s.default_timeout.tv_usec = 99 * 1000;
ret = sched(&s);