changeset 25129:c04b64054255

Support select subtitle by source, add 4 properties: 1. sub_source for current sub source (sub file, vobsub, or from demuxer). 2. sub_file for all subtitles from files. 3. sub_vobsub for all subtitles from vobsub. 4. sub_demux for all subtitles from demuxer. Now mplayer can supply a stable and clear interface to external programs using mplayer in slave mode to select a subtitle by its source and its unique id for that source printed by mplayer using -identify parameter.
author ulion
date Sun, 25 Nov 2007 04:09:04 +0000
parents b3aa123be8f5
children 948560eef6b5
files DOCS/tech/slave.txt command.c input/input.c input/input.h
diffstat 4 files changed, 228 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/DOCS/tech/slave.txt	Sat Nov 24 13:14:40 2007 +0000
+++ b/DOCS/tech/slave.txt	Sun Nov 25 04:09:04 2007 +0000
@@ -295,6 +295,34 @@
     Cycle through the available subtitles if [value] is omitted or less
     than -1. Supported subtitle sources are -sub options on the command
     line, VOBsubs, DVD subtitles, and Ogg and Matroska text streams.
+    This command is mainly for cycling all subtitles, if you want to set
+    a specific subtitle, use sub_file, sub_vob, or sub_demux.
+
+sub_source [source]
+    Display first subtitle from [source]. Here [source] is an integer:
+    SUB_SOURCE_SUBS   (0) for file subs
+    SUB_SOURCE_VOBSUB (1) for VOBsub files
+    SUB_SOURCE_DEMUX  (2) for subtitle embedded in the media file or DVD subs.
+    If [source] is -1, will turn off subtitle display. If [source] less than -1,
+    will cycle between the first subtitle of each currently available sources.
+
+sub_file [value]
+    Display subtitle specifid by [value] for file subs. The [value] is
+    corresponding to ID_FILE_SUB_ID values reported by '-identify'.
+    If [value] is -1, will turn off subtitle display. If [value] less than -1,
+    will cycle all file subs.
+
+sub_vob [value]
+    Display subtitle specifid by [value] for vobsubs. The [value] is
+    corresponding to ID_VOBSUB_ID values reported by '-identify'.
+    If [value] is -1, will turn off subtitle display. If [value] less than -1,
+    will cycle all vobsubs.
+
+sub_demux [value]
+    Display subtitle specifid by [value] for subtitles from DVD or embedded
+    in media file. The [value] is corresponding to ID_SUBTITLE_ID values
+    reported by '-identify'. If [value] is -1, will turn off subtitle display.
+    If [value] less than -1, will cycle all DVD subs or embedded subs.
 
 sub_scale <value> [abs]
     Adjust the subtitle size by +/- <value> or set it to <value> when [abs]
@@ -465,6 +493,10 @@
 switch_video       int       -2      255     X   X   X    select video stream
 switch_program     int       -1      65535   X   X   X    (see TAB default keybind)
 sub                int       -1              X   X   X    select subtitle stream
+sub_source         int       -1      2       X   X   X    select subtitle source
+sub_file           int       -1              X   X   X    select file subtitles
+sub_vob            int       -1              X   X   X    select vobsubs
+sub_demux          int       -1              X   X   X    select subs from demux
 sub_delay          float                     X   X   X
 sub_pos            int       0       100     X   X   X    subtitle position
 sub_alignment      int       0       2       X   X   X    subtitle alignment
--- a/command.c	Sat Nov 24 13:14:40 2007 +0000
+++ b/command.c	Sun Nov 25 04:09:04 2007 +0000
@@ -88,14 +88,14 @@
 	   vo_dheight, vo_fs);
 }
 
