From 3e7c3a8db90be62c46ffbd8e8fdb27c9f3ac79a6 Mon Sep 17 00:00:00 2001 From: SilentD Date: Mon, 7 Feb 2022 17:43:53 +0530 Subject: [PATCH] Show chapter names on hover Taken from: https://github.com/mpv-player/mpv/commit/76b1ac57a4f49ff2c7f18b7e46aefa7fb3362984 --- mordenx.lua | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 64 insertions(+), 1 deletion(-) diff --git a/mordenx.lua b/mordenx.lua index 409336e..bb75352 100644 --- a/mordenx.lua +++ b/mordenx.lua @@ -45,6 +45,7 @@ local user_opts = { visibility = 'auto', -- only used at init to set visibility_mode(...) windowcontrols = 'auto', -- whether to show window controls language = 'eng', -- eng=English, chs=Chinese + chapter_fmt = "Chapter: %s", -- chapter print format for seekbar-hover. "no" to disable } -- Localization @@ -138,6 +139,7 @@ local state = { osd = mp.create_osd_overlay('ass-events'), lastvisibility = user_opts.visibility, -- save last visibility on pause if showonpause fulltime = user_opts.timems, + chapter_list = {}, -- sorted by time } local window_control_box_width = 138 @@ -550,8 +552,36 @@ end -- -- Element Rendering -- + +-- returns nil or a chapter element from the native property chapter-list +function get_chapter(possec) + local cl = state.chapter_list -- sorted, get latest before possec, if any + + for n=#cl,1,-1 do + if possec >= cl[n].time then + return cl[n] + end + end +end + function render_elements(master_ass) + -- when the slider is dragged or hovered and we have a target chapter name + -- then we use it instead of the normal title. we calculate it before the + -- render iterations because the title may be rendered before the slider. + state.forced_title = nil + local se, ae = state.slider_element, elements[state.active_element] + if user_opts.chapter_fmt ~= "no" and se and (ae == se or (not ae and mouse_hit(se))) then + local dur = mp.get_property_number("duration", 0) + if dur > 0 then + local possec = get_slider_value(se) * dur / 100 -- of mouse pos + local ch = get_chapter(possec) + if ch and ch.title and ch.title ~= "" then + state.forced_title = string.format(user_opts.chapter_fmt, ch.title) + end + end + end + for n=1, #elements do local element = elements[n] local style_ass = assdraw.ass_new() @@ -1115,6 +1145,7 @@ function update_options(list) validate_user_opts() request_tick() visibility_mode(user_opts.visibility, true) + update_duration_watch() request_init() end @@ -1322,7 +1353,8 @@ function osc_init() -- title ne = new_element('title', 'button') ne.content = function () - local title = mp.command_native({'expand-text', user_opts.title}) + local title = state.forced_title or + mp.command_native({"expand-text", user_opts.title}) if state.paused then title = title:gsub('\\n', ' '):gsub('\\$', ''):gsub('{','\\{') else @@ -1336,6 +1368,7 @@ function osc_init() ne = new_element('seekbar', 'slider') ne.enabled = not (mp.get_property('percent-pos') == nil) + state.slider_element = ne.enabled and ne or nil -- used for forced_title ne.slider.markerF = function () local duration = mp.get_property_number('duration', nil) if not (duration == nil) then @@ -1930,12 +1963,42 @@ function enable_osc(enable) end end +-- duration is observed for the sole purpose of updating chapter markers +-- positions. live streams with chapters are very rare, and the update is also +-- expensive (with request_init), so it's only observed when we have chapters +-- and the user didn't disable the livemarkers option (update_duration_watch). +function on_duration() request_init() end + +local duration_watched = false +function update_duration_watch() + local want_watch = user_opts.livemarkers and + (mp.get_property_number("chapters", 0) or 0) > 0 and + true or false -- ensure it's a boolean + + if (want_watch ~= duration_watched) then + if want_watch then + mp.observe_property("duration", nil, on_duration) + else + mp.unobserve_property(on_duration) + end + duration_watched = want_watch + end +end + validate_user_opts() +update_duration_watch() mp.register_event('shutdown', shutdown) mp.register_event('start-file', request_init) mp.observe_property('track-list', nil, request_init) mp.observe_property('playlist', nil, request_init) +mp.observe_property("chapter-list", "native", function(_, list) + list = list or {} -- safety, shouldn't return nil + table.sort(list, function(a, b) return a.time < b.time end) + state.chapter_list = list + update_duration_watch() + request_init() +end) mp.register_script_message('osc-message', show_message) mp.register_script_message('osc-chapterlist', function(dur)