From 1a558bf5c23a369c8c3f5d3e705c3c4212d25dcc Mon Sep 17 00:00:00 2001 From: Guido Cella Date: Fri, 11 Oct 2024 20:24:23 +0200 Subject: [PATCH] osc.lua: remove NIH list formatting All of the code to format playlist/track-list/chapter-list is unnecessary when mpv's core can already show-text these properties. Also an issue with this custom formatting is that showing fewer entries than can fit on the OSD can make it seem like the playlist ends there and there are no entries afterwards. Also remove lots of pointless code around the track-list (mpv's track id and the osc_id are exactly the same). This simplification will make it easier to bind customizable commands, otherwise yet another script message to call set_track would have to be added, when cycle sub/audio already output information about the new track on their own. --- DOCS/man/osc.rst | 9 -- player/lua/osc.lua | 321 +++++++-------------------------------------- 2 files changed, 45 insertions(+), 285 deletions(-) diff --git a/DOCS/man/osc.rst b/DOCS/man/osc.rst index cdc30c7a1d..f77a0e754e 100644 --- a/DOCS/man/osc.rst +++ b/DOCS/man/osc.rst @@ -493,10 +493,6 @@ Script Commands The OSC script listens to certain script commands. These commands can bound in ``input.conf``, or sent by other scripts. -``osc-message`` - Show a message on screen using the OSC. First argument is the message, - second the duration in seconds. - ``osc-visibility`` Controls visibility mode ``never`` / ``auto`` (on mouse move) / ``always`` and also ``cycle`` to cycle between the modes. @@ -515,8 +511,3 @@ to set auto mode (the default) with ``b``:: ``osc-idlescreen`` Controls the visibility of the mpv logo on idle. Valid arguments are ``yes``, ``no``, and ``cycle`` to toggle between yes and no. - -``osc-playlist``, ``osc-chapterlist``, ``osc-tracklist`` - Shows a limited view of the respective type of list using the OSC. First - argument is duration in seconds. - diff --git a/player/lua/osc.lua b/player/lua/osc.lua index 4d4407af12..6634395f93 100644 --- a/player/lua/osc.lua +++ b/player/lua/osc.lua @@ -1,7 +1,6 @@ local assdraw = require 'mp.assdraw' local msg = require 'mp.msg' local opt = require 'mp.options' -local utils = require 'mp.utils' -- -- Parameters @@ -27,9 +26,6 @@ local user_opts = { deadzonesize = 0.5, -- size of deadzone minmousemove = 0, -- minimum amount of pixels the mouse has to -- move between ticks to make the OSC show up - iamaprogrammer = false, -- use native mpv values and disable OSC - -- internal track list management (and some - -- functions that depend on it) layout = "bottombar", seekbarstyle = "bar", -- bar, diamond or knob seekbarhandlesize = 0.6, -- size ratio of the diamond and knob handle @@ -94,8 +90,8 @@ local margins_opts = { } local tick_delay = 1 / 60 -local tracks_osc = {} -local tracks_mpv = {} +local audio_track_count = 0 +local sub_track_count = 0 local window_control_box_width = 80 local layouts = {} local is_december = os.date("*t").month == 12 @@ -152,8 +148,6 @@ local state = { marginsREQ = false, -- is a margins update pending? last_mouseX = nil, last_mouseY = nil, -- last mouse position, to detect significant mouse movement mouse_in_window = false, - message_text = nil, - message_hide_timer = nil, fullscreen = false, tick_timer = nil, tick_last_time = 0, -- when the last tick() was run @@ -343,13 +337,6 @@ local function get_slider_value(element) return get_slider_value_at(element, get_virt_mouse_pos()) end -local function countone(val) - if not user_opts.iamaprogrammer then - val = val + 1 - end - return val -end - -- align: -1 .. +1 -- frame: size of the containing area -- obj: size of the object that should be positioned inside the area @@ -505,224 +492,23 @@ local function render_wipe() end --- --- Message display --- - --- pos is 1 based -local function limited_list(prop, pos) - local proplist = mp.get_property_native(prop, {}) - local count = #proplist - if count == 0 then - return count, proplist - end - - local fs = tonumber(mp.get_property('options/osd-font-size')) - local max = math.ceil(osc_param.unscaled_y*0.75 / fs) - if max % 2 == 0 then - max = max - 1 - end - local delta = math.ceil(max / 2) - 1 - local begi = math.max(math.min(pos - delta, count - max + 1), 1) - local endi = math.min(begi + max - 1, count) - - local reslist = {} - for i=begi, endi do - local item = proplist[i] - item.current = (i == pos) and true or nil - table.insert(reslist, item) - end - return count, reslist -end - -local function get_playlist() - local pos = mp.get_property_number('playlist-pos', 0) + 1 - local count, limlist = limited_list('playlist', pos) - if count == 0 then - return 'Empty playlist.' - end - - local message = string.format('Playlist [%d/%d]:\n', pos, count) - local show = mp.get_property_native('osd-playlist-entry') - local trailing_slash_pattern = mp.get_property("platform") == "windows" - and "[/\\]+$" or "/+$" - for _, v in ipairs(limlist) do - local entry = v.title - if not entry or show ~= 'title' then - entry = v.filename - if not entry:find("://") then - entry = select(2, utils.split_path( - entry:gsub(trailing_slash_pattern, ""))) - end - end - if v.title and show == 'both' then - entry = string.format('%s (%s)', v.title, entry) - end - message = string.format('%s %s %s\n', message, - (v.current and '●' or '○'), entry) - end - return message -end - -local function get_chapterlist() - local pos = mp.get_property_number('chapter', 0) + 1 - local count, limlist = limited_list('chapter-list', pos) - if count == 0 then - return 'No chapters.' - end - - local message = string.format('Chapters [%d/%d]:\n', pos, count) - for i, v in ipairs(limlist) do - local time = mp.format_time(v.time) - local title = v.title - if title == nil then - title = string.format('Chapter %02d', i) - end - message = string.format('%s[%s] %s %s\n', message, time, - (v.current and '●' or '○'), title) - end - return message -end - -local function render_message(ass) - if state.message_hide_timer and state.message_hide_timer:is_enabled() and - state.message_text - then - local _, lines = string.gsub(state.message_text, "\\N", "") - - local fontsize = tonumber(mp.get_property("options/osd-font-size")) - local outline = tonumber(mp.get_property("options/osd-border-size")) - local maxlines = math.ceil(osc_param.unscaled_y*0.75 / fontsize) - local counterscale = osc_param.playresy / osc_param.unscaled_y - - fontsize = fontsize * counterscale / math.max(0.65 + math.min(lines/maxlines, 1), 1) - outline = outline * counterscale / math.max(0.75 + math.min(lines/maxlines, 1)/2, 1) - - local style = "{\\bord" .. outline .. "\\fs" .. fontsize .. "}" - - - ass:new_event() - ass:append(style .. state.message_text) - else - state.message_text = nil - end -end - -local function show_message(text, duration) - --print("text: "..text.." duration: " .. duration) - if duration == nil then - duration = tonumber(mp.get_property("options/osd-duration")) / 1000 - elseif type(duration) ~= "number" then - print("duration: " .. duration) - end - - -- cut the text short, otherwise the following functions - -- may slow down massively on huge input - text = string.sub(text, 0, 4000) - - state.message_text = mp.command_native({"escape-ass", text}) - - if not state.message_hide_timer then - state.message_hide_timer = mp.add_timeout(0, request_tick) - end - state.message_hide_timer:kill() - state.message_hide_timer.timeout = duration - state.message_hide_timer:resume() - request_tick() -end - - -- -- Tracklist Management -- -local nicetypes = {video = "Video", audio = "Audio", sub = "Subtitle"} - -- updates the OSC internal playlists, should be run each time the track-layout changes local function update_tracklist() - local tracktable = mp.get_property_native("track-list", {}) + audio_track_count, sub_track_count = 0, 0 - -- by osc_id - tracks_osc.video, tracks_osc.audio, tracks_osc.sub = {}, {}, {} - -- by mpv_id - tracks_mpv.video, tracks_mpv.audio, tracks_mpv.sub = {}, {}, {} - for n = 1, #tracktable do - if tracktable[n].type ~= "unknown" then - local type = tracktable[n].type - local mpv_id = tonumber(tracktable[n].id) - - -- by osc_id - table.insert(tracks_osc[type], tracktable[n]) - - -- by mpv_id - tracks_mpv[type][mpv_id] = tracktable[n] - tracks_mpv[type][mpv_id].osc_id = #tracks_osc[type] + for _, track in pairs(mp.get_property_native("track-list")) do + if track.type == "audio" then + audio_track_count = audio_track_count + 1 + elseif track.type == "sub" then + sub_track_count = sub_track_count + 1 end end end --- return a nice list of tracks of the given type (video, audio, sub) -local function get_tracklist(type) - local message = "Available " .. nicetypes[type] .. " Tracks: " - if #tracks_osc[type] == 0 then - message = message .. "none" - else - for n = 1, #tracks_osc[type] do - local track = tracks_osc[type][n] - local lang, title, selected = "unknown", "", "○" - if track.lang ~= nil then lang = track.lang end - if track.title ~= nil then title = track.title end - if track.id == tonumber(mp.get_property(type)) then - selected = "●" - end - message = message.."\n"..selected.." "..n..": ["..lang.."] "..title - end - end - return message -end - --- relatively change the track of given by tracks - --(+1 -> next, -1 -> previous) -local function set_track(type, next) - local current_track_mpv, current_track_osc - if mp.get_property(type) == "no" then - current_track_osc = 0 - else - current_track_mpv = tonumber(mp.get_property(type)) - current_track_osc = tracks_mpv[type][current_track_mpv].osc_id - end - local new_track_osc = (current_track_osc + next) % (#tracks_osc[type] + 1) - local new_track_mpv - if new_track_osc == 0 then - new_track_mpv = "no" - else - new_track_mpv = tracks_osc[type][new_track_osc].id - end - - mp.commandv("set", type, new_track_mpv) - - if new_track_osc == 0 then - show_message(nicetypes[type] .. " Track: none") - else - show_message(nicetypes[type] .. " Track: " - .. new_track_osc .. "/" .. #tracks_osc[type] - .. " [".. (tracks_osc[type][new_track_osc].lang or "unknown") .."] " - .. (tracks_osc[type][new_track_osc].title or "")) - end -end - --- get the currently selected track of , OSC-style counted -local function get_track(type) - local track = mp.get_property(type) - if track ~= "no" and track ~= nil then - local tr = tracks_mpv[type][tonumber(track)] - if tr then - return tr.osc_id - end - end - return 0 -end - -- WindowControl helpers local function window_controls_enabled() local val = user_opts.windowcontrols @@ -1917,16 +1703,11 @@ local function osc_init() end ne.eventresponder["mbtn_left_up"] = function () - local title = mp.get_property_osd("media-title") - if have_pl then - title = string.format("[%d/%d] %s", countone(pl_pos - 1), - pl_count, title) - end - show_message(title) + mp.command("show-text '[${playlist-pos-1}/${playlist-count}] ${media-title}'") end ne.eventresponder["mbtn_right_up"] = - function () show_message(mp.get_property_osd("filename")) end + function () mp.command("show-text ${filename}") end -- playlist buttons @@ -1939,13 +1720,13 @@ local function osc_init() function () mp.commandv("playlist-prev", "weak") if user_opts.playlist_osd then - show_message(get_playlist(), 3) + mp.command("show-text ${playlist} 3000") end end ne.eventresponder["shift+mbtn_left_up"] = - function () show_message(get_playlist(), 3) end + function () mp.command("show-text ${playlist} 3000") end ne.eventresponder["mbtn_right_up"] = - function () show_message(get_playlist(), 3) end + function () mp.command("show-text ${playlist} 3000") end --next ne = new_element("pl_next", "button") @@ -1956,13 +1737,13 @@ local function osc_init() function () mp.commandv("playlist-next", "weak") if user_opts.playlist_osd then - show_message(get_playlist(), 3) + mp.command("show-text ${playlist} 3000") end end ne.eventresponder["shift+mbtn_left_up"] = - function () show_message(get_playlist(), 3) end + function () mp.command("show-text ${playlist} 3000") end ne.eventresponder["mbtn_right_up"] = - function () show_message(get_playlist(), 3) end + function () mp.command("show-text ${playlist} 3000") end -- big buttons @@ -2017,13 +1798,13 @@ local function osc_init() function () mp.commandv("add", "chapter", -1) if user_opts.chapters_osd then - show_message(get_chapterlist(), 3) + mp.command("show-text ${chapter-list} 3000") end end ne.eventresponder["shift+mbtn_left_up"] = - function () show_message(get_chapterlist(), 3) end + function () mp.command("show-text ${chapter-list} 3000") end ne.eventresponder["mbtn_right_up"] = - function () show_message(get_chapterlist(), 3) end + function () mp.command("show-text ${chapter-list} 3000") end --ch_next ne = new_element("ch_next", "button") @@ -2034,13 +1815,13 @@ local function osc_init() function () mp.commandv("add", "chapter", 1) if user_opts.chapters_osd then - show_message(get_chapterlist(), 3) + mp.command("show-text ${chapter-list} 3000") end end ne.eventresponder["shift+mbtn_left_up"] = - function () show_message(get_chapterlist(), 3) end + function () mp.command("show-text ${chapter-list} 3000") end ne.eventresponder["mbtn_right_up"] = - function () show_message(get_chapterlist(), 3) end + function () mp.command("show-text ${chapter-list} 3000") end -- update_tracklist() @@ -2048,53 +1829,45 @@ local function osc_init() --cy_audio ne = new_element("cy_audio", "button") - ne.enabled = (#tracks_osc.audio > 0) + ne.enabled = audio_track_count > 0 ne.content = function () - local aid = "–" - if get_track("audio") ~= 0 then - aid = get_track("audio") - end - return ("\238\132\134" .. osc_styles.smallButtonsLlabel - .. " " .. aid .. "/" .. #tracks_osc.audio) + return ("\238\132\134" .. osc_styles.smallButtonsLlabel .. " " .. + (mp.get_property_native("aid") or "-") .. "/" .. audio_track_count) end ne.eventresponder["mbtn_left_up"] = - function () set_track("audio", 1) end + function () mp.command("cycle audio") end ne.eventresponder["mbtn_right_up"] = - function () set_track("audio", -1) end + function () mp.command("cycle audio down") end ne.eventresponder["shift+mbtn_left_down"] = - function () show_message(get_tracklist("audio"), 2) end + function () mp.command("show-text ${track-list/audio} 2000") end if user_opts.scrollcontrols then ne.eventresponder["wheel_down_press"] = - function () set_track("audio", 1) end + function () mp.command("cycle audio") end ne.eventresponder["wheel_up_press"] = - function () set_track("audio", -1) end + function () mp.command("cycle audio down") end end --cy_sub ne = new_element("cy_sub", "button") - ne.enabled = (#tracks_osc.sub > 0) + ne.enabled = sub_track_count > 0 ne.content = function () - local sid = "–" - if get_track("sub") ~= 0 then - sid = get_track("sub") - end - return ("\238\132\135" .. osc_styles.smallButtonsLlabel - .. " " .. sid .. "/" .. #tracks_osc.sub) + return ("\238\132\135" .. osc_styles.smallButtonsLlabel .. " " .. + (mp.get_property_native("sid") or "-") .. "/" .. sub_track_count) end ne.eventresponder["mbtn_left_up"] = - function () set_track("sub", 1) end + function () mp.command("cycle sub") end ne.eventresponder["mbtn_right_up"] = - function () set_track("sub", -1) end + function () mp.command("cycle sub down") end ne.eventresponder["shift+mbtn_left_down"] = - function () show_message(get_tracklist("sub"), 2) end + function () mp.command("show-text ${track-list/sub} 2000") end if user_opts.scrollcontrols then ne.eventresponder["wheel_down_press"] = - function () set_track("sub", 1) end + function () mp.command("cycle sub") end ne.eventresponder["wheel_up_press"] = - function () set_track("sub", -1) end + function () mp.command("cycle sub down") end end --tog_fs @@ -2632,9 +2405,6 @@ local function render() -- actual rendering local ass = assdraw.ass_new() - -- Messages - render_message(ass) - -- actual OSC if state.osc_visible then render_elements(ass) @@ -2776,19 +2546,18 @@ mp.observe_property("chapter-list", "native", function(_, list) request_init() end) -mp.register_script_message("osc-message", show_message) +-- These are for backwards compatibility only. +mp.register_script_message("osc-message", function(message, dur) + mp.osd_message(message, dur) +end) mp.register_script_message("osc-chapterlist", function(dur) - show_message(get_chapterlist(), dur) + mp.command("show-text ${chapter-list} " .. (dur and dur * 1000 or "")) end) mp.register_script_message("osc-playlist", function(dur) - show_message(get_playlist(), dur) + mp.command("show-text ${playlist} " .. (dur and dur * 1000 or "")) end) mp.register_script_message("osc-tracklist", function(dur) - local message = {} - for k in pairs(nicetypes) do - table.insert(message, get_tracklist(k)) - end - show_message(table.concat(message, '\n\n'), dur) + mp.command("show-text ${track-list} " .. (dur and dur * 1000 or "")) end) mp.observe_property("fullscreen", "bool", function(_, val)