diff --git a/command.c b/command.c index 065802b6d0..f0b17719db 100644 --- a/command.c +++ b/command.c @@ -434,6 +434,51 @@ static int mp_property_chapter(m_option_t *prop, int action, void *arg, return M_PROPERTY_OK; } +static int mp_property_edition(m_option_t *prop, int action, void *arg, + MPContext *mpctx) +{ + struct MPOpts *opts = &mpctx->opts; + struct demuxer *demuxer = mpctx->master_demuxer; + if (!demuxer) + return M_PROPERTY_UNAVAILABLE; + if (demuxer->num_editions <= 0) + return M_PROPERTY_UNAVAILABLE; + + int edition = demuxer->edition; + + switch (action) { + case M_PROPERTY_GET: + case M_PROPERTY_PRINT: + return m_property_int_ro(prop, action, arg, edition); + case M_PROPERTY_SET: + if (!arg) + return M_PROPERTY_ERROR; + M_PROPERTY_CLAMP(prop, *(int *)arg); + edition = *(int *)arg; + break; + case M_PROPERTY_STEP_UP: + case M_PROPERTY_STEP_DOWN: { + edition += arg ? *(int *)arg : (action == M_PROPERTY_STEP_UP ? 1 : -1); + if (edition < 0) + edition = demuxer->num_editions - 1; + if (edition >= demuxer->num_editions) + edition = 0; + break; + } + default: + return M_PROPERTY_NOT_IMPLEMENTED; + } + + if (edition != demuxer->edition) { + opts->edition_id = edition; + mpctx->stop_play = PT_RESTART; + set_osd_tmsg(mpctx, OSD_MSG_TEXT, 1, opts->osd_duration, + "Playing edition %d of %d.", edition + 1, + demuxer->num_editions); + } + return M_PROPERTY_OK; +} + /// Number of titles in file static int mp_property_titles(m_option_t *prop, int action, void *arg, MPContext *mpctx) @@ -441,10 +486,9 @@ static int mp_property_titles(m_option_t *prop, int action, void *arg, struct demuxer *demuxer = mpctx->master_demuxer; if (!demuxer) return M_PROPERTY_UNAVAILABLE; - if (demuxer->num_titles == 0) - stream_control(demuxer->stream, STREAM_CTRL_GET_NUM_TITLES, - &demuxer->num_titles); - return m_property_int_ro(prop, action, arg, demuxer->num_titles); + int num_titles = 0; + stream_control(demuxer->stream, STREAM_CTRL_GET_NUM_TITLES, &num_titles); + return m_property_int_ro(prop, action, arg, num_titles); } /// Number of chapters in file @@ -457,6 +501,17 @@ static int mp_property_chapters(m_option_t *prop, int action, void *arg, return m_property_int_ro(prop, action, arg, count); } +static int mp_property_editions(m_option_t *prop, int action, void *arg, + MPContext *mpctx) +{ + struct demuxer *demuxer = mpctx->master_demuxer; + if (!demuxer) + return M_PROPERTY_UNAVAILABLE; + if (demuxer->num_editions <= 0) + return M_PROPERTY_UNAVAILABLE; + return m_property_int_ro(prop, action, arg, demuxer->num_editions); +} + /// Current dvd angle (RW) static int mp_property_angle(m_option_t *prop, int action, void *arg, MPContext *mpctx) @@ -1638,10 +1693,13 @@ static const m_option_t mp_properties[] = { M_OPT_MIN, 0, 0, NULL }, { "chapter", mp_property_chapter, CONF_TYPE_INT, M_OPT_MIN, 0, 0, NULL }, + { "edition", mp_property_edition, CONF_TYPE_INT, + M_OPT_MIN, -1, 0, NULL }, { "titles", mp_property_titles, CONF_TYPE_INT, 0, 0, 0, NULL }, { "chapters", mp_property_chapters, CONF_TYPE_INT, 0, 0, 0, NULL }, + { "editions", mp_property_editions, CONF_TYPE_INT }, { "angle", mp_property_angle, CONF_TYPE_INT, CONF_RANGE, -2, 10, NULL }, { "metadata", mp_property_metadata, CONF_TYPE_STRING_LIST, @@ -2110,6 +2168,12 @@ static void show_tracks_on_osd(MPContext *mpctx) res = talloc_asprintf_append(res, "\n"); } + struct demuxer *demuxer = mpctx->master_demuxer; + if (demuxer && demuxer->num_editions > 1) + res = talloc_asprintf_append(res, "\nEdition: %d of %d\n", + demuxer->edition + 1, + demuxer->num_editions); + set_osd_msg(mpctx, OSD_MSG_TEXT, 1, opts->osd_duration, "%s", res); talloc_free(res); } diff --git a/etc/input.conf b/etc/input.conf index a7732acf01..3744df8431 100644 --- a/etc/input.conf +++ b/etc/input.conf @@ -125,6 +125,7 @@ MUTE mute CLOSE_WIN quit ! seek_chapter -1 # skip to previous chapter @ seek_chapter 1 # next +E step_property_osd edition # next edition A switch_angle 1 U stop diff --git a/libmpdemux/demux_mkv.c b/libmpdemux/demux_mkv.c index b5ab880916..3943bff733 100644 --- a/libmpdemux/demux_mkv.c +++ b/libmpdemux/demux_mkv.c @@ -856,6 +856,9 @@ static int demux_mkv_read_chapters(struct demuxer *demuxer) "[mkv] Found %d editions, will play #%d (first is 0).\n", num_editions, selected_edition); + demuxer->num_editions = num_editions; + demuxer->edition = selected_edition; + talloc_free(parse_ctx.talloc_ctx); mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] \\---- [ parsing chapters ] ---------\n"); diff --git a/libmpdemux/demuxer.h b/libmpdemux/demuxer.h index cf81ce988c..f2236c6016 100644 --- a/libmpdemux/demuxer.h +++ b/libmpdemux/demuxer.h @@ -249,7 +249,8 @@ typedef struct demuxer { struct sh_stream **streams; int num_streams; - int num_titles; + int num_editions; + int edition; struct demux_chapter *chapters; int num_chapters; diff --git a/mp_core.h b/mp_core.h index 04a3dac735..ea21752767 100644 --- a/mp_core.h +++ b/mp_core.h @@ -55,6 +55,7 @@ enum stop_play_reason { PT_NEXT_ENTRY, // prepare to play next entry in playlist PT_CURRENT_ENTRY, // prepare to play mpctx->playlist->current PT_STOP, // stop playback, clear playlist + PT_RESTART, // restart previous file PT_QUIT, // stop playback, quit player }; diff --git a/mplayer.c b/mplayer.c index fd409cc27c..f27551cd1b 100644 --- a/mplayer.c +++ b/mplayer.c @@ -516,6 +516,11 @@ static void print_file_properties(struct MPContext *mpctx, const char *filename) } } } + struct demuxer *demuxer = mpctx->master_demuxer; + if (demuxer->num_editions > 1) + mp_msg(MSGT_CPLAYER, MSGL_INFO, + "Playing edition %d of %d (--edition=%d).\n", + demuxer->edition + 1, demuxer->num_editions, demuxer->edition); for (int t = 0; t < STREAM_TYPE_COUNT; t++) { for (int n = 0; n < mpctx->num_tracks; n++) if (mpctx->tracks[n]->type == t) @@ -4023,6 +4028,10 @@ static void play_files(struct MPContext *mpctx) new_entry = playlist_get_next(mpctx->playlist, +1); } else if (mpctx->stop_play == PT_CURRENT_ENTRY) { new_entry = mpctx->playlist->current; + } else if (mpctx->stop_play == PT_RESTART) { + // The same as PT_CURRENT_ENTRY, unless we decide that the current + // playlist entry can be removed during playback. + new_entry = mpctx->playlist->current; } else { // PT_STOP playlist_clear(mpctx->playlist); }