diff --git a/DOCS/tech/slave.txt b/DOCS/tech/slave.txt index b732058aa1..d1d44bab53 100644 --- a/DOCS/tech/slave.txt +++ b/DOCS/tech/slave.txt @@ -295,6 +295,34 @@ sub_select [value] 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 [abs] Adjust the subtitle size by +/- or set it to when [abs] @@ -465,6 +493,10 @@ aspect float X 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 diff --git a/command.c b/command.c index 52314bc19c..be5c1ebb0e 100644 --- a/command.c +++ b/command.c @@ -88,14 +88,14 @@ static void rescale_input_coordinates(int ix, int iy, double *dx, double *dy) 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 @@ static int sub_source(MPContext * mpctx) 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 @@ static int mp_property_sub(m_option_t * prop, int action, void *arg, 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 @@ static m_option_t mp_properties[] = { // 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 @@ static struct { { "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 }, diff --git a/input/input.c b/input/input.c index 835b97c916..35292aa061 100644 --- a/input/input.c +++ b/input/input.c @@ -92,6 +92,10 @@ static mp_cmd_t mp_cmds[] = { { 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}} } }, diff --git a/input/input.h b/input/input.h index 469ad48713..3dc7598f64 100644 --- a/input/input.h +++ b/input/input.h @@ -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