Skip to content

Commit 09d075f

Browse files
N-R-Kkasper93
authored andcommitted
osc: define and add support for "preview" api
this adds a "standard" api for ui scripts and thumbnailers to communicate with each other, based on the simple thumbfast api [0]. the api works as follows: * To issue a thumbnail draw command, the UI script will set the property `user-data/osc/draw-preview`. * To clear the thumbnail, the UI script will set the previously mentioned property to `nil`. a more ideal api would make it so that the thumbnailer script only generates the thumbnail and doesn't need to draw at all. but such api is vastly more complex [4] and would require a lot more work and maintenance on mpv's side. this is a decent enough api that allows arbitrary thumbnailers and ui scripts to communicate between each other and work together, while being simple enough that it can be supported without too much maintenance. this change has been tested with work with thumbfast [1]. and for demonstration that this api can be useful outside of osc, it has also been tested to work on mfpbar's thumbnailer branch [2]. the code to determine thumbnail x,y is based on the osc fork inside of thumbfast [3]. [0]: https://github.com/po5/thumbfast?tab=readme-ov-file#for-ui-developers-how-to-add-thumbfast-support-to-your-script [1]: po5/thumbfast#173 [2]: https://codeberg.org/NRK/mpv-toolbox/src/branch/thumbnailer/mfpbar [3]: https://github.com/po5/thumbfast/tree/vanilla-osc [4]: #17654
1 parent 8da99f7 commit 09d075f

3 files changed

Lines changed: 96 additions & 0 deletions

File tree

DOCS/man/input.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3924,6 +3924,10 @@ Property list
39243924
the left, right, top, and bottom margins respectively.
39253925
Values are between 0.0 and 1.0, normalized to window width/height.
39263926

3927+
``user-data/osc/draw-preview``
3928+
Used to communicate between osc and compatible thumbnailer (if
3929+
installed). See `OSC Preview API`_ section for more details.
3930+
39273931
``user-data/mpv/ytdl``
39283932
Data shared by the builtin ytdl hook script.
39293933

DOCS/man/osc.rst

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -586,6 +586,12 @@ Configurable Options
586586

587587
Use display fps to calculate the interval between OSC redraws.
588588

589+
``max_thumb_size``
590+
Default: 200
591+
592+
Maximum display size of the preview thumbnail. Only meaningful when a
593+
Thumbnailer is active. See the `OSC Preview API`_ section.
594+
589595
The following options configure what commands are run when the buttons are
590596
clicked. ``mbtn_mid`` commands are also triggered with ``shift+mbtn_left``.
591597

@@ -719,3 +725,35 @@ to set auto mode (the default) with ``b``::
719725
Controls the visibility of the mpv logo on idle. Valid arguments are ``yes``,
720726
``no``, and ``cycle`` to toggle between yes and no. If a second argument is
721727
passed (any value), then the output on the OSD will be silenced.
728+
729+
OSC Preview API
730+
~~~~~~~~~~~~~~~
731+
732+
The OSC supports displaying preview thumbnails when hovering over the seekbar if
733+
a compatible thumbnailer script is installed. It communicates with a thumbnailer
734+
script via the following ``user-data`` properties:
735+
736+
``user-data/osc/draw-preview``
737+
Set by the OSC to request a thumbnail within the currently playing file.
738+
The requested thumbnail timestamp in seconds is set in
739+
``user-data/osc/hover-sec``. The ``draw-preview`` property is a table with
740+
the following fields:
741+
742+
``x``, ``y``
743+
Top-left coordinates (positive integers) to draw the thumbnail at.
744+
745+
``w``, ``h``
746+
Width and height (positive non-zero integers) of the area to draw the
747+
thumbnail in. Note that this only specifies the drawing width and
748+
height, the actual backing thumbnail size may differ.
749+
750+
``ass``
751+
Optional ASS string to render alongside the thumbnail, using OSD
752+
coordinates. This can be used for decorations such as a thumbnail
753+
border.
754+
755+
The OSC sets this property to ``nil`` to signal the thumbnailer to clear
756+
the displayed thumbnail.
757+
758+
Avoid installing/enabling multiple thumbnailer script since this api expects
759+
only one to be active at a time.

