/* Handle STREAM_PAUSE */ static void stream_on_pause(void) { int status = stream_mgr.status; stream_mgr_lock(); /* Reply with previous state */ stream_mgr_reply_msg(status); if (status == STREAM_PLAYING) { /* Pause the clock */ pcm_output_play_pause(false); /* Pause each active stream */ actl_stream_broadcast(STREAM_PAUSE, 0); /* Pause the disk buffer - buffer may continue filling */ disk_buf_send_msg(STREAM_PAUSE, false); /* Unboost the CPU */ cancel_cpu_boost(); /* Offically paused */ stream_mgr.status = STREAM_PAUSED; } stream_mgr_unlock(); }
static void stream_start_playback(uint32_t time, bool fill_buffer) { if (stream_mgr.seeked) { /* Clear any seeked status */ stream_mgr.seeked = false; /* Flush old PCM data */ pcm_output_flush(); /* Set the master clock */ set_stream_clock(time); /* Make sure streams are back in active pool */ move_strl_to_actl(); /* Prepare the parser and associated streams */ parser_prepare_streaming(); } /* Start buffer which optional force fill */ disk_buf_send_msg(STREAM_PLAY, fill_buffer); /* Tell each stream to start - may generate end of stream signals * now - we'll handle this when finished */ actl_stream_broadcast(STREAM_PLAY, 0); /* Actually start the clock */ pcm_output_play_pause(true); }
/* Clear any particular notification for which a stream registered */ void stream_clear_notify(struct stream *str, int for_msg) { switch (for_msg) { case DISK_BUF_DATA_NOTIFY: disk_buf_send_msg(DISK_BUF_CLEAR_DATA_NOTIFY, (intptr_t)str); break; } }
/* Handle seeking details if playing or paused */ static uint32_t stream_seek_intl(uint32_t time, int whence, int status, bool *was_buffering) { if (status != STREAM_STOPPED) { bool wb; /* Place streams in a non-running state - keep them on actl */ actl_stream_broadcast(STREAM_STOP, 0); /* Stop all buffering or else risk clobbering random-access data */ wb = disk_buf_send_msg(STREAM_STOP, 0); if (was_buffering != NULL) *was_buffering = wb; } time = time_from_whence(time, whence); stream_mgr.seeked = true; return parser_seek_time(time); }
/* Handle STREAM_STOP */ static void stream_on_stop(bool reply) { int status = stream_mgr.status; stream_mgr_lock(); if (reply) stream_mgr_reply_msg(status); if (status != STREAM_STOPPED) { /* Pause the clock */ pcm_output_play_pause(false); /* Update the resume time info */ stream_remember_resume_time(); /* Not stopped = paused or playing */ stream_mgr.seeked = false; /* Stop buffering */ disk_buf_send_msg(STREAM_STOP, 0); /* Clear any still-active streams and remove from actl */ actl_stream_broadcast(STREAM_STOP, 1); /* Stop PCM output (and clock) */ pcm_output_stop(); /* Cancel our processor boost */ cancel_cpu_boost(); stream_mgr.status = STREAM_STOPPED; } stream_mgr_unlock(); }
int str_next_data_not_ready(struct stream *str) { /* Save the current window since it actually might be ready by the time * the registration is received by buffering. */ off_t win_right = str->hdr.win_right; if (str->hdr.win_right < disk_buf.filesize - MIN_BUFAHEAD && disk_buf.filesize > MIN_BUFAHEAD) { /* Set right edge to where probing left off + the minimum margin */ str->hdr.win_right += MIN_BUFAHEAD; } else { /* Request would be passed the end of the file */ str->hdr.win_right = disk_buf.filesize; } switch (disk_buf_send_msg(DISK_BUF_DATA_NOTIFY, (intptr_t)str)) { case DISK_BUF_NOTIFY_OK: /* Was ready - restore window and process */ str->hdr.win_right = win_right; return STREAM_OK; case DISK_BUF_NOTIFY_ERROR: /* Error - quit parsing */ str_end_of_stream(str); return STREAM_DATA_END; default: /* Not ready - go wait for notification from buffering. */ str->pkt_flags = 0; return STREAM_DATA_NOT_READY; } }