audiod: Avoid delay when closing slot.
[paraslash.git] / audiod.c
index 4dfd5d53d4c5c1a5d7d3d3b4273231dddc6a0f5a..6da2ccc78db5baf374cb3997f34012605d75b6d7 100644 (file)
--- a/audiod.c
+++ b/audiod.c
@@ -1,5 +1,5 @@
 /*
- * 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.
  */
@@ -1089,32 +1089,44 @@ static void set_stat_task_restart_barrier(unsigned seconds)
        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);
 }
 
 /*
@@ -1123,12 +1135,11 @@ static void try_to_close_slot(int 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);
@@ -1151,10 +1162,13 @@ static void start_stop_decoders(void)
 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;