chiark / gitweb /
Consistency check for finished tracks.
[disorder] / server / play.c
index 9f54d615bf77d547fd240b2412d14f971f360855..8406238d52f8865fe62047725ce05d87ec886d8d 100644 (file)
@@ -96,6 +96,19 @@ static int speaker_readable(ev_source *ev, int fd,
     D(("SM_PLAYING %s %ld", sm.id, sm.data));
     playing->sofar = sm.data;
     break;
+  case SM_ARRIVED: {
+    /* track ID is now prepared */
+    struct queue_entry *q;
+    for(q = qhead.next; q != &qhead && strcmp(q->id, sm.id); q = q->next)
+      ;
+    if(q && q->preparing) {
+      q->preparing = 0;
+      q->prepared = 1;
+      /* We might be waiting to play the now-prepared track */
+      play(ev);
+    }
+    break;
+  }
   default:
     disorder_error(0, "unknown speaker message type %d", sm.type);
   }
@@ -287,7 +300,7 @@ static int start(ev_source *ev,
 
   D(("start %s", q->id));
   /* Find the player plugin. */
-  if(!(player = find_player(q)) < 0)
+  if(!(player = find_player(q)))
     return START_HARDFAIL;              /* No player */
   if(!(q->pl = open_plugin(player->s[1], 0)))
     return START_HARDFAIL;
@@ -379,19 +392,21 @@ int prepare(ev_source *ev,
   if(q->pid >= 0)
     return START_OK;
   /* If the track is already prepared, do nothing */
-  if(q->prepared)
+  if(q->prepared || q->preparing)
     return START_OK;
   /* Find the player plugin */
-  if(!(player = find_player(q)) < 0
+  if(!(player = find_player(q))) 
     return START_HARDFAIL;              /* No player */
   q->pl = open_plugin(player->s[1], 0);
   q->type = play_get_type(q->pl);
   if((q->type & DISORDER_PLAYER_TYPEMASK) != DISORDER_PLAYER_RAW)
     return START_OK;                    /* Not a raw player */
-  const int rc = play_background(ev, player, q, prepare_child, NULL);
+  int rc = play_background(ev, player, q, prepare_child, NULL);
   if(rc == START_OK) {
     ev_child(ev, q->pid, 0, player_finished, q);
-    q->prepared = 1;
+    q->preparing = 1;
+    /* Actually the track is still "in flight" */
+    rc = START_SOFTFAIL;
   }
   return rc;
 }
@@ -717,14 +732,20 @@ void scratch(const char *who, const char *id) {
       speaker_send(speaker_fd, &sm);
       D(("sending SM_CANCEL for %s", playing->id));
     }
-    /* Try to make sure there is a scratch */
-    ensure_next_scratch(NULL);
-    /* Insert it at the head of the queue */
-    if(next_scratch){
-      next_scratch->submitter = who;
-      queue_insert_entry(&qhead, next_scratch);
-      eventlog_raw("queue", queue_marshall(next_scratch), (const char *)0);
-      next_scratch = NULL;
+    /* If playing is enabled then add a scratch to the queue.  Having a scratch
+     * appear in the queue when further play is disabled is weird and
+     * contradicts implicit assumptions made elsewhere, so we try to avoid
+     * it. */
+    if(playing_is_enabled()) {
+      /* Try to make sure there is a scratch */
+      ensure_next_scratch(NULL);
+      /* Insert it at the head of the queue */
+      if(next_scratch){
+        next_scratch->submitter = who;
+        queue_insert_entry(&qhead, next_scratch);
+        eventlog_raw("queue", queue_marshall(next_scratch), (const char *)0);
+        next_scratch = NULL;
+      }
     }
     notify_scratch(playing->track, playing->submitter, who,
                   xtime(0) - playing->played);