X-Git-Url: https://git.distorted.org.uk/~mdw/disorder/blobdiff_plain/f3102c220cd8142a0281f3b487b8c6157672ae7c..9439cdabec3e4c1d29e4366f9b654ef27eb2c586:/server/play.c diff --git a/server/play.c b/server/play.c index 9f54d61..9b919d1 100644 --- a/server/play.c +++ b/server/play.c @@ -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; } @@ -625,11 +640,13 @@ void play(ev_source *ev) { /* Miscelleneous ------------------------------------------------------------ */ +int flag_enabled(const char *s) { + return !s || !strcmp(s, "yes"); +} + /** @brief Return true if play is enabled */ int playing_is_enabled(void) { - const char *s = trackdb_get_global("playing"); - - return !s || !strcmp(s, "yes"); + return flag_enabled(trackdb_get_global("playing")); } /** @brief Enable play */ @@ -641,15 +658,13 @@ void enable_playing(const char *who, ev_source *ev) { } /** @brief Disable play */ -void disable_playing(const char *who) { +void disable_playing(const char *who, ev_source attribute((unused)) *ev) { trackdb_set_global("playing", "no", who); } /** @brief Return true if random play is enabled */ int random_is_enabled(void) { - const char *s = trackdb_get_global("random-play"); - - return !s || !strcmp(s, "yes"); + return flag_enabled(trackdb_get_global("random-play")); } /** @brief Enable random play */ @@ -660,7 +675,7 @@ void enable_random(const char *who, ev_source *ev) { } /** @brief Disable random play */ -void disable_random(const char *who) { +void disable_random(const char *who, ev_source attribute((unused)) *ev) { trackdb_set_global("random-play", "no", who); } @@ -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);