/* 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(); }
uint32_t stream_get_seek_time(uint32_t *start) { uint32_t time; stream_mgr_lock(); if (stream_mgr.seeked) { time = str_parser.last_seek_time; } else { time = TICKS_TO_TS(pcm_output_get_clock()); /* Clock can be start early so keep in range */ if (time < str_parser.start_pts) time = str_parser.start_pts; } if (start != NULL) *start = str_parser.start_pts; stream_mgr_unlock(); return time; }
/* Handle STREAM_CLOSE */ static int stream_on_close(void) { int status = STREAM_STOPPED; stream_mgr_lock(); /* Any open file that was accepted for playback? */ if (stream_mgr.filename != NULL) { /* Yes - hide video */ stream_show_vo(false); /* Stop any playback */ status = stream_mgr.status; stream_on_stop(false); /* Tell parser file is finished */ parser_close_stream(); /* Reinitialize manager */ stream_mgr_init_state(); } /* Let disk buffer reset itself - file might be open even if no good */ disk_buf_close(); stream_mgr_unlock(); return status; }
/* Handle STREAM_OPEN */ void stream_on_open(const char *filename) { int err = STREAM_ERROR; stream_mgr_lock(); trigger_cpu_boost(); /* Open the video file */ if (disk_buf_open(filename) >= 0) { /* Initialize the parser */ err = parser_init_stream(); if (err >= STREAM_OK) { /* File ok - save the opened filename */ stream_mgr.filename = filename; } } /* If error - cleanup */ if (err < STREAM_OK) stream_on_close(); cancel_cpu_boost(); stream_mgr_unlock(); stream_mgr_reply_msg(err); }
/* Handle STREAM_CLOSE */ static int stream_on_close(void) { int status = STREAM_STOPPED; stream_mgr_lock(); /* Any open file? */ if (stream_mgr.filename != NULL) { /* Yes - hide video */ stream_show_vo(false); /* Stop any playback */ status = stream_mgr.status; stream_on_stop(false); /* Tell parser file is finished */ parser_close_stream(); /* Close file */ disk_buf_close(); /* Reinitialize manager */ stream_mgr_init_state(); } stream_mgr_unlock(); return status; }
/* Query the visibility of video output */ bool stream_vo_is_visible(void) { bool vis; stream_mgr_lock(); vis = send_video_msg(VIDEO_DISPLAY_IS_VISIBLE, 0); stream_mgr_unlock(); return vis; }
/* Show/hide the gray video overlay (independently of vo visibility). */ void stream_gray_show(bool show) { stream_mgr_lock(); grey_show(show); stream_mgr_unlock(); }
bool stream_draw_frame(bool no_prepare) { bool retval; stream_mgr_lock(); retval = send_video_msg(VIDEO_PRINT_FRAME, no_prepare); stream_mgr_unlock(); return retval; }
/* Return the time playback should resume if interrupted */ uint32_t stream_get_resume_time(void) { uint32_t resume_time; /* A stop request is async and replies before setting this - must lock */ stream_mgr_lock(); resume_time = stream_mgr.resume_time; stream_mgr_unlock(); return resume_time; }
/* Show/hide the video output */ bool stream_show_vo(bool show) { bool vis; stream_mgr_lock(); vis = send_video_msg(VIDEO_DISPLAY_SHOW, show); #ifndef HAVE_LCD_COLOR grey_show(show); #endif stream_mgr_unlock(); return vis; }
void stream_vo_set_clip(const struct vo_rect *rc) { stream_mgr_lock(); if (rc) { stream_mgr.parms.rc = *rc; rc = &stream_mgr.parms.rc; } send_video_msg(VIDEO_SET_CLIP_RECT, (intptr_t)rc); stream_mgr_unlock(); }
/* Handle STREAM_SEEK */ static void stream_on_seek(struct stream_seek_data *skd) { uint32_t time = skd->time; int whence = skd->whence; switch (whence) { case SEEK_SET: case SEEK_CUR: case SEEK_END: if (stream_mgr.filename == NULL) break; /* Keep things spinning if already doing so */ stream_keep_disk_active(); /* Have data - reply in order to acquire lock */ stream_mgr_reply_msg(STREAM_OK); stream_mgr_lock(); /* Either seeking must be possible or a full rewind must be done */ if (stream_can_seek() || time_from_whence(time, whence) == 0) { bool buffer; if (stream_mgr.status == STREAM_PLAYING) { /* Keep clock from advancing while seeking */ pcm_output_play_pause(false); } time = stream_seek_intl(time, whence, stream_mgr.status, &buffer); stream_remember_resume_time(); if (stream_mgr.status == STREAM_PLAYING) { /* Sync and restart - no force buffering */ stream_start_playback(time, buffer); } } stream_mgr_unlock(); return; } /* Invalid parameter or no file */ stream_mgr_reply_msg(STREAM_ERROR); }
bool stream_set_callback(long id, void *fn) { bool retval = false; stream_mgr_lock(); switch (id) { case VIDEO_SET_POST_FRAME_CALLBACK: retval = send_video_msg(id, (intptr_t)fn); } stream_mgr_unlock(); return retval; }
/* Return the video dimensions */ bool stream_vo_get_size(struct vo_ext *sz) { bool retval = false; stream_mgr_lock(); if (str_parser.dims.w > 0 && str_parser.dims.h > 0) { *sz = str_parser.dims; retval = true; } stream_mgr_unlock(); return retval; }
/* Display a thumbnail at the last seek point */ bool stream_display_thumb(const struct vo_rect *rc) { bool retval; if (rc == NULL) return false; stream_mgr_lock(); stream_mgr.parms.rc = *rc; retval = send_video_msg(VIDEO_PRINT_THUMBNAIL, (intptr_t)&stream_mgr.parms.rc); stream_mgr_unlock(); return retval; }
bool stream_vo_get_clip(struct vo_rect *rc) { bool retval; if (!rc) return false; stream_mgr_lock(); retval = send_video_msg(VIDEO_GET_CLIP_RECT, (intptr_t)&stream_mgr.parms.rc); *rc = stream_mgr.parms.rc; stream_mgr_unlock(); return retval; }
/* Seeks playback time to/by the specified time */ int stream_seek(uint32_t time, int whence) { int ret; if (stream_mgr.thread == 0) return STREAM_ERROR; stream_mgr_lock(); stream_mgr.parms.skd.time = time; stream_mgr.parms.skd.whence = whence; ret = stream_mgr_send_msg(STREAM_SEEK, (intptr_t)&stream_mgr.parms.skd); stream_mgr_unlock(); return ret; }
/* Handler STREAM_PLAY */ static void stream_on_play(void) { int status = stream_mgr.status; stream_mgr_lock(); if (status == STREAM_STOPPED) { uint32_t start; /* We just say we're playing now */ stream_mgr.status = STREAM_PLAYING; /* Reply with previous state */ stream_mgr_reply_msg(status); trigger_cpu_boost(); /* Seek to initial position and set clock to that time */ /* Save the resume time */ stream_remember_resume_time(); /* Prepare seek to start point */ start = stream_seek_intl(stream_mgr.resume_time, SEEK_SET, STREAM_STOPPED, NULL); /* Sync and start - force buffer fill */ stream_start_playback(start, true); } else { /* Reply with previous state */ stream_mgr_reply_msg(status); } stream_mgr_unlock(); }
/* Handle STREAM_RESUME */ static void stream_on_resume(void) { int status = stream_mgr.status; stream_mgr_lock(); /* Reply with previous state */ stream_mgr_reply_msg(status); if (status == STREAM_PAUSED) { /* Boost the CPU */ trigger_cpu_boost(); /* Sync and start - no force buffering */ stream_start_playback(str_parser.last_seek_time, false); /* Officially playing */ stream_mgr.status = STREAM_PLAYING; } stream_mgr_unlock(); }
/* 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(); }
/* Handle STREAM_EV_COMPLETE */ static void stream_on_ev_complete(struct stream *str) { stream_mgr_lock(); /* Stream is active? */ if (actl_stream_remove(str)) { /* No - remove this stream from the active list */ DEBUGF(" finished: 0x%02x\n", str->id); if (list_is_empty(stream_mgr.actl)) { /* All streams have acked - stop playback */ stream_on_stop(false); stream_mgr.resume_time = 0; /* Played to end - no resume */ } else { /* Stream is done - stop it and place back in pool */ str_send_msg(str, STREAM_STOP, 1); } } stream_mgr_unlock(); }
/* Wait for a state transistion to complete */ void stream_wait_status(void) { stream_mgr_lock(); stream_mgr_unlock(); }