Beispiel #1
0
// Allocate state and enable navigation features. Must happen before
// initializing cache, because the cache would read data. Since stream_dvdnav is
// in a mode which skips all transitions on reading data (before enabling
// navigation), this would skip some menu screens.
void mp_nav_init(struct MPContext *mpctx)
{
    assert(!mpctx->nav_state);

    // dvdnav is interactive
    if (mpctx->encode_lavc_ctx)
        return;

    struct mp_nav_cmd inp = {MP_NAV_CMD_ENABLE};
    if (stream_control(mpctx->stream, STREAM_CTRL_NAV_CMD, &inp) < 1)
        return;

    mpctx->nav_state = talloc_zero(NULL, struct mp_nav_state);
    mpctx->nav_state->log = mp_log_new(mpctx->nav_state, mpctx->log, "discnav");

    MP_VERBOSE(mpctx->nav_state, "enabling\n");

    mp_input_enable_section(mpctx->input, "discnav", 0);
    mp_input_set_section_mouse_area(mpctx->input, "discnav-menu",
                                    INT_MIN, INT_MIN, INT_MAX, INT_MAX);
}
Beispiel #2
0
// Allocate state and enable navigation features. Must happen before
// initializing cache, because the cache would read data. Since stream_dvdnav is
// in a mode which skips all transitions on reading data (before enabling
// navigation), this would skip some menu screens.
void mp_nav_init(struct MPContext *mpctx)
{
    assert(!mpctx->nav_state);

    // dvdnav is interactive
    if (mpctx->encode_lavc_ctx)
        return;

    struct mp_nav_cmd inp = {MP_NAV_CMD_ENABLE};
    if (run_stream_control(mpctx, STREAM_CTRL_NAV_CMD, &inp) < 1)
        return;

    mpctx->nav_state = talloc_zero(NULL, struct mp_nav_state);
    mpctx->nav_state->log = mp_log_new(mpctx->nav_state, mpctx->log, "discnav");
    pthread_mutex_init(&mpctx->nav_state->osd_lock, NULL);

    MP_VERBOSE(mpctx->nav_state, "enabling\n");

    mp_input_enable_section(mpctx->input, "discnav",
                MP_INPUT_ALLOW_VO_DRAGGING | MP_INPUT_ALLOW_HIDE_CURSOR);

    update_state(mpctx);
    update_mouse_on_button(mpctx);
}
Beispiel #3
0
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;
}