summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChrisK2 <spam@kalania.de>2014-08-15 15:24:22 +0200
committerChrisK2 <spam@kalania.de>2014-08-15 15:24:22 +0200
commit364e06261a2ffd39afea1d029d4dcc87ef1d6144 (patch)
tree54f090f68f2ca244856e67977b1fcf513fc821ac
parentd5940fabcd6b477c72430c84e460975060807646 (diff)
downloadmpv-364e06261a2ffd39afea1d029d4dcc87ef1d6144.tar.bz2
mpv-364e06261a2ffd39afea1d029d4dcc87ef1d6144.tar.xz
osc: Overhaul (wip)
Code reorganized to make layouts exchangeable alternative test layout can be tested with layout=slimbox in the OSC config timers are now used to properly animate the fade out when the player is paused duplicate seeks are discarded again
-rw-r--r--player/lua/osc.lua1350
1 files changed, 848 insertions, 502 deletions
diff --git a/player/lua/osc.lua b/player/lua/osc.lua
index f688d0f55a..06974239c7 100644
--- a/player/lua/osc.lua
+++ b/player/lua/osc.lua
@@ -24,22 +24,17 @@ local user_opts = {
minmousemove = 3, -- minimum amount of pixels the mouse has to move between ticks to make the OSC show up
seektooltip = true, -- display tooltip over the seekbar indicating time at mouse position
iamaprogrammer = false, -- use native mpv values and disable OSC internal playlist management (and some functions that depend on it)
+ layout = "box",
}
-- read options from config and command-line
read_options(user_opts, "osc")
-local osc_param = {
- osc_w = 550, -- width, height, corner-radius, padding of the OSC box
- osc_h = 138,
- osc_r = 10,
- osc_p = 15,
-
- -- calculated by osc_init()
+local osc_param = { -- calculated by osc_init()
playresy = 0, -- canvas size Y
playresx = 0, -- canvas size X
- posX, posY = 0,0, -- position of the controler
- pos_offsetX, pos_offsetY = 0,0, -- vertical/horizontal position offset for contents aligned at the borders of the box
+ display_aspect = 1,
+ areas = {},
}
local osc_styles = {
@@ -72,6 +67,8 @@ local state = {
message_text,
message_timeout,
fullscreen = false,
+ timer = nil,
+ cache_idle = false,
}
@@ -87,7 +84,8 @@ function scale_value(x0, x1, y0, y1, val)
return (m * val) + b
end
--- returns hitbox spanning coordinates (top left, bottom right corner) according to alignment
+-- returns hitbox spanning coordinates (top left, bottom right corner)
+-- according to alignment
function get_hitbox_coords(x, y, an, w, h)
local alignments = {
@@ -107,14 +105,22 @@ function get_hitbox_coords(x, y, an, w, h)
return alignments[an]()
end
+function get_hitbox_coords_geo(geometry)
+ return get_hitbox_coords(geometry.x, geometry.y, geometry.an,
+ geometry.w, geometry.h)
+end
+
function get_element_hitbox(element)
- return element.hitbox.x1, element.hitbox.y1, element.hitbox.x2, element.hitbox.y2
+ return element.hitbox.x1, element.hitbox.y1,
+ element.hitbox.x2, element.hitbox.y2
end
function mouse_hit(element)
- local mX, mY = mp.get_mouse_pos()
- local bX1, bY1, bX2, bY2 = get_element_hitbox(element)
+ return mouse_hit_coords(get_element_hitbox(element))
+end
+function mouse_hit_coords(bX1, bY1, bX2, bY2)
+ local mX, mY = mp.get_mouse_pos()
return (mX >= bX1 and mX <= bX2 and mY >= bY1 and mY <= bY2)
end
@@ -128,11 +134,11 @@ function limit_range(min, max, val)
end
function get_slider_value(element)
- local fill_offsetV = element.metainfo.slider.border
- local paddingH = (element.h - (2*fill_offsetV)) / 2
+ local foV = element.layout.slider.border
+ local pH = (element.layout.geometry.h - (2*foV)) / 2
- local b_x1, b_x2 = element.hitbox.x1 + paddingH, element.hitbox.x2 - paddingH
- local s_min, s_max = element.metainfo.slider.min, element.metainfo.slider.max
+ local b_x1, b_x2 = element.hitbox.x1 + pH, element.hitbox.x2 - pH
+ local s_min, s_max = element.slider.min, element.slider.max
local pos = scale_value(b_x1, b_x2, s_min, s_max, mp.get_mouse_pos())
@@ -159,6 +165,15 @@ function mult_alpha(alphaA, alphaB)
return 255 - (((1-(alphaA/255)) * (1-(alphaB/255))) * 255)
end
+function add_area(name, x1, y1, x2, y2)
+ -- create area if needed
+ if (osc_param.areas[name] == nil) then
+ osc_param.areas[name] = {}
+ end
+ table.insert(osc_param.areas[name], {x1=x1, y1=y1, x2=x2, y2=y2})
+end
+
+
--
-- Tracklist Management
--
@@ -253,187 +268,175 @@ end
-- Element Management
--
--- do not use this function, use the wrappers below
-function register_element(type, x, y, an, w, h, style, content, eventresponder, metainfo2)
- -- type button, slider or box
- -- x, y position
- -- an alignment (see ASS standard)
- -- w, h size of hitbox
- -- style main style
- -- content what the element should display, can be a string or a function(ass)
- -- eventresponder A table containing functions mapped to events that shall be run on those events
- -- metainfo A table containing additional parameters for the element
-
- -- set default metainfo
- local metainfo = {}
- if not (metainfo2 == nil) then metainfo = metainfo2 end
- if metainfo.visible == nil then metainfo.visible = true end -- element visible at all?
- if metainfo.enabled == nil then metainfo.enabled = true end -- element clickable?
- if metainfo.styledown == nil then metainfo.styledown = true end -- should the element be styled with the elementDown style when clicked?
- if metainfo.softrepeat == nil then metainfo.softrepeat = false end -- should the *_down event be executed with "hold for repeat" behaviour?
- if metainfo.alpha1 == nil then metainfo.alpha1 = 0 end -- alpha1 of the element, 0 = opaque, 255 = transparent (primary fill alpha)
- if metainfo.alpha2 == nil then metainfo.alpha2 = 255 end -- alpha1 of the element, 0 = opaque, 255 = transparent (secondary fill alpha)
- if metainfo.alpha3 == nil then metainfo.alpha3 = 255 end -- alpha1 of the element, 0 = opaque, 255 = transparent (border alpha)
- if metainfo.alpha4 == nil then metainfo.alpha4 = 255 end -- alpha1 of the element, 0 = opaque, 255 = transparent (shadow alpha)
-
- if metainfo.visible then
- local ass = assdraw.ass_new()
-
- ass:append("{}") -- shitty hack to troll the new_event function into inserting a \n
- ass:new_event()
- ass:pos(x, y) -- positioning
- ass:an(an)
- ass:append(style) -- styling
-
- -- if the element is supposed to be disabled, style it accordingly and kill the eventresponders
- if metainfo.enabled == false then
- metainfo.alpha1 = 136
- eventresponder = nil
- end
+local elements = {}
- -- Calculate the hitbox
- local bX1, bY1, bX2, bY2 = get_hitbox_coords(x, y, an, w, h)
- local hitbox
- if type == "slider" then
- -- if it's a slider, cut the border and gap off, as those aren't of interest for eventhandling
- local fill_offset = metainfo.slider.border
- hitbox = {x1 = bX1 + fill_offset, y1 = bY1 + fill_offset, x2 = bX2 - fill_offset, y2 = bY2 - fill_offset}
- else
- hitbox = {x1 = bX1, y1 = bY1, x2 = bX2, y2 = bY2}
- end
+function prepare_elements()
- local element = {
- type = type,
- elem_ass = ass,
- hitbox = hitbox,
- w = w,
- h = h,
- x = x,
- y = y,
- content = content,
- eventresponder = eventresponder,
- metainfo = metainfo,
- state = {},
- }
-
- table.insert(elements, element)
+ -- remove elements without layout or invisble
+ local elements2 = {}
+ for n, element in pairs(elements) do
+ if not (element.layout == nil) and (element.visible) then
+ table.insert(elements2, element)
+ end
end
-end
+ elements = elements2
-function register_button(x, y, an, w, h, style, content, eventresponder, metainfo)
- register_element("button", x, y, an, w, h, style, content, eventresponder, metainfo)
-end
-
-function register_box(x, y, an, w, h, r, style, metainfo2)
- local ass = assdraw.ass_new()
- ass:draw_start()
- ass:round_rect_cw(0, 0, w, h, r)
- ass:draw_stop()
+ function elem_compare (a, b)
+ return a.layout.layer < b.layout.layer
+ end
- local metainfo = {}
- if not (metainfo2 == nil) then metainfo = metainfo2 end
+ table.sort(elements, elem_compare)
- metainfo.styledown = false
- register_element("box", x, y, an, w, h, style, ass, nil, metainfo)
-end
+ for _,element in pairs(elements) do
-function register_slider(x, y, an, w, h, style, min, max, markerF, posF, eventresponder, metainfo2)
- local metainfo = {}
- if not (metainfo2 == nil) then metainfo = metainfo2 end
- local slider1 = {}
- if (metainfo.slider == nil) then metainfo.slider = slider1 end
+ local elem_geo = element.layout.geometry
+ local style_ass = assdraw.ass_new()
- -- defaults
- if min == nil then metainfo.slider.min = 0 else metainfo.slider.min = min end
- if max == nil then metainfo.slider.max = 100 else metainfo.slider.max = max end
- if metainfo.slider.border == nil then metainfo.slider.border = 1 end
- if metainfo.slider.gap == nil then metainfo.slider.gap = 2 end
- if metainfo.slider.type == nil then metainfo.slider.type = "slider" end
+ -- prepare static elements
+ style_ass:append("{}") -- hack to troll new_event into inserting a \n
+ style_ass:new_event()
+ style_ass:pos(elem_geo.x, elem_geo.y)
+ style_ass:an(elem_geo.an)
+ style_ass:append(element.layout.style)
- metainfo.slider.markerF = markerF
- metainfo.slider.posF = posF
+ element.style_ass = style_ass
- -- prepare the box with markers
- local ass = assdraw.ass_new()
- local border, gap = metainfo.slider.border, metainfo.slider.gap
- local fill_offsetV = border + gap -- Vertical offset between element outline and drag-area
- local fill_offsetH = h / 2 -- Horizontal offset between element outline and drag-area
+ local static_ass = assdraw.ass_new()
- ass:draw_start()
- -- the box
- ass:rect_cw(0, 0, w, h);
+ if (element.type == "box") then
+ --draw box
+ static_ass:draw_start()
+ static_ass:round_rect_cw(0, 0, elem_geo.w, elem_geo.h,
+ element.layout.box.radius)
+ static_ass:draw_stop()
- -- the "hole"
- ass:rect_ccw(border, border, w - border, h - border)
- -- marker nibbles
- if not (markerF == nil) and gap > 0 then
- local markers = markerF()
- for n = 1, #markers do
- if (markers[n] > min) and (markers[n] < max) then
+ elseif (element.type == "slider") then
+ --draw static slider parts
- local coordL, coordR = fill_offsetH, (w - fill_offsetH)
+ local slider_lo = element.layout.slider
+ -- offset between element outline and drag-area
+ local foV = slider_lo.border + slider_lo.gap
+ local foH = 0
+ if (slider_lo.stype == "slider") then
+ foH = elem_geo.h / 2
+ elseif (slider_lo.stype == "bar") then
+ foH = slider_lo.border + slider_lo.gap
+ end
- local s = scale_value(min, max, coordL, coordR, markers[n])
+ static_ass:draw_start()
+
+ -- the box
+ static_ass:rect_cw(0, 0, elem_geo.w, elem_geo.h);
+
+ -- the "hole"
+ static_ass:rect_ccw(slider_lo.border, slider_lo.border,
+ elem_geo.w - slider_lo.border, elem_geo.h - slider_lo.border)
+
+ -- marker nibbles
+ if not (element.slider.markerF == nil) and (slider_lo.gap > 0) then
+ local markers = element.slider.markerF()
+ for _,marker in pairs(markers) do
+ if (marker > element.slider.min) and
+ (marker < element.slider.max) then
+
+ local s = scale_value(element.slider.min,
+ element.slider.max, foH, (elem_geo.w - foH), marker)
+
+ if (slider_lo.gap > 1) then -- draw triangles
+
+ local a = slider_lo.gap / 0.5 --0.866
+
+ --top
+ if (slider_lo.nibbles_top) then
+ static_ass:move_to(s - (a/2), slider_lo.border)
+ static_ass:line_to(s + (a/2), slider_lo.border)
+ static_ass:line_to(s, foV)
+ end
+
+ --bottom
+ if (slider_lo.nibbles_bottom) then
+ static_ass:move_to(s - (a/2),
+ elem_geo.h - slider_lo.border)
+ static_ass:line_to(s,
+ elem_geo.h - foV)
+ static_ass:line_to(s + (a/2),
+ elem_geo.h - slider_lo.border)
+ end
+
+ else -- draw 1px nibbles
+
+ --top
+ if (slider_lo.nibbles_top) then
+ static_ass:rect_cw(s - 0.5, slider_lo.gap,
+ s + 0.5, slider_lo.gap*2);
+ end
+
+ --bottom
+ if (slider_lo.nibbles_bottom) then
+ static_ass:rect_cw(s - 0.5,
+ elem_geo.h - slider_lo.gap*2,
+ s + 0.5,
+ elem_geo.h - slider_lo.gap);
+ end
+ end
+ end
+ end
+ end
+ end
- if gap > 1 then
- -- draw triangles
- local a = gap / 0.5 --0.866
- --top
- ass:move_to(s - (a/2), border)
- ass:line_to(s + (a/2), border)
- ass:line_to(s, border + gap)
+ element.static_ass = static_ass
- --bottom
- ass:move_to(s - (a/2), h - border)
- ass:line_to(s, h - border - gap)
- ass:line_to(s + (a/2), h - border)
- else
- -- draw 1px nibbles
- ass:rect_cw(s - 0.5, border, s + 0.5, border*2);
- ass:rect_cw(s - 0.5, h - border*2, s + 0.5, h - border);
- end
+ -- if the element is supposed to be disabled,
+ -- style it accordingly and kill the eventresponders
+ if not (element.enabled) then
+ element.layout.alpha[1] = 136
+ element.eventresponder = nil
+ end
- end
+ -- Calculate the hitbox
+ local bX1, bY1, bX2, bY2 = get_hitbox_coords_geo(elem_geo)
+ if type == "slider" then
+ -- if it's a slider, cut the border off,
+ -- as it is not of interest for eventhandling
+ element.hitbox = {
+ x1 = bX1 + slider.border, y1 = bY1 + slider.border,
+ x2 = bX2 - slider.border, y2 = bY2 - slider.border}
+ else
+ element.hitbox = {x1 = bX1, y1 = bY1, x2 = bX2, y2 = bY2}
end
end
-
- register_element("slider", x, y, an, w, h, style, ass, eventresponder, metainfo)
end
+
--
-- Element Rendering
--
function render_elements(master_ass)
- for n = 1, #elements do
-
+ for n=1, #elements do
local element = elements[n]
- local elem_ass = assdraw.ass_new()
- local elem_ass1 = element.elem_ass
- elem_ass:merge(elem_ass1)
+
+ local style_ass = assdraw.ass_new()
+ style_ass:merge(element.style_ass)
--alpha
- local alpha1 = element.metainfo.alpha1
- local alpha2 = element.metainfo.alpha2
- local alpha3 = element.metainfo.alpha3
- local alpha4 = element.metainfo.alpha4
-
- if not(state.animation == nil) then
- alpha1 = mult_alpha(element.metainfo.alpha1, state.animation)
- alpha2 = mult_alpha(element.metainfo.alpha2, state.animation)
- alpha3 = mult_alpha(element.metainfo.alpha3, state.animation)
- alpha4 = mult_alpha(element.metainfo.alpha4, state.animation)
+ local ar = element.layout.alpha
+ if not (state.animation == nil) then
+ ar = {}
+ for ai, av in pairs(element.layout.alpha) do
+ ar[ai] = mult_alpha(av, state.animation)
+ end
end
- elem_ass:append(string.format("{\\1a&H%X&\\2a&H%X&\\3a&H%X&\\4a&H%X&}", alpha1, alpha2, alpha3, alpha4))
-
+ style_ass:append(string.format("{\\1a&H%X&\\2a&H%X&\\3a&H%X&\\4a&H%X&}",
+ ar[1], ar[2], ar[3], ar[4]))
- if state.active_element == n then
+ if (state.active_element == n) then
-- run render event functions
if not (element.eventresponder.render == nil) then
@@ -442,11 +445,11 @@ function render_elements(master_ass)
if mouse_hit(element) then
-- mouse down styling
- if element.metainfo.styledown then
- elem_ass:append(osc_styles.elementDown)
+ if (element.styledown) then
+ style_ass:append(osc_styles.elementDown)
end
- if (element.metainfo.softrepeat == true) and (state.mouse_down_counter >= 15 and state.mouse_down_counter % 5 == 0) then
+ if (element.softrepeat) and (state.mouse_down_counter >= 15 and state.mouse_down_counter % 5 == 0) then
element.eventresponder[state.active_event_source .. "_down"](element)
end
state.mouse_down_counter = state.mouse_down_counter + 1
@@ -454,70 +457,84 @@ function render_elements(master_ass)
end
- if element.type == "slider" then
+ local elem_ass = assdraw.ass_new()
+
+ elem_ass:merge(style_ass)
+
+ if not (element.type == "button") then
+ elem_ass:merge(element.static_ass)
+ end
- elem_ass:merge(element.content) -- ASS objects
+
+
+ if (element.type == "slider") then
+
+ local slider_lo = element.layout.slider
+ local elem_geo = element.layout.geometry
+ local s_min, s_max = element.slider.min, element.slider.max
-- draw pos marker
- local pos = element.metainfo.slider.posF()
+ local pos = element.slider.posF()
if not (pos == nil) then
- pos = limit_range(element.metainfo.slider.min, element.metainfo.slider.max, pos)
-
- local fill_offsetV = element.metainfo.slider.border + element.metainfo.slider.gap
- local fill_offsetH = element.h/2
+ local foV = slider_lo.border + slider_lo.gap
+ local foH = 0
+ if (slider_lo.stype == "slider") then
+ foH = elem_geo.h / 2
+ elseif (slider_lo.stype == "bar") then
+ foH = slider_lo.border + slider_lo.gap
+ end
- local coordL, coordR = fill_offsetH, (element.w - fill_offsetH)
+ pos = limit_range(s_min, s_max, pos)
- local xp = scale_value(element.metainfo.slider.min, element.metainfo.slider.max, coordL, coordR, pos)
+ local xp = scale_value(s_min, s_max,
+ foH, (elem_geo.w - foH), pos)
-- the filling, draw it only if positive
- local innerH = element.h - (2*fill_offsetV)
-
- if element.metainfo.slider.type == "bar" then
- elem_ass:rect_cw(fill_offsetV, fill_offsetV, xp, element.h - fill_offsetV)
- else
- elem_ass:move_to(xp, fill_offsetV)
- elem_ass:line_to(xp+(innerH/2), (innerH/2)+fill_offsetV)
- elem_ass:line_to(xp, (innerH)+fill_offsetV)
- elem_ass:line_to(xp-(innerH/2), (innerH/2)+fill_offsetV)
+ local innerH = elem_geo.h - (2*foV)
+
+ if (slider_lo.stype == "bar") then
+ elem_ass:rect_cw(foH, foV, xp, elem_geo.h - foV)
+ elseif (slider_lo.stype == "slider") then
+ elem_ass:move_to(xp, foV)
+ elem_ass:line_to(xp+(innerH/2), (innerH/2)+foV)
+ elem_ass:line_to(xp, (innerH)+foV)
+ elem_ass:line_to(xp-(innerH/2), (innerH/2)+foV)
end
end
elem_ass:draw_stop()
-- add tooltip
- if not (element.metainfo.slider.tooltipF == nil) then
+ if not (element.slider.tooltipF == nil) then
if mouse_hit(element) then
local sliderpos = get_slider_value(element)
- local tooltiplabel = element.metainfo.slider.tooltipF(sliderpos)
- local s_min, s_max = element.metainfo.slider.min, element.metainfo.slider.max
+ local tooltiplabel = element.slider.tooltipF(sliderpos)
local an = 2
- if (sliderpos < (s_min + 5)) then
- an = 1
- elseif (sliderpos > (s_max - 5)) then
- an = 3
+ if (slider_lo.adjust_tooltip) then
+ if (sliderpos < (s_min + 5)) then
+ an = 1
+ elseif (sliderpos > (s_max - 5)) then
+ an = 3
+ end
end
elem_ass:new_event()
- elem_ass:pos(mp.get_mouse_pos(), element.y - (element.h) - 0) -- positioning
+ elem_ass:pos(mp.get_mouse_pos(),
+ element.hitbox.y1 - slider_lo.border)
elem_ass:an(an)
- elem_ass:append(osc_styles.vidtitle) -- styling
+ elem_ass:append(slider_lo.tooltip_style)
elem_ass:append(tooltiplabel)
end
end
-
-
- elseif element.type == "box" then
- elem_ass:merge(element.content) -- ASS objects
elseif type(element.content) == "function" then
element.content(elem_ass) -- function objects
- else
+ elseif not (element.content == nil) then
elem_ass:append(element.content) -- text objects
end
@@ -574,61 +591,128 @@ end
-- Initialisation and Layout
--
--- OSC INIT
-function osc_init()
- msg.debug("osc_init")
+function new_element(name, type)
+ elements[name] = {}
+ elements[name].type = type
- -- kill old Elements
- elements = {}
+ -- add default stuff
+ elements[name].eventresponder = {}
+ elements[name].visible = true
+ elements[name].enabled = true
+ elements[name].softrepeat = false
+ elements[name].styledown = (type == "button")
+ elements[name].state = {}
- -- set canvas resolution according to display aspect and scaling setting
- local baseResY = 720
- local display_w, display_h, display_aspect = mp.get_screen_size()
- local scale = 1
-
- if (mp.get_property("video") == "no") then -- dummy/forced window
- scale = user_opts.scaleforcedwindow
- elseif state.fullscreen then
- scale = user_opts.scalefullscreen
- else
- scale = user_opts.scalewindowed
+ if (type == "slider") then
+ elements[name].slider = {min = 0, max = 100}
end
- if user_opts.vidscale then
- osc_param.playresy = baseResY / scale
+ return elements[name]
+end
+
+function add_layout(name)
+ if not (elements[name] == nil) then
+ -- new layout
+ elements[name].layout = {}
+
+ -- set layout defaults
+ elements[name].layout.layer = 50
+ elements[name].layout.alpha = {[1] = 0, [2] = 255, [3] = 255, [4] = 255}
+
+ if (elements[name].type == "slider") then
+ -- slider defaults
+ elements[name].layout.slider = {
+ border = 1,
+ gap = 1,
+ nibbles_top = true,
+ nibbles_bottom = true,
+ stype = "slider",
+ adjust_tooltip = true,
+ tooltip_style = "",
+ }
+ elseif (elements[name].type == "box") then
+ elements[name].layout.box = {radius = 0}
+ end
+
+ return elements[name].layout
else
- osc_param.playresy = display_h / scale
+ msg.error("Can't add_layout to element \""..name.."\", doesn't exist.")
end
- osc_param.playresx = osc_param.playresy * display_aspect
+end
+
+--
+-- Layouts
+--
+
+local layouts = {}
+
+-- Classic box layout
+layouts["box"] = function ()
+
+ local osc_geo = {
+ w = 550, -- width
+ h = 138, -- height
+ r = 10, -- corner-radius
+ p = 15, -- padding
+ }
-- make sure the OSC actually fits into the video
- if (osc_param.playresx < (osc_param.osc_w + (2 * osc_param.osc_p))) then
- osc_param.playresy = (osc_param.osc_w + (2 * osc_param.osc_p)) / display_aspect
- osc_param.playresx = osc_param.playresy * display_aspect
+ if (osc_param.playresx < (osc_geo.w + (2 * osc_geo.p))) then
+ osc_param.playresy = (osc_geo.w+(2*osc_geo.p))/osc_param.display_aspect
+ osc_param.playresx = osc_param.playresy * osc_param.display_aspect
end
-- position of the controller according to video aspect and valignment
- osc_param.posX = math.floor(get_align(user_opts.halign, osc_param.playresx, osc_param.osc_w, 0))
- osc_param.posY = math.floor(get_align(user_opts.valign, osc_param.playresy, osc_param.osc_h, 0))
+ local posX = math.floor(get_align(user_opts.halign, osc_param.playresx,
+ osc_geo.w, 0))
+ local posY = math.floor(get_align(user_opts.valign, osc_param.playresy,
+ osc_geo.h, 0))
+
+ -- position offset for contents aligned at the borders of the box
+ local pos_offsetX = (osc_geo.w - (2*osc_geo.p)) / 2
+ local pos_offsetY = (osc_geo.h - (2*osc_geo.p)) / 2
- -- Some calculations on stuff we'll need
- -- vertical/horizontal position offset for contents aligned at the borders of the box
- osc_param.pos_offsetX, osc_param.pos_offsetY = (osc_param.osc_w - (2*osc_param.osc_p)) / 2, (osc_param.osc_h - (2*osc_param.osc_p)) / 2
+ osc_param.areas = {} -- delete areas
+
+ -- area for active mouse input
+ add_area("input", get_hitbox_coords(posX, posY, 5, osc_geo.w, osc_geo.h))
+
+ -- area for show/hide
+ local sh_area_y0, sh_area_y1
+ if user_opts.valign > 0 then
+ -- deadzone above OSC
+ sh_area_y0 = get_align(-1 + (2*user_opts.deadzonesize),
+ posY - (osc_geo.h / 2), 0, 0)
+ sh_area_y1 = osc_param.playresy
+ else
+ -- deadzone below OSC
+ sh_area_y0 = 0
+ sh_area_y1 = (posY + (osc_geo.h / 2)) +
+ get_align(1 - (2*user_opts.deadzonesize),
+ osc_param.playresy - (posY + (osc_geo.h / 2)), 0, 0)
+ end
+ add_area("showhide", 0, sh_area_y0, osc_param.playresx, sh_area_y1)
-- fetch values
- local osc_w, osc_h, osc_r, osc_p = osc_param.osc_w, osc_param.osc_h, osc_param.osc_r, osc_param.osc_p
- local pos_offsetX, pos_offsetY = osc_param.pos_offsetX, osc_param.pos_offsetY
- local posX, posY = osc_param.posX, osc_param.posY
+ local osc_w, osc_h, osc_r, osc_p =
+ osc_geo.w, osc_geo.h, osc_geo.r, osc_geo.p
+
+ local lo
--
- -- Backround box
+ -- Background box
--
- local metainfo = {}
- metainfo.alpha1 = user_opts.boxalpha
- metainfo.alpha3 = user_opts.boxalpha
- register_box(posX, posY, 5, osc_w, osc_h, osc_r, osc_styles.box, metainfo)
+ new_element("bgbox", "box")
+ lo = add_layout("bgbox")
+
+ lo.geometry = {x = posX, y = posY, an = 5, w = osc_w, h = osc_h}
+ lo.layer = 10
+ lo.style = osc_styles.box
+ lo.alpha[1] = user_opts.boxalpha
+ lo.alpha[3] = user_opts.boxalpha
+ lo.box.radius = osc_r
--
-- Title row
@@ -636,312 +720,490 @@ function osc_init()
local titlerowY = posY - pos_offsetY - 10
- -- title
- local contentF = function (ass)
- local title = mp.get_property_osd("media-title")
- if not (title == nil) then
+ lo = add_layout("title")
+ lo.geometry = {x = posX, y = titlerowY, an = 8, w = 496, h = 12}
+ lo.style = osc_styles.vidtitle
- if #title > 80 then
- title = string.format("{\\fscx%f}", (80 / #title) * 100) .. title
- end
+ lo = add_layout("pl_prev")
+ lo.geometry =
+ {x = (posX - pos_offsetX), y = titlerowY, an = 7, w = 12, h = 12}
+ lo.style = osc_styles.vidtitle
- ass:append(title)
- else
- ass:append("mpv")
- end
+ lo = add_layout("pl_next")
+ lo.geometry =
+ {x = (posX + pos_offsetX), y = titlerowY, an = 9, w = 12, h = 12}
+ lo.style = osc_styles.vidtitle
+
+ --
+ -- Big buttons
+ --
+
+ local bigbtnrowY = posY - pos_offsetY + 35
+ local bigbtndist = 60
+
+ lo = add_layout("playpause")
+ lo.geometry =
+ {x = posX, y = bigbtnrowY, an = 5, w = 40, h = 40}
+ lo.style = osc_styles.bigButtons
+
+ lo = add_layout("skipback")
+ lo.geometry =
+ {x = posX - bigbtndist, y = bigbtnrowY, an = 5, w = 40, h = 40}
+ lo.style = osc_styles.bigButtons
+
+ lo = add_layout("skipfrwd")
+ lo.geometry =
+ {x = posX + bigbtndist, y = bigbtnrowY, an = 5, w = 40, h = 40}
+ lo.style = osc_styles.bigButtons
+
+ lo = add_layout("ch_prev")
+ lo.geometry =
+ {x = posX - (bigbtndist * 2), y = bigbtnrowY, an = 5, w = 40, h = 40}
+ lo.style = osc_styles.bigButtons
+
+ lo = add_layout("ch_next")
+ lo.geometry =
+ {x = posX + (bigbtndist * 2), y = bigbtnrowY, an = 5, w = 40, h = 40}
+ lo.style = osc_styles.bigButtons
+
+ lo = add_layout("cy_audio")
+ lo.geometry =
+ {x = posX - pos_offsetX, y = bigbtnrowY, an = 1, w = 70, h = 18}
+ lo.style = osc_styles.smallButtonsL
+
+ lo = add_layout("cy_sub")
+ lo.geometry =
+ {x = posX - pos_offsetX, y = bigbtnrowY, an = 7, w = 70, h = 18}
+ lo.style = osc_styles.smallButtonsL
+
+ lo = add_layout("tog_fs")
+ lo.geometry =
+ {x = posX+pos_offsetX, y = bigbtnrowY, an = 6, w = 25, h = 25}
+ lo.style = osc_styles.smallButtonsR
+
+ --
+ -- Seekbar
+ --
+
+ lo = add_layout("seekbar")
+ lo.geometry =
+ {x = posX, y = posY+pos_offsetY-22, an = 2, w = pos_offsetX*2, h = 15}
+ lo.style = osc_styles.timecodes
+ lo.slider.tooltip_style = osc_styles.vidtitle
+
+ --
+ -- Timecodes + Cache
+ --
+
+ local bottomrowY = posY + pos_offsetY - 5
+
+ lo = add_layout("tc_left")
+ lo.geometry =
+ {x = posX - pos_offsetX, y = bottomrowY, an = 4, w = 110, h = 18}
+ lo.style = osc_styles.timecodes
+
+ lo = add_layout("tc_right")
+ lo.geometry =
+ {x = posX + pos_offsetX, y = bottomrowY, an = 6, w = 110, h = 18}
+ lo.style = osc_styles.timecodes
+
+ lo = add_layout("cache")
+ lo.geometry =
+ {x = posX, y = bottomrowY, an = 5, w = 110, h = 18}
+ lo.style = osc_styles.timecodes
+
+end
+
+-- slim box layout
+layouts["slimbox"] = function ()
+
+ local osc_geo = {
+ w = 600, -- width
+ h = 20, -- height
+ r = 20, -- corner-radius
+ p = 20, -- padding
+ }
+
+ -- make sure the OSC actually fits into the video
+ if (osc_param.playresx < (osc_geo.w + (2 * osc_geo.p))) then
+ osc_param.playresy = (osc_geo.w+(2*osc_geo.p))/osc_param.display_aspect
+ osc_param.playresx = osc_param.playresy * osc_param.display_aspect
end
- local eventresponder = {}
- eventresponder.mouse_btn0_up = function ()
+ -- position of the controller according to video aspect and valignment
+ local posX = math.floor(get_align(user_opts.halign, osc_param.playresx,
+ osc_geo.w, 0))
+ local posY = math.floor(get_align(user_opts.valign, osc_param.playresy,
+ osc_geo.h, 0))
- local title = mp.get_property("media-title")
- local pl_count = tonumber(mp.get_property("playlist-count"))
+ -- position offset for contents aligned at the borders of the box
+ local pos_offsetX = (osc_geo.w - (2*osc_geo.p)) / 2
+ local pos_offsetY = (osc_geo.h - (2*osc_geo.p)) / 2
- if pl_count > 1 then
- local playlist_pos = countone(tonumber(mp.get_property("playlist-pos")))
- title = "[" .. playlist_pos .. "/" .. pl_count .. "] " .. title
- end
+ osc_param.areas = {} -- delete areas
- show_message(title)
+ -- area for active mouse input
+ add_area("input", get_hitbox_coords(posX, posY, 5, osc_geo.w, osc_geo.h))
+
+ -- area for show/hide
+ local sh_area_y0, sh_area_y1
+ if user_opts.valign > 0 then
+ -- deadzone above OSC
+ sh_area_y0 = get_align(-1 + (2*user_opts.deadzonesize),
+ posY - (osc_geo.h / 2), 0, 0)
+ sh_area_y1 = osc_param.playresy
+ else
+ -- deadzone below OSC
+ sh_area_y0 = 0
+ sh_area_y1 = (posY + (osc_geo.h / 2)) +
+ get_align(1 - (2*user_opts.deadzonesize),
+ osc_param.playresy - (posY + (osc_geo.h / 2)), 0, 0)
end
- eventresponder.mouse_btn2_up = function () show_message(mp.get_property("filename")) end
+ add_area("showhide", 0, sh_area_y0, osc_param.playresx, sh_area_y1)
- register_button(posX, titlerowY, 8, 496, 12, osc_styles.vidtitle, contentF, eventresponder, nil)
+ -- fetch values
+ local osc_w, osc_h, osc_r, osc_p =
+ osc_geo.w, osc_geo.h, osc_geo.r, osc_geo.p
- -- If we have more than one playlist entry, render playlist navigation buttons
- local metainfo = {}
- metainfo.visible = (tonumber(mp.get_property("playlist-count")) > 1)
+ local lo
- -- playlist prev
- local eventresponder = {}
- eventresponder.mouse_btn0_up = function () mp.commandv("playlist_prev", "weak") end
- eventresponder["shift+mouse_btn0_up"] = function () show_message(mp.get_property_osd("playlist"), 3) end
- register_button(posX - pos_offsetX, titlerowY, 7, 12, 12, osc_styles.vidtitle, "◀", eventresponder, metainfo)
+ local tc_w = 70
- -- playlist next
- local eventresponder = {}
- eventresponder.mouse_btn0_up = function () mp.commandv("playlist_next", "weak") end
- eventresponder["shift+mouse_btn0_up"] = function () show_message(mp.get_property_osd("playlist"), 3) end
- register_button(posX + pos_offsetX, titlerowY, 9, 12, 12, osc_styles.vidtitle, "▶", eventresponder, metainfo)
- --
- -- Big buttons
- --
+ new_element("bgbox", "box")
+ lo = add_layout("bgbox")
- local bigbuttonrowY = posY - pos_offsetY + 35
- local bigbuttondistance = 60
+ lo.geometry = {x = posX, y = posY, an = 5, w = osc_w, h = osc_h}
+ lo.layer = 10
+ lo.style = osc_styles.box
+ lo.alpha[1] = user_opts.boxalpha
+ lo.box.radius = osc_r
- --play/pause
- local contentF = function (ass)
- if mp.get_property("pause") == "yes" then
- ass:append("\238\132\129")
- else
- ass:append("\238\128\130")
- end
- end
- local eventresponder = {}
- eventresponder.mouse_btn0_up = function () mp.commandv("cycle", "pause") end
- register_button(posX, bigbuttonrowY, 5, 40, 40, osc_styles.bigButtons, contentF, eventresponder, nil)
- --skipback
- local metainfo = {}
- metainfo.softrepeat = true
+ new_element("bgbar1", "box")
+ lo = add_layout("bgbar1")
- local eventresponder = {}
- eventresponder.mouse_btn0_down = function () mp.commandv("seek", -5, "relative", "keyframes") end
- eventresponder["shift+mouse_btn0_down"] = function () mp.commandv("frame_back_step") end
- eventresponder.mouse_btn2_dow