X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~mdw/git/disorder/blobdiff_plain/e623dd03074a7512cef92c1f4474d1f52d950abe..b60ceb3caecce2c86c484e6173fb1428b71d456a:/server/play.c diff --git a/server/play.c b/server/play.c index 9f54d61..b6d3dcc 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; @@ -327,33 +340,6 @@ static int start_child(struct queue_entry *q, void attribute((unused)) *bgdata) { int n; - /* Wait for a device to clear. This ugliness is now deprecated and will - * eventually be removed. */ - if(params->waitdevice) { - ao_initialize(); - if(*params->waitdevice) { - n = ao_driver_id(params->waitdevice); - if(n == -1) - disorder_fatal(0, "invalid libao driver: %s", params->waitdevice); - } else - n = ao_default_driver_id(); - /* Make up a format. */ - ao_sample_format format; - memset(&format, 0, sizeof format); - format.bits = 8; - format.rate = 44100; - format.channels = 1; - format.byte_format = AO_FMT_NATIVE; - int retries = 20; - struct timespec ts; - ts.tv_sec = 0; - ts.tv_nsec = 100000000; /* 0.1s */ - ao_device *device; - while((device = ao_open_live(n, &format, 0)) == 0 && retries-- > 0) - nanosleep(&ts, 0); - if(device) - ao_close(device); - } /* Play the track */ play_track(q->pl, params->argv, params->argc, @@ -379,19 +365,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 +613,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 +631,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 +648,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 +705,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);