summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2012-08-26 01:19:42 +0200
committerwm4 <wm4@nowhere>2012-09-18 21:04:45 +0200
commit88728c6fad99fe6c9cc0b77f95c46d6919f0693a (patch)
tree202bba034426f78e3ffcd20a9b9d660a0be8d86a
parent7236ad5ff2dd67e069b3fb2bf9adc1e0f2135e6f (diff)
downloadmpv-88728c6fad99fe6c9cc0b77f95c46d6919f0693a.tar.bz2
mpv-88728c6fad99fe6c9cc0b77f95c46d6919f0693a.tar.xz
core: runtime Matroska edition switching
Add a new slave property which switches the current Matroska edition. Since each edition can define an entirely new timeline, switching the edition will simply restart playback at the beginning of the file with the new edition selected. Add 'E' as new keybinding to step the edition property. DVD titles are still separate. Apparently they work similarly, but I don't have any multi-title DVDs for testing. Also, cdda (for audio CDs) uses the same mechanism as DVDs to report a number of titles, so there seems to be confusion what exactly this mechanism is supposed to do. That's why the edition code is completely separate for now. Remove demuxer.num_titles. It was just a rather useless cache for the return value of the DVD titles related STREAM_CTRL. One rather obscure corner case isn't taken care of: if the ordered chapters file has file local options set, they are reset on playback restart. This is unexpected, because edition switching is meant to behave like seeking back to the beginning of the file.
-rw-r--r--command.c72
-rw-r--r--etc/input.conf1
-rw-r--r--libmpdemux/demux_mkv.c3
-rw-r--r--libmpdemux/demuxer.h3
-rw-r--r--mp_core.h1
-rw-r--r--mplayer.c9
6 files changed, 84 insertions, 5 deletions
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);
}