/*
- * Copyright (C) 2005-2012 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2005-2013 Andre Noll <maan@systemlinux.org>
*
* Licensed under the GPL v2. For licencing details see COPYING.
*/
/** define the array containing all supported audio formats */
const char *audio_formats[] = {AUDIOD_AUDIO_FORMAT_ARRAY NULL};
+DEFINE_RECEIVER_ARRAY;
+
/** Defines how audiod handles one supported audio format. */
struct audio_format_info {
/** pointer to the receiver for this audio format */
fn->filter_num = a->filter_nums[i];
fn->conf = a->filter_conf[i];
fn->task.pre_select = f->pre_select;
- fn->task.post_select = f->post_select;
-
+ if (f->new_post_select) {
+ fn->task.new_post_select = f->new_post_select;
+ fn->task.post_select = NULL;
+ } else {
+ fn->task.new_post_select = NULL;
+ fn->task.post_select = f->post_select;
+ }
fn->btrn = btr_new_node(&(struct btr_node_description)
EMBRACE(.name = f->name, .parent = parent,
.handler = f->execute, .context = fn));
PARA_NOTICE_LOG("started %s: %s receiver in slot %d\n",
audio_formats[format], r->name, slot_num);
rn->task.pre_select = r->pre_select;
- rn->task.post_select = r->post_select;
+ if (r->new_post_select) {
+ rn->task.new_post_select = r->new_post_select;
+ rn->task.post_select = NULL;
+ } else {
+ rn->task.new_post_select = NULL;
+ rn->task.post_select = r->post_select;
+ }
sprintf(rn->task.status, "%s receiver node", r->name);
register_task(&sched, &rn->task);
return slot_num;
para_fd_set(st->fd, &s->rfds, &s->max_fileno);
}
-static void signal_post_select(struct sched *s, __a_unused struct task *t)
+static int signal_post_select(struct sched *s, __a_unused struct task *t)
{
int signum;
PARA_EMERG_LOG("terminating on signal %d\n", signum);
clean_exit(EXIT_FAILURE, "caught deadly signal");
}
+ return 0;
}
static void signal_setup_default(struct signal_task *st)
{
st->task.pre_select = signal_pre_select;
- st->task.post_select = signal_post_select;
+ st->task.new_post_select = signal_post_select;
+ st->task.post_select = NULL;
sprintf(st->task.status, "signal task");
}
{
ct->task.pre_select = command_pre_select;
ct->task.post_select = command_post_select;
+ ct->task.new_post_select = NULL;
ct->task.error = 0;
ct->fd = audiod_get_socket(); /* doesn't return on errors */
sprintf(ct->task.status, "command task");
tv_add(now, &delay, &stat_task->restart_barrier);
}
-static void try_to_close_slot(int slot_num)
+static bool must_close_slot(int slot_num)
{
struct slot_info *s = &slot[slot_num];
struct audio_format_info *a = afi + s->format;
int i;
if (s->format < 0)
- return;
+ return false;
if (s->receiver_node && s->receiver_node->task.error >= 0)
- return;
+ return false;
for (i = 0; i < a->num_filters; i++)
if (s->fns && s->fns[i].task.error >= 0)
- return;
+ return false;
if (a->num_writers > 0) {
for (i = 0; i < a->num_writers; i++)
if (s->wns && s->wns[i].task.error >= 0)
- return;
+ return false;
} else {
if (s->wns && s->wns[0].task.error >= 0)
- return;
+ return false;
+ }
+ return true;
+}
+
+static void close_unused_slots(void)
+{
+ int i;
+
+ FOR_EACH_SLOT(i) {
+ struct slot_info *s = slot + i;
+ if (!must_close_slot(i))
+ continue;
+ PARA_INFO_LOG("closing slot %d\n", i);
+ close_writers(s);
+ close_filters(s);
+ close_receiver(i);
+ clear_slot(i);
}
- PARA_INFO_LOG("closing slot %d\n", slot_num);
- close_writers(s);
- close_filters(s);
- close_receiver(slot_num);
- clear_slot(slot_num);
}
/*
*/
static void start_stop_decoders(void)
{
- int i, ret;
+ int ret;
struct slot_info *sl;
struct audio_format_info *a;
- FOR_EACH_SLOT(i)
- try_to_close_slot(i);
+ close_unused_slots();
if (audiod_status != AUDIOD_ON ||
!(stat_task->vss_status & VSS_STATUS_FLAG_PLAYING))
return notify_receivers(E_NOT_PLAYING);
static void status_pre_select(struct sched *s, struct task *t)
{
struct status_task *st = container_of(t, struct status_task, task);
- int ret, cafn = stat_task->current_audio_format_num;
+ int i, ret, cafn = stat_task->current_audio_format_num;
if (must_start_decoder())
goto min_delay;
+ FOR_EACH_SLOT(i)
+ if (must_close_slot(i))
+ goto min_delay;
ret = btr_node_status(st->btrn, st->min_iqs, BTR_NT_LEAF);
if (ret > 0)
goto min_delay;
}
/* restart the client task if necessary */
-static void status_post_select(struct sched *s, struct task *t)
+static int status_post_select(struct sched *s, struct task *t)
{
struct status_task *st = container_of(t, struct status_task, task);
st->last_status_read = *now;
out:
start_stop_decoders();
+ return 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.new_post_select = status_post_select;
+ st->task.post_select = NULL;
st->sa_time_diff_sign = 1;
st->clock_diff_count = conf.clock_diff_count_arg;
st->current_audio_format_num = -1;