diff options
Diffstat (limited to 'player/command.c')
-rw-r--r-- | player/command.c | 238 |
1 files changed, 177 insertions, 61 deletions
diff --git a/player/command.c b/player/command.c index 098a11d24f..4f2eb4741d 100644 --- a/player/command.c +++ b/player/command.c @@ -54,6 +54,7 @@ #include "options/m_option.h" #include "options/m_property.h" #include "options/m_config_frontend.h" +#include "osdep/getpid.h" #include "video/out/vo.h" #include "video/csputils.h" #include "video/hwdec.h" @@ -154,7 +155,7 @@ static void hook_remove(struct MPContext *mpctx, struct hook_handler *h) return; } } - assert(0); + MP_ASSERT_UNREACHABLE(); } bool mp_hook_test_completion(struct MPContext *mpctx, char *type) @@ -426,6 +427,13 @@ static int mp_property_display_sync_active(void *ctx, struct m_property *prop, return m_property_flag_ro(action, arg, mpctx->display_sync_active); } +static int mp_property_pid(void *ctx, struct m_property *prop, + int action, void *arg) +{ + // 32 bit on linux/windows - which C99 `int' is not guaranteed to hold + return m_property_int64_ro(action, arg, mp_getpid()); +} + /// filename with path (RO) static int mp_property_path(void *ctx, struct m_property *prop, int action, void *arg) @@ -985,7 +993,7 @@ static int parse_node_chapters(struct MPContext *mpctx, } } - mp_notify(mpctx, MPV_EVENT_CHAPTER_CHANGE, NULL); + mp_notify(mpctx, MP_EVENT_CHAPTER_CHANGE, NULL); mp_notify_property(mpctx, "chapter-list"); return M_PROPERTY_OK; @@ -1941,6 +1949,7 @@ static int get_track_entry(int item, int action, void *arg, void *ctx) .unavailable = !track->lang}, {"audio-channels", SUB_PROP_INT(track_channels(track)), .unavailable = track_channels(track) <= 0}, + {"image", SUB_PROP_FLAG(track->image)}, {"albumart", SUB_PROP_FLAG(track->attached_picture)}, {"default", SUB_PROP_FLAG(track->default_track)}, {"forced", SUB_PROP_FLAG(track->forced_track)}, @@ -2067,6 +2076,16 @@ static int property_current_tracks(void *ctx, struct m_property *prop, return M_PROPERTY_UNKNOWN; struct track *t = mpctx->current_track[order][type]; + + if (!t && mpctx->lavfi) { + for (int n = 0; n < mpctx->num_tracks; n++) { + if (mpctx->tracks[n]->type == type && mpctx->tracks[n]->selected) { + t = mpctx->tracks[n]; + break; + } + } + } + if (!t) return M_PROPERTY_UNAVAILABLE; @@ -2322,6 +2341,25 @@ static int mp_property_current_window_scale(void *ctx, struct m_property *prop, if (vid_w < 1 || vid_h < 1) return M_PROPERTY_UNAVAILABLE; + if (params.rotate % 180 == 90 && (vo->driver->caps & VO_CAP_ROTATE90)) + MPSWAP(int, vid_w, vid_h); + + if (vo->monitor_par < 1) { + vid_h = MPCLAMP(vid_h / vo->monitor_par, 1, 16000); + } else { + vid_w = MPCLAMP(vid_w * vo->monitor_par, 1, 16000); + } + + if (action == M_PROPERTY_SET) { + // Also called by update_window_scale as a NULL property. + double scale = *(double *)arg; + int s[2] = {vid_w * scale, vid_h * scale}; + if (s[0] <= 0 || s[1] <= 0) + return M_PROPERTY_INVALID_FORMAT; + vo_control(vo, VOCTRL_SET_UNFS_WINDOW_SIZE, s); + return M_PROPERTY_OK; + } + int s[2]; if (vo_control(vo, VOCTRL_GET_UNFS_WINDOW_SIZE, s) <= 0 || s[0] < 1 || s[1] < 1) @@ -2334,20 +2372,9 @@ static int mp_property_current_window_scale(void *ctx, struct m_property *prop, static void update_window_scale(struct MPContext *mpctx) { - struct vo *vo = mpctx->video_out; - if (!vo) - return; - - struct mp_image_params params = get_video_out_params(mpctx); - int vid_w, vid_h; - mp_image_params_get_dsize(¶ms, &vid_w, &vid_h); - if (vid_w < 1 || vid_h < 1) - return; - double scale = mpctx->opts->vo->window_scale; - int s[2] = {vid_w * scale, vid_h * scale}; - if (s[0] > 0 && s[1] > 0) - vo_control(vo, VOCTRL_SET_UNFS_WINDOW_SIZE, s); + mp_property_current_window_scale(mpctx, (struct m_property *)NULL, + M_PROPERTY_SET, (void*)&scale); } static int mp_property_display_fps(void *ctx, struct m_property *prop, @@ -2404,6 +2431,23 @@ static int mp_property_vsync_jitter(void *ctx, struct m_property *prop, return m_property_double_ro(action, arg, stddev); } +static int mp_property_display_resolution(void *ctx, struct m_property *prop, + int action, void *arg) +{ + MPContext *mpctx = ctx; + struct vo *vo = mpctx->video_out; + if (!vo) + return M_PROPERTY_UNAVAILABLE; + int res[2]; + if (vo_control(vo, VOCTRL_GET_DISPLAY_RES, &res) <= 0) + return M_PROPERTY_UNAVAILABLE; + if (strcmp(prop->name, "display-width") == 0) { + return m_property_int_ro(action, arg, res[0]); + } else { + return m_property_int_ro(action, arg, res[1]); + } +} + static int mp_property_hidpi_scale(void *ctx, struct m_property *prop, int action, void *arg) { @@ -2587,14 +2631,14 @@ static int mp_property_osd_dim(void *ctx, struct m_property *prop, (vo_res.display_par ? vo_res.display_par : 1); struct m_sub_property props[] = { - {"w", SUB_PROP_DOUBLE(vo_res.w)}, - {"h", SUB_PROP_DOUBLE(vo_res.h)}, + {"w", SUB_PROP_INT(vo_res.w)}, + {"h", SUB_PROP_INT(vo_res.h)}, {"par", SUB_PROP_DOUBLE(vo_res.display_par)}, {"aspect", SUB_PROP_DOUBLE(aspect)}, - {"mt", SUB_PROP_DOUBLE(vo_res.mt)}, - {"mb", SUB_PROP_DOUBLE(vo_res.mb)}, - {"ml", SUB_PROP_DOUBLE(vo_res.ml)}, - {"mr", SUB_PROP_DOUBLE(vo_res.mr)}, + {"mt", SUB_PROP_INT(vo_res.mt)}, + {"mb", SUB_PROP_INT(vo_res.mb)}, + {"ml", SUB_PROP_INT(vo_res.ml)}, + {"mr", SUB_PROP_INT(vo_res.mr)}, {0} }; @@ -2805,12 +2849,12 @@ static int mp_property_sub_pos(void *ctx, struct m_property *prop, return mp_property_generic_option(mpctx, prop, action, arg); } -static int mp_property_sub_text(void *ctx, struct m_property *prop, - int action, void *arg) +static int get_sub_text(void *ctx, struct m_property *prop, + int action, void *arg, int sub_index) { int type = *(int *)prop->priv; MPContext *mpctx = ctx; - struct track *track = mpctx->current_track[0][STREAM_SUB]; + struct track *track = mpctx->current_track[sub_index][STREAM_SUB]; struct dec_sub *sub = track ? track->d_sub : NULL; double pts = mpctx->playback_pts; if (!sub || pts == MP_NOPTS_VALUE) @@ -2831,12 +2875,25 @@ static int mp_property_sub_text(void *ctx, struct m_property *prop, return M_PROPERTY_NOT_IMPLEMENTED; } +static int mp_property_sub_text(void *ctx, struct m_property *prop, + int action, void *arg) +{ + return get_sub_text(ctx, prop, action, arg, 0); +} + +static int mp_property_secondary_sub_text(void *ctx, struct m_property *prop, + int action, void *arg) +{ + return get_sub_text(ctx, prop, action, arg, 1); +} + static struct sd_times get_times(void *ctx, struct m_property *prop, int action, void *arg) { struct sd_times res = { .start = MP_NOPTS_VALUE, .end = MP_NOPTS_VALUE }; MPContext *mpctx = ctx; - struct track *track = mpctx->current_track[0][STREAM_SUB]; + int track_ind = *(int *)prop->priv; + struct track *track = mpctx->current_track[track_ind][STREAM_SUB]; struct dec_sub *sub = track ? track->d_sub : NULL; double pts = mpctx->playback_pts; if (!sub || pts == MP_NOPTS_VALUE) @@ -3331,14 +3388,14 @@ static int mp_property_option_info(void *ctx, struct m_property *prop, char **choices = NULL; if (opt->type == &m_option_type_choice) { - struct m_opt_choice_alternatives *alt = opt->priv; + const struct m_opt_choice_alternatives *alt = opt->priv; int num = 0; for ( ; alt->name; alt++) MP_TARRAY_APPEND(NULL, choices, num, alt->name); MP_TARRAY_APPEND(NULL, choices, num, NULL); } if (opt->type == &m_option_type_obj_settings_list) { - struct m_obj_list *objs = opt->priv; + const struct m_obj_list *objs = opt->priv; int num = 0; for (int n = 0; ; n++) { struct m_obj_desc desc = {0}; @@ -3500,6 +3557,7 @@ static int mp_property_script_props(void *ctx, struct m_property *prop, // Base list of properties. This does not include option-mapped properties. static const struct m_property mp_properties_base[] = { // General + {"pid", mp_property_pid}, {"speed", mp_property_playback_speed}, {"audio-speed-correction", mp_property_av_speed_correction, .priv = "a"}, {"video-speed-correction", mp_property_av_speed_correction, .priv = "v"}, @@ -3519,6 +3577,8 @@ static const struct m_property mp_properties_base[] = { {"total-avsync-change", mp_property_total_avsync_change}, {"mistimed-frame-count", mp_property_mistimed_frame_count}, {"vsync-ratio", mp_property_vsync_ratio}, + {"display-width", mp_property_display_resolution}, + {"display-height", mp_property_display_resolution}, {"decoder-frame-drop-count", mp_property_frame_drop_dec}, {"frame-drop-count", mp_property_frame_drop_vo}, {"vo-delayed-frame-count", mp_property_vo_delayed_frame_count}, @@ -3630,10 +3690,18 @@ static const struct m_property mp_properties_base[] = { {"sub-pos", mp_property_sub_pos}, {"sub-text", mp_property_sub_text, .priv = (void *)&(const int){SD_TEXT_TYPE_PLAIN}}, + {"secondary-sub-text", mp_property_secondary_sub_text, + .priv = (void *)&(const int){SD_TEXT_TYPE_PLAIN}}, {"sub-text-ass", mp_property_sub_text, .priv = (void *)&(const int){SD_TEXT_TYPE_ASS}}, - {"sub-start", mp_property_sub_start}, - {"sub-end", mp_property_sub_end}, + {"sub-start", mp_property_sub_start, + .priv = (void *)&(const int){0}}, + {"secondary-sub-start", mp_property_sub_start, + .priv = (void *)&(const int){1}}, + {"sub-end", mp_property_sub_end, + .priv = (void *)&(const int){0}}, + {"secondary-sub-end", mp_property_sub_end, + .priv = (void *)&(const int){1}}, {"vf", mp_property_vf}, {"af", mp_property_af}, @@ -3702,18 +3770,18 @@ static const char *const *const mp_event_property_change[] = { E(MPV_EVENT_END_FILE, "*"), E(MPV_EVENT_FILE_LOADED, "*"), E(MP_EVENT_CHANGE_ALL, "*"), - E(MPV_EVENT_TRACKS_CHANGED, "track-list", "current-tracks"), - E(MPV_EVENT_TRACK_SWITCHED, "track-list", "current-tracks"), + E(MP_EVENT_TRACKS_CHANGED, "track-list", "current-tracks"), + E(MP_EVENT_TRACK_SWITCHED, "track-list", "current-tracks"), E(MPV_EVENT_IDLE, "*"), E(MPV_EVENT_TICK, "time-pos", "audio-pts", "stream-pos", "avsync", "percent-pos", "time-remaining", "playtime-remaining", "playback-time", "estimated-vf-fps", "drop-frame-count", "vo-drop-frame-count", "total-avsync-change", "audio-speed-correction", "video-speed-correction", "vo-delayed-frame-count", "mistimed-frame-count", "vsync-ratio", - "estimated-display-fps", "vsync-jitter", "sub-text", "audio-bitrate", - "video-bitrate", "sub-bitrate", "decoder-frame-drop-count", + "estimated-display-fps", "vsync-jitter", "sub-text", "secondary-sub-text", + "audio-bitrate", "video-bitrate", "sub-bitrate", "decoder-frame-drop-count", "frame-drop-count", "video-frame-info", "vf-metadata", "af-metadata", - "sub-start", "sub-end"), + "sub-start", "sub-end", "secondary-sub-start", "secondary-sub-end"), E(MP_EVENT_DURATION_UPDATE, "duration"), E(MPV_EVENT_VIDEO_RECONFIG, "video-out-params", "video-params", "video-format", "video-codec", "video-bitrate", "dwidth", "dheight", @@ -3726,15 +3794,16 @@ static const char *const *const mp_event_property_change[] = { "audio-out-params", "volume-max", "mixer-active"), E(MPV_EVENT_SEEK, "seeking", "core-idle", "eof-reached"), E(MPV_EVENT_PLAYBACK_RESTART, "seeking", "core-idle", "eof-reached"), - E(MPV_EVENT_METADATA_UPDATE, "metadata", "filtered-metadata", "media-title"), - E(MPV_EVENT_CHAPTER_CHANGE, "chapter", "chapter-metadata"), + E(MP_EVENT_METADATA_UPDATE, "metadata", "filtered-metadata", "media-title"), + E(MP_EVENT_CHAPTER_CHANGE, "chapter", "chapter-metadata"), E(MP_EVENT_CACHE_UPDATE, "demuxer-cache-duration", "demuxer-cache-idle", "paused-for-cache", "demuxer-cache-time", "cache-buffering-state", "cache-speed", "demuxer-cache-state"), E(MP_EVENT_WIN_RESIZE, "current-window-scale", "osd-width", "osd-height", "osd-par", "osd-dimensions"), - E(MP_EVENT_WIN_STATE, "display-names", "display-fps"), + E(MP_EVENT_WIN_STATE, "display-names", "display-fps", "display-width", + "display-height"), E(MP_EVENT_WIN_STATE2, "display-hidpi-scale"), E(MP_EVENT_FOCUS, "focused"), E(MP_EVENT_CHANGE_PLAYLIST, "playlist", "playlist-pos", "playlist-pos-1", @@ -3917,6 +3986,7 @@ static const struct property_osd_display { {"taskbar-progress", "Progress in taskbar"}, {"snap-window", "Snap to screen edges"}, {"ontop", "Stay on top"}, + {"on-all-workspaces", "Visibility on all workspaces"}, {"border", "Border"}, {"framedrop", "Framedrop"}, {"deinterlace", "Deinterlace"}, @@ -3935,6 +4005,9 @@ static const struct property_osd_display { {"sub-visibility", .msg = "Subtitles ${!sub-visibility==yes:hidden}" "${?sub-visibility==yes:visible${?sub==no: (but no subtitles selected)}}"}, + {"secondary-sub-visibility", + .msg = "Secondary Subtitles ${!secondary-sub-visibility==yes:hidden}" + "${?secondary-sub-visibility==yes:visible${?secondary-sid==no: (but no secondary subtitles selected)}}"}, {"sub-forced-only", "Forced sub only"}, {"sub-scale", "Sub Scale"}, {"sub-ass-vsfilter-aspect-compat", "Subtitle VSFilter aspect compat"}, @@ -4115,7 +4188,7 @@ static void recreate_overlays(struct MPContext *mpctx) struct command_ctx *cmd = mpctx->command_ctx; int overlay_next = !cmd->overlay_osd_current; struct sub_bitmaps *new = &cmd->overlay_osd[overlay_next]; - new->format = SUBBITMAP_RGBA; + new->format = SUBBITMAP_BGRA; new->change_id = 1; bool valid = false; @@ -4859,7 +4932,9 @@ static void cmd_add_cycle(void *p) bool is_cycle = !!cmd->priv; char *property = cmd->args[0].v.s; - if (cmd->cmd->repeated && !check_property_autorepeat(property, mpctx)) { + if (cmd->cmd->repeated && !check_property_autorepeat(property, mpctx) && + !(cmd->cmd->flags & MP_ALLOW_REPEAT) /* "repeatable" prefix */ ) + { MP_VERBOSE(mpctx, "Dropping command '%s' from auto-repeated key.\n", cmd->cmd->original); return; @@ -4981,13 +5056,14 @@ static void cmd_sub_step_seek(void *p) struct mp_cmd_ctx *cmd = p; struct MPContext *mpctx = cmd->mpctx; bool step = *(bool *)cmd->priv; + int track_ind = cmd->args[1].v.i; if (!mpctx->playback_initialized) { cmd->success = false; return; } - struct track *track = mpctx->current_track[0][STREAM_SUB]; + struct track *track = mpctx->current_track[track_ind][STREAM_SUB]; struct dec_sub *sub = track ? track->d_sub : NULL; double refpts = get_current_time(mpctx); if (sub && refpts != MP_NOPTS_VALUE) { @@ -5097,7 +5173,7 @@ static void cmd_loadlist(void *p) struct mp_cmd_ctx *cmd = p; struct MPContext *mpctx = cmd->mpctx; char *filename = cmd->args[0].v.s; - bool append = cmd->args[1].v.i; + int append = cmd->args[1].v.i; struct playlist *pl = playlist_parse_file(filename, cmd->abort->cancel, mpctx->global); @@ -5114,7 +5190,7 @@ static void cmd_loadlist(void *p) if (!new) new = playlist_get_first(mpctx->playlist); - if (!append && new) + if ((!append || (append == 2 && !mpctx->playlist->current)) && new) mp_set_playlist_entry(mpctx, new); struct mpv_node *res = &cmd->result; @@ -5240,6 +5316,8 @@ static void cmd_track_add(void *p) struct mp_cmd_ctx *cmd = p; struct MPContext *mpctx = cmd->mpctx; int type = *(int *)cmd->priv; + bool is_albumart = type == STREAM_VIDEO && + cmd->args[4].v.i; if (mpctx->stop_play) { cmd->success = false; @@ -5259,7 +5337,7 @@ static void cmd_track_add(void *p) } } int first = mp_add_external_file(mpctx, cmd->args[0].v.s, type, - cmd->abort->cancel); + cmd->abort->cancel, is_albumart); if (first < 0) { cmd->success = false; return; @@ -5322,8 +5400,10 @@ static void cmd_track_reload(void *p) if (t && t->is_external && t->external_filename) { char *filename = talloc_strdup(NULL, t->external_filename); + bool is_albumart = t->attached_picture; mp_remove_track(mpctx, t); - nt_num = mp_add_external_file(mpctx, filename, type, cmd->abort->cancel); + nt_num = mp_add_external_file(mpctx, filename, type, cmd->abort->cancel, + is_albumart); talloc_free(filename); } @@ -6015,10 +6095,28 @@ const struct mp_cmd_def mp_cmds[] = { }, { "playlist-shuffle", cmd_playlist_shuffle, }, { "playlist-unshuffle", cmd_playlist_unshuffle, }, - { "sub-step", cmd_sub_step_seek, { {"skip", OPT_INT(v.i)} }, - .allow_auto_repeat = true, .priv = &(const bool){true} }, - { "sub-seek", cmd_sub_step_seek, { {"skip", OPT_INT(v.i)} }, - .allow_auto_repeat = true, .priv = &(const bool){false} }, + { "sub-step", cmd_sub_step_seek, + { + {"skip", OPT_INT(v.i)}, + {"flags", OPT_CHOICE(v.i, + {"primary", 0}, + {"secondary", 1}), + OPTDEF_INT(0)}, + }, + .allow_auto_repeat = true, + .priv = &(const bool){true} + }, + { "sub-seek", cmd_sub_step_seek, + { + {"skip", OPT_INT(v.i)}, + {"flags", OPT_CHOICE(v.i, + {"primary", 0}, + {"secondary", 1}), + OPTDEF_INT(0)}, + }, + .allow_auto_repeat = true, + .priv = &(const bool){false} + }, { "print-text", cmd_print_text, { {"text", OPT_STRING(v.s)} }, .is_noisy = true, .allow_auto_repeat = true }, { "show-text", cmd_show_text, @@ -6070,6 +6168,7 @@ const struct mp_cmd_def mp_cmds[] = { .flags = MP_CMD_OPT_ARG}, {"title", OPT_STRING(v.s), .flags = MP_CMD_OPT_ARG}, {"lang", OPT_STRING(v.s), .flags = MP_CMD_OPT_ARG}, + {"albumart", OPT_FLAG(v.i), .flags = MP_CMD_OPT_ARG}, }, .priv = &(const int){STREAM_VIDEO}, .spawn_thread = true, @@ -6165,7 +6264,10 @@ const struct mp_cmd_def mp_cmds[] = { { "loadlist", cmd_loadlist, { {"url", OPT_STRING(v.s)}, - {"flags", OPT_CHOICE(v.i, {"replace", 0}, {"append", 1}), + {"flags", OPT_CHOICE(v.i, + {"replace", 0}, + {"append", 1}, + {"append-play", 2}), .flags = MP_CMD_OPT_ARG}, }, .spawn_thread = true, @@ -6471,6 +6573,25 @@ static void update_priority(struct MPContext *mpctx) #endif } +static void update_track_switch(struct MPContext *mpctx, int order, int type) +{ + if (!mpctx->playback_initialized) + return; + + int tid = mpctx->opts->stream_id[order][type]; + struct track *track; + if (tid == -1) { + // If "auto" reset to default track selection + track = select_default_track(mpctx, order, type); + mark_track_selection(mpctx, order, type, -1); + } else { + track = mp_track_by_tid(mpctx, type, tid); + } + mp_switch_track_n(mpctx, order, type, track, (tid == -1) ? 0 : FLAG_MARK_SELECTION); + print_track_list(mpctx, "Track switched:"); + mp_wakeup_core(mpctx); +} + void mp_option_change_callback(void *ctx, struct m_config_option *co, int flags, bool self_update) { @@ -6482,9 +6603,6 @@ void mp_option_change_callback(void *ctx, struct m_config_option *co, int flags, if (co) mp_notify_property(mpctx, co->name); - if (opt_ptr == &opts->pause) - mp_notify(mpctx, opts->pause ? MPV_EVENT_PAUSE : MPV_EVENT_UNPAUSE, 0); - if (self_update) return; @@ -6629,15 +6747,8 @@ void mp_option_change_callback(void *ctx, struct m_config_option *co, int flags, for (int type = 0; type < STREAM_TYPE_COUNT; type++) { for (int order = 0; order < num_ptracks[type]; order++) { - if (opt_ptr == &opts->stream_id[order][type] && - mpctx->playback_initialized) - { - struct track *track = - mp_track_by_tid(mpctx, type, opts->stream_id[order][type]); - mp_switch_track_n(mpctx, order, type, track, FLAG_MARK_SELECTION); - print_track_list(mpctx, "Track switched:"); - mp_wakeup_core(mpctx); - } + if (opt_ptr == &opts->stream_id[order][type]) + update_track_switch(mpctx, order, type); } } @@ -6646,6 +6757,11 @@ void mp_option_change_callback(void *ctx, struct m_config_option *co, int flags, if (opt_ptr == &opts->vo->taskbar_progress) update_vo_playback_state(mpctx); + + if (opt_ptr == &opts->image_display_duration && mpctx->vo_chain + && mpctx->vo_chain->is_sparse && !mpctx->ao_chain + && mpctx->video_status == STATUS_DRAINING) + mpctx->time_frame = opts->image_display_duration; } void mp_notify_property(struct MPContext *mpctx, const char *property) |