diff options
author | ChrisK2 <spam@kalania.de> | 2014-08-15 15:24:22 +0200 |
---|---|---|
committer | ChrisK2 <spam@kalania.de> | 2014-08-15 15:24:22 +0200 |
commit | 364e06261a2ffd39afea1d029d4dcc87ef1d6144 (patch) | |
tree | 54f090f68f2ca244856e67977b1fcf513fc821ac /player/lua/osc.lua | |
parent | d5940fabcd6b477c72430c84e460975060807646 (diff) | |
download | mpv-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
Diffstat (limited to 'player/lua/osc.lua')
-rw-r--r-- | player/lua/osc.lua | 1350 |
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 |