player/lua/osc.lua

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,8 @@ local user_opts = {
7979
tick_delay = 1 / 60, -- minimum interval between OSC redraws in seconds
8080
tick_delay_follow_display_fps = false, -- use display fps as the minimum interval
8181

82+
max_thumb_size = 200, -- maximum display size of preview thumbnails
83+
8284
-- luacheck: push ignore
8385
-- luacheck: max line length
8486
menu_mbtn_left_command = "script-binding select/menu; script-message-to osc osc-hide",
@@ -1177,6 +1179,56 @@ local function render_elements(master_ass)
11771179
ass_append_alpha(elem_ass, slider_lo.alpha, 0)
11781180
elem_ass:append(tooltiplabel)
11791181

1182+
local hover_sec = mp.get_property_number("duration", 0) * (sliderpos / 100)
1183+
mp.set_property_number("user-data/osc/hover-sec", hover_sec)
1184+
1185+
-- thumbnail
1186+
local osd_w, osd_h = mp.get_osd_size()
1187+
local vop = mp.get_property_native("video-out-params")
1188+
local draw_thumbnail = osd_w > 0 and vop
1189+
if draw_thumbnail then
1190+
local r_w, r_h = get_virt_scale_factor()
1191+
local thumb_max = math.min(user_opts.max_thumb_size,
1192+
math.min(osd_w, osd_h) * 0.25)
1193+
local scale = thumb_max / math.max(vop.dw, vop.dh)
1194+
local thumb_w = math.floor(vop.dw * scale + 0.5)
1195+
local thumb_h = math.floor(vop.dh * scale + 0.5)
1196+
local tooltip_font_size = (user_opts.layout == "box" or
1197+
user_opts.layout == "slimbox") and 2 or 12
1198+
local thumb_tx = tx
1199+
local thumb_ty = user_opts.layout ~= "topbar" and element.hitbox.y1 - 8 or
1200+
element.hitbox.y2 + tooltip_font_size + 8
1201+
local thumb_pad = 4
1202+
local thumb_margin_x = 20 / r_w
1203+
local thumb_margin_y = (4 + user_opts.tooltipborder) / r_h + thumb_pad
1204+
local thumb_x = math.min(osd_w - thumb_w - thumb_margin_x,
1205+
math.max(thumb_margin_x, thumb_tx / r_w - thumb_w / 2))
1206+
local thumb_y = thumb_ty / r_h + (user_opts.layout ~= "topbar" and
1207+
-(thumb_h + tooltip_font_size / r_h + thumb_margin_y) or
1208+
thumb_margin_y)
1209+
1210+
local thumb_req = {
1211+
x = math.floor(thumb_x + 0.5), y = math.floor(thumb_y + 0.5),
1212+
w = math.floor(thumb_w + 0.5), h = math.floor(thumb_h + 0.5),
1213+
}
1214+
1215+
local thumb_ass = assdraw.ass_new()
1216+
thumb_ass:new_event()
1217+
thumb_ass:pos(thumb_req.x, thumb_req.y)
1218+
thumb_ass:an(7)
1219+
thumb_ass:append(osc_styles.timePosBar)
1220+
thumb_ass:append("{\\1a&H20&}")
1221+
thumb_ass:draw_start()
1222+
thumb_ass:rect_cw(-thumb_pad, -thumb_pad,
1223+
thumb_req.w + thumb_pad, thumb_req.h + thumb_pad)
1224+
thumb_ass:draw_stop()
1225+
thumb_req.ass = thumb_ass.text
1226+
1227+
mp.set_property_native("user-data/osc/draw-preview", thumb_req)
1228+
end
1229+
else
1230+
mp.set_property_native("user-data/osc/hover-sec", nil)
1231+
mp.set_property_native("user-data/osc/draw-preview", nil)
11801232
end
11811233
end
11821234

@@ -3187,6 +3239,8 @@ mp.register_event("file-loaded", function()
31873239
end)
31883240
mp.add_hook("on_unload", 50, function()
31893241
state.file_loaded = false
3242+
mp.set_property_native("user-data/osc/hover-sec", nil)
3243+
mp.set_property_native("user-data/osc/draw-preview", nil)
31903244
request_tick()
31913245
end)
31923246

0 commit comments

Comments
 (0)