-static int sub_source(MPContext * mpctx)
+static int sub_source_by_pos(MPContext * mpctx, int pos)
 {
     int source = -1;
     int top = -1;
     int i;
     for (i = 0; i < SUB_SOURCES; i++) {
 	int j = mpctx->global_sub_indices[i];
-	if ((j >= 0) && (j > top) && (mpctx->global_sub_pos >= j)) {
+	if ((j >= 0) && (j > top) && (pos >= j)) {
 	    source = i;
 	    top = j;
 	}
@@ -103,6 +103,11 @@
     return source;
 }
 
+static int sub_source(MPContext * mpctx)
+{
+    return sub_source_by_pos(mpctx, mpctx->global_sub_pos);
+}
+
 /**
  * \brief Log the currently displayed subtitle to a file
  *
@@ -1363,6 +1368,175 @@
     return M_PROPERTY_OK;
 }
 
+/// Selected sub source (RW)
+static int mp_property_sub_source(m_option_t * prop, int action, void *arg,
+                                  MPContext * mpctx)
+{
+    int source;
+    if (!mpctx->sh_video || mpctx->global_sub_size <= 0)
+        return M_PROPERTY_UNAVAILABLE;
+
+    switch (action) {
+    case M_PROPERTY_GET:
+        if (!arg)
+            return M_PROPERTY_ERROR;
+        *(int *) arg = sub_source(mpctx);
+        return M_PROPERTY_OK;
+    case M_PROPERTY_PRINT:
+        if (!arg)
+            return M_PROPERTY_ERROR;
+        *(char **) arg = malloc(64);
+        (*(char **) arg)[63] = 0;
+        switch (sub_source(mpctx))
+        {
+        case SUB_SOURCE_SUBS:
+            snprintf(*(char **) arg, 63, MSGTR_SubSourceFile);
+            break;
+        case SUB_SOURCE_VOBSUB:
+            snprintf(*(char **) arg, 63, MSGTR_SubSourceVobsub);
+            break;
+        case SUB_SOURCE_DEMUX:
+            snprintf(*(char **) arg, 63, MSGTR_SubSourceDemux);
+            break;
+        default:
+            snprintf(*(char **) arg, 63, MSGTR_Disabled);
+        }
+        return M_PROPERTY_OK;
+    case M_PROPERTY_SET:
+        if (!arg)
+            return M_PROPERTY_ERROR;
+        M_PROPERTY_CLAMP(prop, *(int*)arg);
+        if (*(int *) arg < 0)
+            mpctx->global_sub_pos = -1;
+        else if (*(int *) arg != sub_source(mpctx)) {
+            if (*(int *) arg != sub_source_by_pos(mpctx, mpctx->global_sub_indices[*(int *) arg]))
+                return M_PROPERTY_UNAVAILABLE;
+            mpctx->global_sub_pos = mpctx->global_sub_indices[*(int *) arg];
+        }
+        break;
+    case M_PROPERTY_STEP_UP:
+    case M_PROPERTY_STEP_DOWN: {
+        int step_all = (arg && *(int*)arg != 0 ? *(int*)arg : 1)
+                       * (action == M_PROPERTY_STEP_UP ? 1 : -1);
+        int step = (step_all > 0) ? 1 : -1;
+        int cur_source = sub_source(mpctx);
+        source = cur_source;
+        while (step_all) {
+            source += step;
+            if (source >= SUB_SOURCES)
+                source = -1;
+            else if (source < -1)
+                source = SUB_SOURCES - 1;
+            if (source == cur_source || source == -1 ||
+                    source == sub_source_by_pos(mpctx, mpctx->global_sub_indices[source]))
+                step_all -= step;
+        }
+        if (source == cur_source)
+            return M_PROPERTY_OK;
+        if (source == -1)
+            mpctx->global_sub_pos = -1;
+        else
+            mpctx->global_sub_pos = mpctx->global_sub_indices[source];
+        break;
+    }
+    default:
+        return M_PROPERTY_NOT_IMPLEMENTED;
+    }
+    --mpctx->global_sub_pos;
+    return mp_property_sub(prop, M_PROPERTY_STEP_UP, NULL, mpctx);
+}
+
+/// Selected subtitles from specific source (RW)
+static int mp_property_sub_by_type(m_option_t * prop, int action, void *arg,
+                                   MPContext * mpctx)
+{
+    int source, is_cur_source, offset;
+    if (!mpctx->sh_video || mpctx->global_sub_size <= 0)
+        return M_PROPERTY_UNAVAILABLE;
+
+    if (!strcmp(prop->name, "sub_file"))
+        source = SUB_SOURCE_SUBS;
+    else if (!strcmp(prop->name, "sub_vob"))
+        source = SUB_SOURCE_VOBSUB;
+    else if (!strcmp(prop->name, "sub_demux"))
+        source = SUB_SOURCE_DEMUX;
+    else
+        return M_PROPERTY_ERROR;
+
+    offset = mpctx->global_sub_indices[source];
+    if (offset < 0 || source != sub_source_by_pos(mpctx, offset))
+        return M_PROPERTY_UNAVAILABLE;
+
+    is_cur_source = sub_source(mpctx) == source;
+    switch (action) {
+    case M_PROPERTY_GET:
+        if (!arg)
+            return M_PROPERTY_ERROR;
+        *(int *) arg = (is_cur_source) ? mpctx->global_sub_pos - offset : -1;
+        return M_PROPERTY_OK;
+    case M_PROPERTY_PRINT:
+        if (!arg)
+            return M_PROPERTY_ERROR;
+        if (is_cur_source)
+            return mp_property_sub(prop, M_PROPERTY_PRINT, arg, mpctx);
+        *(char **) arg = malloc(64);
+        (*(char **) arg)[63] = 0;
+        snprintf(*(char **) arg, 63, MSGTR_Disabled);
+        return M_PROPERTY_OK;
+    case M_PROPERTY_SET:
+        if (!arg)
+            return M_PROPERTY_ERROR;
+        if (*(int *) arg >= 0) {
+            mpctx->global_sub_pos = offset + *(int *) arg;
+            if (mpctx->global_sub_pos >= mpctx->global_sub_size
+                    || sub_source(mpctx) != source) {
+                mpctx->global_sub_pos = -1;
+                *(int *) arg = -1;
+            }
+        }
+        else
+            mpctx->global_sub_pos = -1;
+        break;
+    case M_PROPERTY_STEP_UP:
+    case M_PROPERTY_STEP_DOWN: {
+        int step_all = (arg && *(int*)arg != 0 ? *(int*)arg : 1)
+                       * (action == M_PROPERTY_STEP_UP ? 1 : -1);
+        int step = (step_all > 0) ? 1 : -1;
+        int max_sub_pos_for_source = -1;
+        if (!is_cur_source)
+            mpctx->global_sub_pos = -1;
+        while (step_all) {
+            if (mpctx->global_sub_pos == -1) {
+                if (step > 0)
+                    mpctx->global_sub_pos = offset;
+                else if (max_sub_pos_for_source == -1) {
+                    // Find max pos for specific source
+                    mpctx->global_sub_pos = mpctx->global_sub_size - 1;
+                    while (mpctx->global_sub_pos >= 0
+                            && sub_source(mpctx) != source)
+                        --mpctx->global_sub_pos;
+                }
+                else
+                    mpctx->global_sub_pos = max_sub_pos_for_source;
+            }
+            else {
+                mpctx->global_sub_pos += step;
+                if (mpctx->global_sub_pos < offset ||
+                        mpctx->global_sub_pos >= mpctx->global_sub_size ||
+                        sub_source(mpctx) != source)
+                    mpctx->global_sub_pos = -1;
+            }
+            step_all -= step;
+        }
+        break;
+    }
+    default:
+        return M_PROPERTY_NOT_IMPLEMENTED;
+    }
+    --mpctx->global_sub_pos;
+    return mp_property_sub(prop, M_PROPERTY_STEP_UP, NULL, mpctx);
+}
+
 /// Subtitle delay (RW)
 static int mp_property_sub_delay(m_option_t * prop, int action, void *arg,
 				 MPContext * mpctx)
@@ -1702,6 +1876,14 @@
     // Subs
     { "sub", mp_property_sub, CONF_TYPE_INT,
      M_OPT_MIN, -1, 0, NULL },
+    { "sub_source", mp_property_sub_source, CONF_TYPE_INT,
+     M_OPT_RANGE, -1, SUB_SOURCES - 1, NULL },
+    { "sub_vob", mp_property_sub_by_type, CONF_TYPE_INT,
+     M_OPT_MIN, -1, 0, NULL },
+    { "sub_demux", mp_property_sub_by_type, CONF_TYPE_INT,
+     M_OPT_MIN, -1, 0, NULL },
+    { "sub_file", mp_property_sub_by_type, CONF_TYPE_INT,
+     M_OPT_MIN, -1, 0, NULL },
     { "sub_delay", mp_property_sub_delay, CONF_TYPE_FLOAT,
      0, 0, 0, NULL },
     { "sub_pos", mp_property_sub_pos, CONF_TYPE_INT,
@@ -1830,6 +2012,10 @@
     { "vsync", MP_CMD_SWITCH_VSYNC, 1, 0, -1, MSGTR_VSyncStatus },
 	// subs
     { "sub", MP_CMD_SUB_SELECT, 1, 0, -1, MSGTR_SubSelectStatus },
+    { "sub_source", MP_CMD_SUB_SOURCE, 1, 0, -1, MSGTR_SubSourceStatus },
+    { "sub_vob", MP_CMD_SUB_VOB, 1, 0, -1, MSGTR_SubSelectStatus },
+    { "sub_demux", MP_CMD_SUB_DEMUX, 1, 0, -1, MSGTR_SubSelectStatus },
+    { "sub_file", MP_CMD_SUB_FILE, 1, 0, -1, MSGTR_SubSelectStatus },
     { "sub_pos", MP_CMD_SUB_POS, 0, 0, -1, MSGTR_SubPosStatus },
     { "sub_alignment", MP_CMD_SUB_ALIGNMENT, 1, 0, -1, MSGTR_SubAlignStatus },
     { "sub_delay", MP_CMD_SUB_DELAY, 0, 0, OSD_MSG_SUB_DELAY, MSGTR_SubDelayStatus },
--- a/input/input.c	Sat Nov 24 13:14:40 2007 +0000
+++ b/input/input.c	Sun Nov 25 04:09:04 2007 +0000
@@ -92,6 +92,10 @@
   { MP_CMD_SUB_REMOVE, "sub_remove", 0, { {MP_CMD_ARG_INT,{-1}}, {-1,{0}} } },
   { MP_CMD_SUB_SELECT, "vobsub_lang", 0, { { MP_CMD_ARG_INT,{-2} }, {-1,{0}} } }, // for compatibility
   { MP_CMD_SUB_SELECT, "sub_select", 0, { { MP_CMD_ARG_INT,{-2} }, {-1,{0}} } },
+  { MP_CMD_SUB_SOURCE, "sub_source", 0, { { MP_CMD_ARG_INT,{-2} }, {-1,{0}} } },
+  { MP_CMD_SUB_VOB, "sub_vob", 0, { { MP_CMD_ARG_INT,{-2} }, {-1,{0}} } },
+  { MP_CMD_SUB_DEMUX, "sub_demux", 0, { { MP_CMD_ARG_INT,{-2} }, {-1,{0}} } },
+  { MP_CMD_SUB_FILE, "sub_file", 0, { { MP_CMD_ARG_INT,{-2} }, {-1,{0}} } },
   { MP_CMD_SUB_LOG, "sub_log", 0, { {-1,{0}} } },
   { MP_CMD_SUB_SCALE, "sub_scale",1, { {MP_CMD_ARG_FLOAT,{0}}, {MP_CMD_ARG_INT,{0}}, {-1,{0}} } },
   { MP_CMD_GET_PERCENT_POS, "get_percent_pos", 0, { {-1,{0}} } },
--- a/input/input.h	Sat Nov 24 13:14:40 2007 +0000
+++ b/input/input.h	Sun Nov 25 04:09:04 2007 +0000
@@ -99,6 +99,10 @@
 #define MP_CMD_TV_TELETEXT_ADD_DEC 98
 #define MP_CMD_TV_TELETEXT_GO_LINK 99
 #define MP_CMD_TV_START_SCAN 100
+#define MP_CMD_SUB_SOURCE 101
+#define MP_CMD_SUB_FILE 102
+#define MP_CMD_SUB_VOB 103
+#define MP_CMD_SUB_DEMUX 104
 
 #define MP_CMD_GUI_EVENTS       5000
 #define MP_CMD_GUI_LOADFILE     5001