summaryrefslogtreecommitdiffstats
path: root/player
diff options
context:
space:
mode:
Diffstat (limited to 'player')
-rw-r--r--player/command.c75
-rw-r--r--player/command.h1
-rw-r--r--player/configfiles.c17
-rw-r--r--player/core.h4
-rw-r--r--player/external_files.c28
-rw-r--r--player/javascript.c49
-rw-r--r--player/javascript/defaults.js1
-rw-r--r--player/loadfile.c17
-rw-r--r--player/lua.c11
-rw-r--r--player/lua/console.lua14
-rw-r--r--player/lua/defaults.lua5
-rw-r--r--player/lua/ytdl_hook.lua11
-rw-r--r--player/playloop.c4
13 files changed, 188 insertions, 49 deletions
diff --git a/player/command.c b/player/command.c
index e55e6e46d9..098a11d24f 100644
--- a/player/command.c
+++ b/player/command.c
@@ -2621,6 +2621,34 @@ static int mp_property_osd_ass(void *ctx, struct m_property *prop,
return m_property_read_sub(props, action, arg);
}
+static int mp_property_mouse_pos(void *ctx, struct m_property *prop,
+ int action, void *arg)
+{
+ MPContext *mpctx = ctx;
+
+ switch (action) {
+ case M_PROPERTY_GET_TYPE:
+ *(struct m_option *)arg = (struct m_option){.type = CONF_TYPE_NODE};
+ return M_PROPERTY_OK;
+
+ case M_PROPERTY_GET: {
+ struct mpv_node node;
+ int x, y, hover;
+ mp_input_get_mouse_pos(mpctx->input, &x, &y, &hover);
+
+ node_init(&node, MPV_FORMAT_NODE_MAP, NULL);
+ node_map_add_int64(&node, "x", x);
+ node_map_add_int64(&node, "y", y);
+ node_map_add_flag(&node, "hover", hover);
+ *(struct mpv_node *)arg = node;
+
+ return M_PROPERTY_OK;
+ }
+ }
+
+ return M_PROPERTY_NOT_IMPLEMENTED;
+}
+
/// Video fps (RO)
static int mp_property_fps(void *ctx, struct m_property *prop,
int action, void *arg)
@@ -3591,6 +3619,8 @@ static const struct m_property mp_properties_base[] = {
{"osd-sym-cc", mp_property_osd_sym},
{"osd-ass-cc", mp_property_osd_ass},
+ {"mouse-pos", mp_property_mouse_pos},
+
// Subs
{"sid", property_switch_track, .priv = (void *)(const int[]){0, STREAM_SUB}},
{"secondary-sid", property_switch_track,
@@ -3682,7 +3712,8 @@ static const char *const *const mp_event_property_change[] = {
"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",
- "frame-drop-count", "video-frame-info", "vf-metadata", "af-metadata"),
+ "frame-drop-count", "video-frame-info", "vf-metadata", "af-metadata",
+ "sub-start", "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",
@@ -3709,6 +3740,7 @@ static const char *const *const mp_event_property_change[] = {
E(MP_EVENT_CHANGE_PLAYLIST, "playlist", "playlist-pos", "playlist-pos-1",
"playlist-count", "playlist/count", "playlist-current-pos",
"playlist-playing-pos"),
+ E(MP_EVENT_INPUT_PROCESSED, "mouse-pos"),
E(MP_EVENT_CORE_IDLE, "core-idle", "eof-reached"),
};
#undef E
@@ -5690,14 +5722,41 @@ static void cmd_write_watch_later_config(void *p)
mp_write_watch_later_conf(mpctx);
}
+static void cmd_delete_watch_later_config(void *p)
+{
+ struct mp_cmd_ctx *cmd = p;
+ struct MPContext *mpctx = cmd->mpctx;
+
+ char *filename = cmd->args[0].v.s;
+ if (filename && !*filename)
+ filename = NULL;
+ mp_delete_watch_later_conf(mpctx, filename);
+}
+
static void cmd_mouse(void *p)
{
struct mp_cmd_ctx *cmd = p;
struct MPContext *mpctx = cmd->mpctx;
+ int pre_key = 0;
const int x = cmd->args[0].v.i, y = cmd->args[1].v.i;
int button = cmd->args[2].v.i;
+
+ if (mpctx->video_out && mpctx->video_out->config_ok) {
+ int oldx, oldy, oldhover;
+ mp_input_get_mouse_pos(mpctx->input, &oldx, &oldy, &oldhover);
+ struct mp_osd_res vo_res = osd_get_vo_res(mpctx->osd);
+
+ // TODO: VOs don't send outside positions. should we abort if outside?
+ int hover = x >= 0 && y >= 0 && x < vo_res.w && y < vo_res.h;
+
+ if (vo_res.w && vo_res.h && hover != oldhover)
+ pre_key = hover ? MP_KEY_MOUSE_ENTER : MP_KEY_MOUSE_LEAVE;
+ }
+
if (button == -1) {// no button
+ if (pre_key)
+ mp_input_put_key_artificial(mpctx->input, pre_key);
mp_input_set_mouse_pos_artificial(mpctx->input, x, y);
return;
}
@@ -5714,6 +5773,8 @@ static void cmd_mouse(void *p)
return;
}
button += dbc ? MP_MBTN_DBL_BASE : MP_MBTN_BASE;
+ if (pre_key)
+ mp_input_put_key_artificial(mpctx->input, pre_key);
mp_input_set_mouse_pos_artificial(mpctx->input, x, y);
mp_input_put_key_artificial(mpctx->input, button);
}
@@ -6240,6 +6301,8 @@ const struct mp_cmd_def mp_cmds[] = {
},
{ "write-watch-later-config", cmd_write_watch_later_config },
+ { "delete-watch-later-config", cmd_delete_watch_later_config,
+ {{"filename", OPT_STRING(v.s), .flags = MP_CMD_OPT_ARG} }},
{ "mouse", cmd_mouse, { {"x", OPT_INT(v.i)},
{"y", OPT_INT(v.i)},
@@ -6462,6 +6525,16 @@ void mp_option_change_callback(void *ctx, struct m_config_option *co, int flags,
mpctx->ipc_ctx = mp_init_ipc(mpctx->clients, mpctx->global);
}
+ if (opt_ptr == &opts->vo->video_driver_list) {
+ struct track *track = mpctx->current_track[0][STREAM_VIDEO];
+ uninit_video_out(mpctx);
+ reinit_video_chain(mpctx);
+ if (track)
+ reselect_demux_stream(mpctx, track, true);
+
+ mp_wakeup_core(mpctx);
+ }
+
if (flags & UPDATE_AUDIO)
reload_audio_output(mpctx);
diff --git a/player/command.h b/player/command.h
index c47ed40f1d..b45e616497 100644
--- a/player/command.h
+++ b/player/command.h
@@ -102,6 +102,7 @@ enum {
MP_EVENT_CHANGE_PLAYLIST,
MP_EVENT_CORE_IDLE,
MP_EVENT_DURATION_UPDATE,
+ MP_EVENT_INPUT_PROCESSED,
};
bool mp_hook_test_completion(struct MPContext *mpctx, char *type);
diff --git a/player/configfiles.c b/player/configfiles.c
index 0150133dbd..3930cf2139 100644
--- a/player/configfiles.c
+++ b/player/configfiles.c
@@ -433,6 +433,23 @@ exit:
talloc_free(conffile);
}
+void mp_delete_watch_later_conf(struct MPContext *mpctx, const char *file)
+{
+ if (!file) {
+ struct playlist_entry *cur = mpctx->playing;
+ if (!cur)
+ return;
+ file = cur->filename;
+ if (!file)
+ return;
+ }
+
+ char *fname = mp_get_playback_resume_config_filename(mpctx, file);
+ if (fname)
+ unlink(fname);
+ talloc_free(fname);
+}
+
void mp_load_playback_resume(struct MPContext *mpctx, const char *file)
{
if (!mpctx->opts->position_resume)
diff --git a/player/core.h b/player/core.h
index aab408e92c..f2f0a15a00 100644
--- a/player/core.h
+++ b/player/core.h
@@ -514,6 +514,7 @@ void mp_load_auto_profiles(struct MPContext *mpctx);
void mp_get_resume_defaults(struct MPContext *mpctx);
void mp_load_playback_resume(struct MPContext *mpctx, const char *file);
void mp_write_watch_later_conf(struct MPContext *mpctx);
+void mp_delete_watch_later_conf(struct MPContext *mpctx, const char *file);
struct playlist_entry *mp_check_playlist_resume(struct MPContext *mpctx,
struct playlist *playlist);
@@ -546,7 +547,8 @@ void mp_set_playlist_entry(struct MPContext *mpctx, struct playlist_entry *e);
void mp_play_files(struct MPContext *mpctx);
void update_demuxer_properties(struct MPContext *mpctx);
void print_track_list(struct MPContext *mpctx, const char *msg);
-void reselect_demux_stream(struct MPContext *mpctx, struct track *track);
+void reselect_demux_stream(struct MPContext *mpctx, struct track *track,
+ bool refresh_only);
void prepare_playlist(struct MPContext *mpctx, struct playlist *pl);
void autoload_external_files(struct MPContext *mpctx, struct mp_cancel *cancel);
struct track *select_default_track(struct MPContext *mpctx, int order,
diff --git a/player/external_files.c b/player/external_files.c
index 40fad916ef..06585bf18f 100644
--- a/player/external_files.c
+++ b/player/external_files.c
@@ -43,21 +43,24 @@ static const char *const audio_exts[] = {"mp3", "aac", "mka", "dts", "flac",
NULL};
// Stolen from: vlc/-/blob/master/modules/meta_engine/folder.c#L40
+// sorted by priority (descending)
static const char *const cover_files[] = {
- "Folder.jpg",
- "Folder.png",
- "AlbumArtSmall.jpg",
"AlbumArt.jpg",
"Album.jpg",
- ".folder.png",
"cover.jpg",
"cover.png",
- "cover.gif",
"front.jpg",
"front.png",
- "front.gif",
- "front.bmp",
+
+ "AlbumArtSmall.jpg",
+ "Folder.jpg",
+ "Folder.png",
+ ".folder.png",
"thumb.jpg",
+
+ "front.bmp",
+ "front.gif",
+ "cover.gif",
NULL
};
@@ -79,11 +82,13 @@ static int test_ext(bstr ext)
return -1;
}
-static int test_filename(bstr fname)
+static int test_cover_filename(bstr fname, int *priority)
{
for (int n = 0; cover_files[n]; n++) {
- if (bstrcasecmp(bstr0(cover_files[n]), fname) == 0)
+ if (bstrcasecmp(bstr0(cover_files[n]), fname) == 0) {
+ *priority = MP_ARRAY_SIZE(cover_files) - n;
return STREAM_VIDEO;
+ }
}
return -1;
}
@@ -186,9 +191,10 @@ static void append_dir_subtitles(struct mpv_global *global, struct MPOpts *opts,
talloc_steal(tmpmem2, dename.start);
// check what it is (most likely)
+ int cover_prio = 0;
int type = test_ext(tmp_fname_ext);
if (type < 0)
- type = test_filename(dename);
+ type = test_cover_filename(dename, &cover_prio);
char **langs = NULL;
int fuzz = -1;
switch (type) {
@@ -245,7 +251,7 @@ static void append_dir_subtitles(struct mpv_global *global, struct MPOpts *opts,
// cover art: just accept it
if (type == STREAM_VIDEO && fuzz >= 1)
- prio |= 1;
+ prio = cover_prio;
mp_dbg(log, "Potential external file: \"%s\" Priority: %d\n",
de->d_name, prio);
diff --git a/player/javascript.c b/player/javascript.c
index be28ef9e66..8cb263e123 100644
--- a/player/javascript.c
+++ b/player/javascript.c
@@ -33,6 +33,7 @@
#include "options/m_property.h"
#include "common/msg.h"
#include "common/msg_control.h"
+#include "common/stats.h"
#include "options/m_option.h"
#include "input/input.h"
#include "options/path.h"
@@ -64,6 +65,8 @@ struct script_ctx {
struct MPContext *mpctx;
struct mp_log *log;
char *last_error_str;
+ size_t js_malloc_size;
+ struct stats_ctx *stats;
};
static struct script_ctx *jctx(js_State *J)
@@ -458,6 +461,25 @@ static int s_init_js(js_State *J, struct script_ctx *ctx)
return 0;
}
+static void *mp_js_alloc(void *actx, void *ptr, int size_)
+{
+ if (size_ < 0)
+ return NULL;
+
+ struct script_ctx* ctx = actx;
+ size_t size = size_, osize = 0;
+ if (ptr) // free/realloc
+ osize = ta_get_size(ptr);
+
+ void *ret = talloc_realloc_size(actx, ptr, size);
+
+ if (!size || ret) { // free / successful realloc/malloc
+ ctx->js_malloc_size = ctx->js_malloc_size - osize + size;
+ stats_size_value(ctx->stats, "mem", ctx->js_malloc_size);
+ }
+ return ret;
+}
+
/**********************************************************************
* Initialization - booting the script
*********************************************************************/
@@ -479,10 +501,24 @@ static int s_load_javascript(struct mp_script_args *args)
.last_error_str = talloc_strdup(ctx, "Cannot initialize JavaScript"),
.filename = args->filename,
.path = args->path,
+ .js_malloc_size = 0,
+ .stats = stats_ctx_create(ctx, args->mpctx->global,
+ mp_tprintf(80, "script/%s", mpv_client_name(args->client))),
};
+ stats_register_thread_cputime(ctx->stats, "cpu");
+
+ js_Alloc alloc_fn = NULL;
+ void *actx = NULL;
+
+ char *mem_report = getenv("MPV_LEAK_REPORT");
+ if (mem_report && strcmp(mem_report, "1") == 0) {
+ alloc_fn = mp_js_alloc;
+ actx = ctx;
+ }
+
int r = -1;
- js_State *J = js_newstate(NULL, NULL, 0);
+ js_State *J = js_newstate(alloc_fn, actx, 0);
if (!J || s_init_js(J, ctx))
goto error_out;
@@ -745,16 +781,6 @@ static void push_nums_obj(js_State *J, const char * const names[],
}
}
-// args: none, return: object with properties x, y
-static void script_get_mouse_pos(js_State *J)
-{
- int x, y;
- mp_input_get_mouse_pos(jctx(J)->mpctx->input, &x, &y);
- const char * const names[] = {"x", "y", NULL};
- const double vals[] = {x, y};
- push_nums_obj(J, names, vals);
-}
-
// args: input-section-name, x0, y0, x1, y1
static void script_input_set_section_mouse_area(js_State *J)
{
@@ -1145,7 +1171,6 @@ static const struct fn_entry main_fns[] = {
FN_ENTRY(get_wakeup_pipe, 0),
FN_ENTRY(_hook_add, 3),
FN_ENTRY(_hook_continue, 1),
- FN_ENTRY(get_mouse_pos, 0),
FN_ENTRY(input_set_section_mouse_area, 5),
FN_ENTRY(last_error, 0),
FN_ENTRY(_set_last_error, 1),
diff --git a/player/javascript/defaults.js b/player/javascript/defaults.js
index 2435390b87..0904524ce4 100644
--- a/player/javascript/defaults.js
+++ b/player/javascript/defaults.js
@@ -663,6 +663,7 @@ mp.get_script_file = function() { return mp.script_file };
mp.get_script_directory = function() { return mp.script_path };
mp.get_time = function() { return mp.get_time_ms() / 1000 };
mp.utils.getcwd = function() { return mp.get_property("working-directory") };
+mp.get_mouse_pos = function() { return mp.get_property_native("mouse-pos") };
mp.dispatch_event = dispatch_event;
mp.process_timers = process_timers;
mp.notify_idle_observers = notify_idle_observers;
diff --git a/player/loadfile.c b/player/loadfile.c
index 0adc8e351d..058be92c83 100644
--- a/player/loadfile.c
+++ b/player/loadfile.c
@@ -362,7 +362,9 @@ void update_demuxer_properties(struct MPContext *mpctx)
// Enables or disables the stream for the given track, according to
// track->selected.
-void reselect_demux_stream(struct MPContext *mpctx, struct track *track)
+// With refresh_only=true, refreshes the stream if it's enabled.
+void reselect_demux_stream(struct MPContext *mpctx, struct track *track,
+ bool refresh_only)
{
if (!track->stream)
return;
@@ -372,7 +374,10 @@ void reselect_demux_stream(struct MPContext *mpctx, struct track *track)
if (track->type == STREAM_SUB)
pts -= 10.0;
}
- demuxer_select_track(track->demuxer, track->stream, pts, track->selected);
+ if (refresh_only)
+ demuxer_refresh_track(track->demuxer, track->stream, pts);
+ else
+ demuxer_select_track(track->demuxer, track->stream, pts, track->selected);
}
static void enable_demux_thread(struct MPContext *mpctx, struct demuxer *demux)
@@ -658,14 +663,14 @@ void mp_switch_track_n(struct MPContext *mpctx, int order, enum stream_type type
if (current->remux_sink)
close_recorder_and_error(mpctx);
current->selected = false;
- reselect_demux_stream(mpctx, current);
+ reselect_demux_stream(mpctx, current, false);
}
mpctx->current_track[order][type] = track;
if (track) {
track->selected = true;
- reselect_demux_stream(mpctx, track);
+ reselect_demux_stream(mpctx, track, false);
}
if (type == STREAM_VIDEO && order == 0) {
@@ -1341,7 +1346,7 @@ done:
if (mpctx->playback_initialized) {
for (int n = 0; n < mpctx->num_tracks; n++)
- reselect_demux_stream(mpctx, mpctx->tracks[n]);
+ reselect_demux_stream(mpctx, mpctx->tracks[n], false);
}
mp_notify(mpctx, MPV_EVENT_TRACKS_CHANGED, NULL);
@@ -1583,7 +1588,7 @@ static void play_current_file(struct MPContext *mpctx)
}
for (int n = 0; n < mpctx->num_tracks; n++)
- reselect_demux_stream(mpctx, mpctx->tracks[n]);
+ reselect_demux_stream(mpctx, mpctx->tracks[n], false);
update_demuxer_properties(mpctx);
diff --git a/player/lua.c b/player/lua.c
index 363e1a52fd..2eb163ef16 100644
--- a/player/lua.c
+++ b/player/lua.c
@@ -991,16 +991,6 @@ static int script_raw_abort_async_command(lua_State *L)
return 0;
}
-static int script_get_mouse_pos(lua_State *L)
-{
- struct MPContext *mpctx = get_mpctx(L);
- int px, py;
- mp_input_get_mouse_pos(mpctx->input, &px, &py);
- lua_pushnumber(L, px);
- lua_pushnumber(L, py);
- return 2;
-}
-
static int script_get_time(lua_State *L)
{
struct script_ctx *ctx = get_ctx(L);
@@ -1242,7 +1232,6 @@ static const struct fn_entry main_fns[] = {
AF_ENTRY(set_property_native),
FN_ENTRY(raw_observe_property),
FN_ENTRY(raw_unobserve_property),
- FN_ENTRY(get_mouse_pos),
FN_ENTRY(get_time),
FN_ENTRY(input_set_section_mouse_area),
FN_ENTRY(format_time),
diff --git a/player/lua/console.lua b/player/lua/console.lua
index 1e7fd14732..a483bbe1f4 100644
--- a/player/lua/console.lua
+++ b/player/lua/console.lua
@@ -214,8 +214,9 @@ end
-- Show the repl if hidden and replace its contents with 'text'
-- (script-message-to repl type)
-function show_and_type(text)
+function show_and_type(text, cursor_pos)
text = text or ''
+ cursor_pos = tonumber(cursor_pos)
-- Save the line currently being edited, just in case
if line ~= text and line ~= '' and history[#history] ~= line then
@@ -223,7 +224,12 @@ function show_and_type(text)
end
line = text
- cursor = line:len() + 1
+ if cursor_pos ~= nil and cursor_pos >= 1
+ and cursor_pos <= line:len() + 1 then
+ cursor = math.floor(cursor_pos)
+ else
+ cursor = line:len() + 1
+ end
history_pos = #history + 1
insert_mode = false
if repl_active then
@@ -737,8 +743,8 @@ mp.add_key_binding(nil, 'enable', function()
end)
-- Add a script-message to show the REPL and fill it with the provided text
-mp.register_script_message('type', function(text)
- show_and_type(text)
+mp.register_script_message('type', function(text, cursor_pos)
+ show_and_type(text, cursor_pos)
end)
-- Redraw the REPL when the OSD size changes. This is needed because the
diff --git a/player/lua/defaults.lua b/player/lua/defaults.lua
index 95f8952f5d..920ee425aa 100644
--- a/player/lua/defaults.lua
+++ b/player/lua/defaults.lua
@@ -42,6 +42,11 @@ function mp.input_disable_section(section)
mp.commandv("disable-section", section)
end
+function mp.get_mouse_pos()
+ local m = mp.get_property_native("mouse-pos")
+ return m.x, m.y
+end
+
-- For dispatching script-binding. This is sent as:
-- script-message-to $script_name $binding_name $keystate
-- The array is indexed by $binding_name, and has functions like this as value:
diff --git a/player/lua/ytdl_hook.lua b/player/lua/ytdl_hook.lua
index 929e379a89..e9a7b3aac7 100644
--- a/player/lua/ytdl_hook.lua
+++ b/player/lua/ytdl_hook.lua
@@ -8,16 +8,18 @@ local o = {
use_manifests = false,
all_formats = false,
force_all_formats = true,
+ ytdl_path = "youtube-dl",
}
local ytdl = {
- path = "youtube-dl",
+ path = nil,
searched = false,
blacklisted = {}
}
options.read_options(o, nil, function()
ytdl.blacklisted = {} -- reparse o.exclude next time
+ ytdl.searched = false
end)
local chapter_list = {}
@@ -690,8 +692,11 @@ function run_ytdl_hook(url)
-- check for youtube-dl in mpv's config dir
if not (ytdl.searched) then
local exesuf = (package.config:sub(1,1) == '\\') and '.exe' or ''
- local ytdl_mcd = mp.find_config_file("youtube-dl" .. exesuf)
- if not (ytdl_mcd == nil) then
+ local ytdl_mcd = mp.find_config_file(o.ytdl_path .. exesuf)
+ if ytdl_mcd == nil then
+ msg.verbose("No youtube-dl found with path "..o.ytdl_path..exesuf.." in config directories")
+ ytdl.path = o.ytdl_path
+ else
msg.verbose("found youtube-dl at: " .. ytdl_mcd)
ytdl.path = ytdl_mcd
end
diff --git a/player/playloop.c b/player/playloop.c
index 6cff3c9108..87c8b6390c 100644
--- a/player/playloop.c
+++ b/player/playloop.c
@@ -110,13 +110,17 @@ void mp_core_unlock(struct MPContext *mpctx)
// Process any queued user input.
static void mp_process_input(struct MPContext *mpctx)
{
+ int processed = 0;
for (;;) {
mp_cmd_t *cmd = mp_input_read_cmd(mpctx->input);
if (!cmd)
break;
run_command(mpctx, cmd, NULL, NULL, NULL);
+ processed = 1;
}
mp_set_timeout(mpctx, mp_input_get_delay(mpctx->input));
+ if (processed)
+ mp_notify(mpctx, MP_EVENT_INPUT_PROCESSED, NULL);
}
double get_relative_time(struct MPContext *mpctx)