Skip to content

Commit ba21209

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` with `hover_sec`, `x`, `y`, `w` and `h` field set. hover_sec is the position in seconds where the user is hovering. x and y are top-left coordinates to draw the thumbnail in and `w` and `h` are width and height of the size to draw the thumbnail at (the actual backing thumbnail size may be different). x,y,w,h must be positive integers. * 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]: mpv-player#17518 (comment)
1 parent 4f9f1ff commit ba21209

3 files changed

Lines changed: 93 additions & 0 deletions

File tree

DOCS/man/input.rst

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

3954+
``user-data/osc/draw-preview``
3955+
Used to communicate between osc and compatible thumbnailer (if
3956+
installed). See `OSC Preview API`_ section for more details.
3957+
39543958
``menu-data`` (RW)
39553959
This property stores the raw menu definition. See `Context Menu`_ section for details.
39563960

DOCS/man/osc.rst

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -588,6 +588,12 @@ Configurable Options
588588

589589
Use display fps to calculate the interval between OSC redraws.
590590

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

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

player/lua/osc.lua

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

83+
max_thumb_size = 200, -- maximum display size of preview thumbnails
84+
8385
-- luacheck: push ignore
8486
-- luacheck: max line length
8587
menu_mbtn_left_command = "script-binding select/menu; script-message-to osc osc-hide",
@@ -1156,6 +1158,53 @@ local function render_elements(master_ass)
11561158
ass_append_alpha(elem_ass, slider_lo.alpha, 0)
11571159
elem_ass:append(tooltiplabel)
11581160

1161+
-- thumbnail
1162+
local osd_w, osd_h = mp.get_osd_size()
1163+
local vop = mp.get_property_native("video-out-params")
1164+
local draw_thumbnail = osd_w > 0 and vop
1165+
if draw_thumbnail then
1166+
local r_w, r_h = get_virt_scale_factor()
1167+
local thumb_max = math.min(user_opts.max_thumb_size,
1168+
math.min(osd_w, osd_h) * 0.25)
1169+
local scale = thumb_max / math.max(vop.dw, vop.dh)
1170+
local thumb_w = math.floor(vop.dw * scale + 0.5)
1171+
local thumb_h = math.floor(vop.dh * scale + 0.5)
1172+
local tooltip_font_size = (user_opts.layout == "box" or
1173+
user_opts.layout == "slimbox") and 2 or 12
1174+
local thumb_tx = tx
1175+
local thumb_ty = user_opts.layout ~= "topbar" and element.hitbox.y1 - 8 or
1176+
element.hitbox.y2 + tooltip_font_size + 8
1177+
local thumb_pad = 4
1178+
local thumb_margin_x = 20 / r_w
1179+
local thumb_margin_y = (4 + user_opts.tooltipborder) / r_h + thumb_pad
1180+
local thumb_x = math.min(osd_w - thumb_w - thumb_margin_x,
1181+
math.max(thumb_margin_x, thumb_tx / r_w - thumb_w / 2))
1182+
local thumb_y = thumb_ty / r_h + (user_opts.layout ~= "topbar" and
1183+
-(thumb_h + tooltip_font_size / r_h + thumb_margin_y) or
1184+
thumb_margin_y)
1185+
1186+
local thumb_req = {
1187+
hover_sec = mp.get_property_number("duration", 0) * (sliderpos / 100),
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)
11591208
end
11601209
end
11611210

@@ -3170,6 +3219,7 @@ mp.register_event("file-loaded", function()
31703219
end)
31713220
mp.add_hook("on_unload", 50, function()
31723221
state.file_loaded = false
3222+
mp.set_property_native("user-data/osc/draw-preview", nil)
31733223
request_tick()
31743224
end)
31753225

0 commit comments

Comments
 (0)