Skip to content

Commit c03ce1c

Browse files
committed
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 [1]. 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 this is a decent enough api that allows arbitrary thumbnailers and ui scripts to communicate between each other and work together. this change has been tested with work with thumbfast (using the "thumbfast-glue" script [4]). and for demonstration that this api can be useful outside of osc, it has also been tested to work on mfpbar's thumbnailer branch [3]. the code to determine thumbnail x,y is based on the osc fork inside of thumbfast [2]. [1]: https://github.com/po5/thumbfast?tab=readme-ov-file#for-ui-developers-how-to-add-thumbfast-support-to-your-script [2]: https://github.com/po5/thumbfast/tree/vanilla-osc [3]: https://codeberg.org/NRK/mpv-toolbox/src/branch/thumbnailer/mfpbar [4]: #17518 (comment)
1 parent c961c96 commit c03ce1c

File tree

3 files changed

+96
-0
lines changed

3 files changed

+96
-0
lines changed

DOCS/man/input.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3929,6 +3929,10 @@ Property list
39293929
``user-data/mpv/console/open``
39303930
Whether the console is open.
39313931

3932+
``user-data/osc/draw-preview``
3933+
Used to communicate between osc and compatible thumbnailer (if
3934+
installed). See `OSC Preview API`_ section for more details.
3935+
39323936
``menu-data`` (RW)
39333937
This property stores the raw menu definition. See `Context Menu`_ section for details.
39343938

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 as only one can be active
759+
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",
@@ -1154,6 +1156,56 @@ local function render_elements(master_ass)
11541156
ass_append_alpha(elem_ass, slider_lo.alpha, 0)
11551157
elem_ass:append(tooltiplabel)
11561158

1159+
local hover_sec = mp.get_property_number("duration", 0) * (sliderpos / 100)
1160+
mp.set_property_number("user-data/osc/hover-sec", hover_sec)
1161+
1162+
-- thumbnail
1163+
local osd_w, osd_h = mp.get_osd_size()
1164+
local vop = mp.get_property_native("video-out-params")
1165+
local draw_thumbnail = osd_w > 0 and vop
1166+
if draw_thumbnail then
1167+
local r_w, r_h = get_virt_scale_factor()
1168+
local thumb_max = math.min(user_opts.max_thumb_size,
1169+
math.min(osd_w, osd_h) * 0.25)
1170+
local scale = thumb_max / math.max(vop.dw, vop.dh)
1171+
local thumb_w = math.floor(vop.dw * scale + 0.5)
1172+
local thumb_h = math.floor(vop.dh * scale + 0.5)
1173+
local tooltip_font_size = (user_opts.layout == "box" or
1174+
user_opts.layout == "slimbox") and 2 or 12
1175+
local thumb_tx = tx
1176+
local thumb_ty = user_opts.layout ~= "topbar" and element.hitbox.y1 - 8 or
1177+
element.hitbox.y2 + tooltip_font_size + 8
1178+
local thumb_pad = 4
1179+
local thumb_margin_x = 20 / r_w
1180+
local thumb_margin_y = (4 + user_opts.tooltipborder) / r_h + thumb_pad
1181+
local thumb_x = math.min(osd_w - thumb_w - thumb_margin_x,
1182+
math.max(thumb_margin_x, thumb_tx / r_w - thumb_w / 2))
1183+
local thumb_y = thumb_ty / r_h + (user_opts.layout ~= "topbar" and
1184+
-(thumb_h + tooltip_font_size / r_h + thumb_margin_y) or
1185+
thumb_margin_y)
1186+
1187+
local thumb_req = {
1188+
x = math.floor(thumb_x + 0.5), y = math.floor(thumb_y + 0.5),
1189+
w = math.floor(thumb_w + 0.5), h = math.floor(thumb_h + 0.5),
1190+
}
1191+
1192+
local thumb_ass = assdraw.ass_new()
1193+
thumb_ass:new_event()
1194+
thumb_ass:pos(thumb_req.x, thumb_req.y)
1195+
thumb_ass:an(7)
1196+
thumb_ass:append(osc_styles.timePosBar)
1197+
thumb_ass:append("{\\1a&H20&}")
1198+
thumb_ass:draw_start()
1199+
thumb_ass:rect_cw(-thumb_pad, -thumb_pad,
1200+
thumb_req.w + thumb_pad, thumb_req.h + thumb_pad)
1201+
thumb_ass:draw_stop()
1202+
thumb_req.ass = thumb_ass.text
1203+
1204+
mp.set_property_native("user-data/osc/draw-preview", thumb_req)
1205+
end
1206+
else
1207+
mp.set_property_native("user-data/osc/draw-preview", nil)
1208+
mp.set_property_native("user-data/osc/hover-sec", nil)
11571209
end
11581210
end
11591211

@@ -3177,6 +3229,8 @@ mp.register_event("file-loaded", function()
31773229
end)
31783230
mp.add_hook("on_unload", 50, function()
31793231
state.file_loaded = false
3232+
mp.set_property_native("user-data/osc/draw-preview", nil)
3233+
mp.set_property_native("user-data/osc/hover-sec", nil)
31803234
request_tick()
31813235
end)
31823236

0 commit comments

Comments
 (0)