void mp_nav_destroy(struct MPContext *mpctx) { osd_set_nav_highlight(mpctx->osd, NULL); if (!mpctx->nav_state) return; mp_input_disable_section(mpctx->input, "discnav"); mp_input_disable_section(mpctx->input, "discnav-menu"); talloc_free(mpctx->nav_state); mpctx->nav_state = NULL; }
void mp_nav_destroy(struct MPContext *mpctx) { osd_set_nav_highlight(mpctx->osd, NULL); if (!mpctx->nav_state) return; mp_input_disable_section(mpctx->input, "discnav"); mp_input_disable_section(mpctx->input, "discnav-menu"); pthread_mutex_destroy(&mpctx->nav_state->osd_lock); talloc_free(mpctx->nav_state); mpctx->nav_state = NULL; update_state(mpctx); update_mouse_on_button(mpctx); }
void mp_nav_reset(struct MPContext *mpctx) { struct mp_nav_state *nav = mpctx->nav_state; if (!nav) return; struct mp_nav_cmd inp = {MP_NAV_CMD_RESUME}; run_stream_control(mpctx, STREAM_CTRL_NAV_CMD, &inp); osd_set_nav_highlight(mpctx->osd, NULL); nav->hi_visible = 0; nav->nav_menu = false; nav->nav_draining = false; nav->nav_still_frame = 0; mp_input_disable_section(mpctx->input, "discnav-menu"); run_stream_control(mpctx, STREAM_CTRL_RESUME_CACHE, NULL); update_state(mpctx); }
void mp_nav_reset(struct MPContext *mpctx) { struct mp_nav_state *nav = mpctx->nav_state; if (!nav) return; struct mp_nav_cmd inp = {MP_NAV_CMD_RESUME}; stream_control(mpctx->stream, STREAM_CTRL_NAV_CMD, &inp); osd_set_nav_highlight(mpctx->osd, NULL); nav->hi_visible = 0; nav->nav_menu = false; nav->nav_draining = false; nav->nav_still_frame = 0; mp_input_disable_section(mpctx->input, "discnav-menu"); // Prevent demuxer init code to seek to the "start" mpctx->stream->start_pos = stream_tell(mpctx->stream); stream_control(mpctx->stream, STREAM_CTRL_RESUME_CACHE, NULL); }
void mp_handle_nav(struct MPContext *mpctx) { struct mp_nav_state *nav = mpctx->nav_state; if (!nav) return; mpctx->sleeptime = MPMIN(mpctx->sleeptime, 0.5); while (1) { if (!mpctx->demuxer) break; struct mp_nav_event *ev = NULL; demux_control(mpctx->demuxer, DEMUXER_CTRL_GET_NAV_EVENT, &ev); if (!ev) break; switch (ev->event) { case MP_NAV_EVENT_DRAIN: { nav->nav_draining = true; MP_VERBOSE(nav, "drain requested\n"); break; } case MP_NAV_EVENT_RESET_ALL: { mpctx->stop_play = PT_RELOAD_DEMUXER; MP_VERBOSE(nav, "reload\n"); // return immediately. // other events should be handled after reloaded. talloc_free(ev); return; } case MP_NAV_EVENT_RESET: { nav->nav_still_frame = 0; break; } case MP_NAV_EVENT_EOF: nav->nav_eof = true; break; case MP_NAV_EVENT_STILL_FRAME: { int len = ev->u.still_frame.seconds; MP_VERBOSE(nav, "wait for %d seconds\n", len); if (len > 0 && nav->nav_still_frame == 0) nav->nav_still_frame = len; break; } case MP_NAV_EVENT_MENU_MODE: nav->nav_menu = ev->u.menu_mode.enable; if (nav->nav_menu) { mp_input_enable_section(mpctx->input, "discnav-menu", MP_INPUT_ON_TOP); } else { mp_input_disable_section(mpctx->input, "discnav-menu"); } update_state(mpctx); break; case MP_NAV_EVENT_HIGHLIGHT: { pthread_mutex_lock(&nav->osd_lock); MP_VERBOSE(nav, "highlight: %d %d %d - %d %d\n", ev->u.highlight.display, ev->u.highlight.sx, ev->u.highlight.sy, ev->u.highlight.ex, ev->u.highlight.ey); nav->highlight[0] = ev->u.highlight.sx; nav->highlight[1] = ev->u.highlight.sy; nav->highlight[2] = ev->u.highlight.ex; nav->highlight[3] = ev->u.highlight.ey; nav->hi_visible = ev->u.highlight.display; pthread_mutex_unlock(&nav->osd_lock); update_resolution(mpctx); osd_set_nav_highlight(mpctx->osd, mpctx); break; } case MP_NAV_EVENT_OVERLAY: { pthread_mutex_lock(&nav->osd_lock); for (int i = 0; i < 2; i++) { if (nav->overlays[i]) talloc_free(nav->overlays[i]); nav->overlays[i] = talloc_steal(nav, ev->u.overlay.images[i]); } pthread_mutex_unlock(&nav->osd_lock); update_resolution(mpctx); osd_set_nav_highlight(mpctx->osd, mpctx); break; } default: ; // ignore } talloc_free(ev); } update_resolution(mpctx); if (mpctx->stop_play == AT_END_OF_FILE) { if (nav->nav_still_frame > 0) { // gross hack mpctx->time_frame += nav->nav_still_frame; nav->nav_still_frame = -2; } else if (nav->nav_still_frame == -2) { struct mp_nav_cmd inp = {MP_NAV_CMD_SKIP_STILL}; run_stream_control(mpctx, STREAM_CTRL_NAV_CMD, &inp); } } if (nav->nav_draining && mpctx->stop_play == AT_END_OF_FILE) { MP_VERBOSE(nav, "execute drain\n"); struct mp_nav_cmd inp = {MP_NAV_CMD_DRAIN_OK}; run_stream_control(mpctx, STREAM_CTRL_NAV_CMD, &inp); nav->nav_draining = false; run_stream_control(mpctx, STREAM_CTRL_RESUME_CACHE, NULL); } // E.g. keep displaying still frames if (mpctx->stop_play == AT_END_OF_FILE && !nav->nav_eof) mpctx->stop_play = KEEP_PLAYING; }