summaryrefslogtreecommitdiffstats
path: root/mpvcore/player/lua/osc.lua
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2013-12-17 00:53:22 +0100
committerwm4 <wm4@nowhere>2013-12-17 00:53:22 +0100
commite44911142914783c9ec717f329bd9b6a8bb9b70e (patch)
tree92bb653f7d56553ffd3bb6e5a22ffc0db91142e8 /mpvcore/player/lua/osc.lua
parent7dc7b900c622235d595337c988a0c75280084b7c (diff)
downloadmpv-e44911142914783c9ec717f329bd9b6a8bb9b70e.tar.bz2
mpv-e44911142914783c9ec717f329bd9b6a8bb9b70e.tar.xz
Move mpvcore/player/ to player/
Diffstat (limited to 'mpvcore/player/lua/osc.lua')
-rw-r--r--mpvcore/player/lua/osc.lua1288
1 files changed, 0 insertions, 1288 deletions
diff --git a/mpvcore/player/lua/osc.lua b/mpvcore/player/lua/osc.lua
deleted file mode 100644
index d1dbf3e8b4..0000000000
--- a/mpvcore/player/lua/osc.lua
+++ /dev/null
@@ -1,1288 +0,0 @@
--- osc.lua
-
-local assdraw = require 'mp.assdraw'
-local msg = require 'mp.msg'
-
---
--- Parameters
---
-
--- default user option values
--- do not touch, change them in plugin_osc.conf
-local user_opts = {
- showwindowed = true, -- show OSC when windowed?
- showfullscreen = true, -- show OSC when fullscreen?
- scalewindowed = 1, -- scaling of the controller when windowed
- scalefullscreen = 1, -- scaling of the controller when fullscreen
- scaleforcedwindow = 2, -- scaling of the controller when rendered on a forced (dummy) window
- vidscale = true, -- scale the controller with the video?
- valign = 0.8, -- vertical alignment, -1 (top) to 1 (bottom)
- halign = 0, -- horizontal alignment, -1 (left) to 1 (right)
- boxalpha = 80, -- alpha of the background box, 0 (opaque) to 255 (fully transparent)
- hidetimeout = 500, -- duration in ms until the OSC hides if no mouse movement, negative value disables autohide
- fadeduration = 200, -- duration of fade out in ms, 0 = no fade
- deadzonesize = 0, -- size of deadzone
- minmousemove = 3, -- minimum amount of pixels the mouse has to move between ticks to make the OSC show up
- seektooltip = false, -- 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)
-}
-
-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()
- 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
-}
-
-local osc_styles = {
- bigButtons = "{\\blur0\\bord0\\1c&HFFFFFF\\3c&HFFFFFF\\fs50\\fnmpv-osd-symbols}",
- smallButtonsL = "{\\blur0\\bord0\\1c&HFFFFFF\\3c&HFFFFFF\\fs20\\fnmpv-osd-symbols}",
- smallButtonsLlabel = "{\\fs17\\fn" .. mp.property_get("options/osd-font") .. "}",
- smallButtonsR = "{\\blur0\\bord0\\1c&HFFFFFF\\3c&HFFFFFF\\fs30\\fnmpv-osd-symbols}",
-
- elementDown = "{\\1c&H999999}",
- timecodes = "{\\blur0\\bord0\\1c&HFFFFFF\\3c&HFFFFFF\\fs20}",
- vidtitle = "{\\blur0\\bord0\\1c&HFFFFFF\\3c&HFFFFFF\\fs12}",
- box = "{\\rDefault\\blur0\\bord1\\1c&H000000\\3c&HFFFFFF}",
-}
-
--- internal states, do not touch
-local state = {
- showtime, -- time of last invocation (last mouse move)
- osc_visible = false,
- anistart, -- time when the animation started
- anitype, -- current type of animation
- animation, -- current animation alpha
- mouse_down_counter = 0, -- used for softrepeat
- active_element = nil, -- nil = none, 0 = background, 1+ = see elements[]
- active_event_source = nil, -- the "button" that issued the current event
- rightTC_trem = true, -- if the right timcode should display total or remaining time
- tc_ms = false, -- Should the timecodes display their time with milliseconds
- mp_screen_sizeX, mp_screen_sizeY, -- last screen-resolution, to detect resolution changes to issue reINITs
- initREQ = false, -- is a re-init request pending?
- last_seek, -- last seek position, to avoid deadlocks by repeatedly seeking to the same position
- last_mouseX, last_mouseY, -- last mouse position, to detect siginificant mouse movement
- message_text,
- message_timeout,
-}
-
---
--- User Settings Management
---
-
-function val2str(val)
- local strval = val
- if type(val) == "boolean" then
- if val then strval = "yes" else strval = "no" end
- end
-
- return strval
-end
-
--- converts val to type of desttypeval
-function typeconv(desttypeval, val)
- if type(desttypeval) == "boolean" then
- if val == "yes" then
- val = true
- elseif val == "no" then
- val = false
- else
- msg.error("Error: Can't convert " .. val .. " to boolean!")
- val = nil
- end
- elseif type(desttypeval) == "number" then
- if not (tonumber(val) == nil) then
- val = tonumber(val)
- else
- msg.error("Error: Can't convert " .. val .. " to number!")
- val = nil
- end
- end
- return val
-end
-
--- Automagical config handling
--- options: A table with options setable via config with assigned default values. The type of the default values is important for
--- converting the values read from the config file back. Do not use "nil" as a default value!
--- identifier: A simple indentifier string for the config file. Make sure this doesn't collide with other scripts.
-
--- How does it work:
--- Existance of the configfile will be checked, if it doesn't exist, the default values from the options table will be written in a new
--- file, commented out. If it exits, the key/value pairs will be read, and values of keys that exist in the options table will overwrite
--- their value. Keys that don't exist in the options table will be ignored, keys that don't exits in the config will keep their default
--- value. The value's types will automatically be converted to the type used in the options table.
-function read_config(options, identifier)
-
- local conffilename = "plugin_" .. identifier .. ".conf"
- local conffile = mp.find_config_file(conffilename)
- local f = io.open(conffile,"r")
- if f == nil then
- -- config not found
- else
- -- config exists, read values
- local linecounter = 1
- for line in f:lines() do
- if string.find(line, "#") == 1 then
-
- else
- local eqpos = string.find(line, "=")
- if eqpos == nil then
-
- else
- local key = string.sub(line, 1, eqpos-1)
- local val = string.sub(line, eqpos+1)
-
- -- match found values with defaults
- if options[key] == nil then
- msg.warn(conffilename..":"..linecounter.." unknown key " .. key .. ", ignoring")
- else
- local convval = typeconv(options[key], val)
- if convval == nil then
- msg.error(conffilename..":"..linecounter.." error converting value '" .. val .. "' for key '" .. key .. "'")
- else
- options[key] = convval
- end
- end
- end
- end
- linecounter = linecounter + 1
- end
- io.close(f)
- end
-end
-
--- read configfile
-read_config(user_opts, "osc")
-
-
---
--- Helperfunctions
---
-
-function scale_value(x0, x1, y0, y1, val)
- local m = (y1 - y0) / (x1 - x0)
- local b = y0 - (m * x0)
- return (m * val) + b
-end
-
--- returns hitbox spanning coordinates (top left, bottom right corner) according to alignment
-function get_hitbox_coords(x, y, an, w, h)
-
- local alignments = {
- [1] = function () return x, y-h, x+w, y end,
- [2] = function () return x-(w/2), y-h, x+(w/2), y end,
- [3] = function () return x-w, y-h, x, y end,
-
- [4] = function () return x, y-(h/2), x+w, y+(h/2) end,
- [5] = function () return x-(w/2), y-(h/2), x+(w/2), y+(h/2) end,
- [6] = function () return x-w, y-(h/2), x, y+(h/2) end,
-
- [7] = function () return x, y, x+w, y+h end,
- [8] = function () return x-(w/2), y, x+(w/2), y+h end,
- [9] = function () return x-w, y, x, y+h end,
- }
-
- return alignments[an]()
-end
-
-function get_element_hitbox(element)
- 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 (mX >= bX1 and mX <= bX2 and mY >= bY1 and mY <= bY2)
-end
-
-function limit_range(min, max, val)
- if val > max then
- val = max
- elseif val < min then
- val = min
- end
- return val
-end
-
-function get_slider_value(element)
- local fill_offsetV = element.metainfo.slider.border + element.metainfo.slider.gap
- local paddingH = (element.h - (2*fill_offsetV)) / 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 pos = scale_value(b_x1, b_x2, s_min, s_max, mp.get_mouse_pos())
-
- return limit_range(s_min, s_max, pos)
-end
-
-function countone(val)
- if not (user_opts.iamaprogrammer) then
- val = val + 1
- end
- return val
-end
-
--- align: -1 .. +1
--- frame: size of the containing area
--- obj: size of the object that should be positioned inside the area
--- margin: min. distance from object to frame (as long as -1 <= align <= +1)
-function get_align(align, frame, obj, margin)
- return (frame / 2) + (((frame / 2) - margin - (obj / 2)) * align)
-end
-
--- multiplies two alpha values, formular can probably be improved
-function mult_alpha(alphaA, alphaB)
- return 255 - (((1-(alphaA/255)) * (1-(alphaB/255))) * 255)
-end
-
---
--- Tracklist Management
---
-
-local nicetypes = {video = "Video", audio = "Audio", sub = "Subtitle"}
-
--- updates the OSC internal playlists, should be run each time the track-layout changes
-function update_tracklist()
- local tracktable = mp.get_track_list()
-
- -- by osc_id
- tracks_osc = {}
- tracks_osc.video, tracks_osc.audio, tracks_osc.sub = {}, {}, {}
- -- by mpv_id
- tracks_mpv = {}
- tracks_mpv.video, tracks_mpv.audio, tracks_mpv.sub = {}, {}, {}
- for n = 1, #tracktable do
- if not (tracktable[n].type == "unkown") then
- local type = tracktable[n].type
- local mpv_id = tonumber(tracktable[n].id)
-
- -- by osc_id
- table.insert(tracks_osc[type], tracktable[n])
-
- -- by mpv_id
- tracks_mpv[type][mpv_id] = tracktable[n]
- tracks_mpv[type][mpv_id].osc_id = #tracks_osc[type]
- end
- end
-end
-
--- return a nice list of tracks of the given type (video, audio, sub)
-function get_tracklist(type)
- local msg = "Available " .. nicetypes[type] .. " Tracks: "
- local select_scale = 100
- if #tracks_osc[type] == 0 then
- msg = msg .. "none"
- else
- for n = 1, #tracks_osc[type] do
- local track = tracks_osc[type][n]
- local lang, title, selected = "unkown", "", "{\\fscx" .. select_scale .. "\\fscy" .. select_scale .. "}○{\\fscx100\\fscy100}"
- if not(track.language == nil) then lang = track.language end
- if not(track.title == nil) then title = track.title end
- if (track.id == tonumber(mp.property_get(type))) then
- selected = "{\\fscx" .. select_scale .. "\\fscy" .. select_scale .. "}●{\\fscx100\\fscy100}"
- end
- msg = msg .. "\n" .. selected .. " " .. n .. ": [" .. lang .. "] " .. title
- end
- end
- return msg
-end
-
--- relatively change the track of given <type> by <next> tracks (+1 -> next, -1 -> previous)
-function set_track(type, next)
- local current_track_mpv, current_track_osc
- if (mp.property_get(type) == "no") then
- current_track_osc = 0
- else
- current_track_mpv = tonumber(mp.property_get(type))
- current_track_osc = tracks_mpv[type][current_track_mpv].osc_id
- end
- local new_track_osc = (current_track_osc + next) % (#tracks_osc[type] + 1)
- local new_track_mpv
- if new_track_osc == 0 then
- new_track_mpv = "no"
- else
- new_track_mpv = tracks_osc[type][new_track_osc].id
- end
-
- mp.send_command("no-osd set " .. type .. " " .. new_track_mpv)
-
- if (new_track_osc == 0) then
- show_message(nicetypes[type] .. " Track: none")
- else
- show_message(nicetypes[type] .. " Track: " .. new_track_osc .. "/" .. #tracks_osc[type]
- .. " [" .. (tracks_osc[type][new_track_osc].language or "unkown") .. "] " .. (tracks_osc[type][new_track_osc].title or ""))
- end
-end
-
--- get the currently selected track of <type>, OSC-style counted
-function get_track(type)
- local track = mp.property_get(type)
- if (track == "no" or track == nil) then
- return 0
- else
- return tracks_mpv[type][tonumber(track)].osc_id
- end
-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
-
- -- 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 + metainfo.slider.gap
- 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
-
- local element = {
- type = type,
- elem_ass = ass,
- hitbox = hitbox,
- w = w,
- h = h,
- x = x,
- y = y,
- content = content,
- eventresponder = eventresponder,
- metainfo = metainfo,
- }
-
- table.insert(elements, element)
- end
-end
-
-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()
-
- local metainfo = {}
- if not (metainfo2 == nil) then metainfo = metainfo2 end
-
- metainfo.styledown = false
-
- register_element("box", x, y, an, w, h, style, ass, nil, metainfo)
-end
-
-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
-
- -- 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
-
- metainfo.slider.markerF = markerF
- metainfo.slider.posF = posF
-
- -- 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
-
- ass:draw_start()
-
- -- the box
- ass:rect_cw(0, 0, w, h);
-
- -- 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
-
- local coordL, coordR = fill_offsetH, (w - fill_offsetH)
-
- local s = scale_value(min, max, coordL, coordR, markers[n])
-
- 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)
-
- --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
-
- end
- 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
-
- local element = elements[n]
- local elem_ass = assdraw.ass_new()
- local elem_ass1 = element.elem_ass
- elem_ass:merge(elem_ass1)
-
- --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)
- end
-
- elem_ass:append(string.format("{\\1a&H%X&\\2a&H%X&\\3a&H%X&\\4a&H%X&}", alpha1, alpha2, alpha3, alpha4))
-
-
- if state.active_element == n then
-
- -- run render event functions
- if not (element.eventresponder.render == nil) then
- element.eventresponder.render(element)
- end
-
- if mouse_hit(element) then
- -- mouse down styling
- if element.metainfo.styledown then
- elem_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
- element.eventresponder[state.active_event_source .. "_down"](element)
- end
- state.mouse_down_counter = state.mouse_down_counter + 1
- end
-
- end
-
- if element.type == "slider" then
-
- elem_ass:merge(element.content) -- ASS objects
-
- -- draw pos marker
- local pos = element.metainfo.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 coordL, coordR = fill_offsetH, (element.w - fill_offsetH)
-
- local xp = scale_value(element.metainfo.slider.min, element.metainfo.slider.max, coordL, coordR, 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)
- end
- end
-
- elem_ass:draw_stop()
-
- -- add tooltip
- if not (element.metainfo.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 an = 2
- if (sliderpos < (s_min + 10)) then
- an = 1
- elseif (sliderpos > (s_max - 10)) then
- an = 3
- end
-
- elem_ass:new_event()
- elem_ass:pos(mp.get_mouse_pos(), element.y - (element.h) - 0) -- positioning
- elem_ass:an(an)
- elem_ass:append(osc_styles.vidtitle) -- styling
- 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
- elem_ass:append(element.content) -- text objects
- end
-
- master_ass:merge(elem_ass)
- end
-end
-
---
--- Message display
---
-
-function show_message(text, duration)
-
- if duration == nil then
- duration = tonumber(mp.property_get("options/osd-duration")) / 1000
- end
-
- -- cut the text short, otherwise the following functions may slow down massively on huge input
- text = string.sub(text, 0, 4000)
-
- -- replace actual linebreaks with ASS linebreaks and get the amount of lines along the way
- local lines
- text, lines = string.gsub(text, "\n", "\\N")
-
- -- append a Zero-Width-Space to . and _ to enable linebreaking of long filenames
- text = string.gsub(text, "%.", ".\226\128\139")
- text = string.gsub(text, "_", "_\226\128\139")
-
- -- scale the fontsize for longer multi-line output
- local fontsize, outline = tonumber(mp.property_get("options/osd-font-size")), tonumber(mp.property_get("options/osd-border-size"))
- if lines > 12 then
- fontsize, outline = fontsize / 2, outline / 1.5
- elseif lines > 8 then
- fontsize, outline = fontsize / 1.5, outline / 1.25
- end
-
- local style = "{\\bord" .. outline .. "\\fs" .. fontsize .. "}"
-
- state.message_text = style .. text
- state.message_timeout = mp.get_timer() + duration
-end
-
-function render_message(ass)
- if not(state.message_timeout == nil) and not(state.message_text == nil) and state.message_timeout > mp.get_timer() then
- ass:new_event()
- ass:append(state.message_text)
- else
- state.message_text = nil
- state.message_timeout = nil
- end
-end
-
---
--- Initialisation and Layout
---
-
--- OSC INIT
-function osc_init()
- -- kill old Elements
- elements = {}
-
- -- 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.property_get("video") == "no") then -- dummy/forced window
- scale = user_opts.scaleforcedwindow
- elseif (mp.property_get("fullscreen") == "yes") then
- scale = user_opts.scalefullscreen
- else
- scale = user_opts.scalewindowed
- end
-
-
- if user_opts.vidscale then
- osc_param.playresy = baseResY / scale
- else
- osc_param.playresy = display_h / scale
- end
- osc_param.playresx = osc_param.playresy * display_aspect
-
- -- 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
- 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))
-
- -- 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
-
- -- 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
-
- --
- -- Backround 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)
-
- --
- -- Title row
- --
-
- local titlerowY = posY - pos_offsetY - 10
-
- -- title
- local contentF = function (ass)
- local title = mp.property_get_string("media-title")
- if not (title == nil) then
-
- if #title > 80 then
- title = string.format("{\\fscx%f}", (80 / #title) * 100) .. title
- end
-
- ass:append(title)
- else
- ass:append("mpv")
- end
- end
-
- local eventresponder = {}
- eventresponder.mouse_btn0_up = function ()
-
- local title = mp.property_get("media-title")
- local pl_count = tonumber(mp.property_get("playlist-count"))
-
- if pl_count > 1 then
- local playlist_pos = countone(tonumber(mp.property_get("playlist-pos")))
- title = "[" .. playlist_pos .. "/" .. pl_count .. "] " .. title
- end
-
- show_message(title)
- end
- eventresponder.mouse_btn2_up = function () show_message(mp.property_get("filename")) end
-
- register_button(posX, titlerowY, 8, 496, 12, osc_styles.vidtitle, contentF, eventresponder, nil)
-
- -- If we have more than one playlist entry, render playlist navigation buttons
- local metainfo = {}
- metainfo.visible = (tonumber(mp.property_get("playlist-count")) > 1)
-
- -- playlist prev
- local eventresponder = {}
- eventresponder.mouse_btn0_up = function () mp.send_command("playlist_prev weak") end
- eventresponder["shift+mouse_btn0_up"] = function () show_message(mp.property_get("playlist"), 3) end
- register_button(posX - pos_offsetX, titlerowY, 7, 12, 12, osc_styles.vidtitle, "◀", eventresponder, metainfo)
-
- -- playlist next
- local eventresponder = {}
- eventresponder.mouse_btn0_up = function () mp.send_command("playlist_next weak") end
- eventresponder["shift+mouse_btn0_up"] = function () show_message(mp.property_get("playlist"), 3) end
- register_button(posX + pos_offsetX, titlerowY, 9, 12, 12, osc_styles.vidtitle, "▶", eventresponder, metainfo)
-
- --
- -- Big buttons
- --
-
- local bigbuttonrowY = posY - pos_offsetY + 35
- local bigbuttondistance = 60
-
- --play/pause
- local contentF = function (ass)
- if mp.property_get("pause") == "yes" then
- ass:append("\238\132\129")
- else
- ass:append("\238\128\130")
- end
- end
- local eventresponder = {}
- eventresponder.mouse_btn0_up = function () mp.send_command("no-osd cycle pause") end
- register_button(posX, bigbuttonrowY, 5, 40, 40, osc_styles.bigButtons, contentF, eventresponder, nil)
-
- --skipback
- local metainfo = {}
- metainfo.softrepeat = true
-
- local eventresponder = {}
- eventresponder.mouse_btn0_down = function () mp.send_command("no-osd seek -5 relative keyframes") end
- eventresponder["shift+mouse_btn0_down"] = function () mp.send_command("no-osd frame_back_step") end
- eventresponder.mouse_btn2_down = function () mp.send_command("no-osd seek -30 relative keyframes") end
- register_button(posX - bigbuttondistance, bigbuttonrowY, 5, 40, 40, osc_styles.bigButtons, "\238\128\132", eventresponder, metainfo)
-
- --skipfrwd
- local eventresponder = {}
- eventresponder.mouse_btn0_down = function () mp.send_command("no-osd seek 10 relative keyframes") end
- eventresponder["shift+mouse_btn0_down"] = function () mp.send_command("no-osd frame_step") end
- eventresponder.mouse_btn2_down = function () mp.send_command("no-osd seek 60 relative keyframes") end
- register_button(posX + bigbuttondistance, bigbuttonrowY, 5, 40, 40, osc_styles.bigButtons, "\238\128\133", eventresponder, metainfo)
-
- --chapters
- -- do we have any?
- local metainfo = {}
- metainfo.enabled = ((#mp.get_chapter_list()) > 0)
-
- --prev
- local eventresponder = {}
- eventresponder.mouse_btn0_up = function () mp.send_command("osd-msg add chapter -1") end
- eventresponder["shift+mouse_btn0_up"] = function () show_message(mp.property_get("chapter-list"), 3) end
- register_button(posX - (bigbuttondistance * 2), bigbuttonrowY, 5, 40, 40, osc_styles.bigButtons, "\238\132\132", eventresponder, metainfo)
-
- --next
- local eventresponder = {}
- eventresponder.mouse_btn0_up = function () mp.send_command("osd-msg add chapter 1") end
- eventresponder["shift+mouse_btn0_up"] = function () show_message(mp.property_get("chapter-list"), 3) end
- register_button(posX + (bigbuttondistance * 2), bigbuttonrowY, 5, 40, 40, osc_styles.bigButtons, "\238\132\133", eventresponder, metainfo)
-
-
- --
- -- Smaller buttons
- --
-
- if not (user_opts.iamaprogrammer) then
- update_tracklist()
- end
-
- --cycle audio tracks
-
- local metainfo = {}
- local eventresponder = {}
- local contentF
-
- if not (user_opts.iamaprogrammer) then
- metainfo.enabled = (#tracks_osc.audio > 0)
-
- contentF = function (ass)
- local aid = "–"
- if not (get_track("audio") == 0) then
- aid = get_track("audio")
- end
- ass:append("\238\132\134" .. osc_styles.smallButtonsLlabel .. " " .. aid .. "/" .. #tracks_osc.audio)
- end
-
- eventresponder.mouse_btn0_up = function () set_track("audio", 1) end
- eventresponder.mouse_btn2_up = function () set_track("audio", -1) end
- eventresponder["shift+mouse_btn0_down"] = function ()
- show_message(get_tracklist("audio"), 2)
- end
- else
- metainfo.enabled = true
- contentF = function (ass)
- local aid = mp.property_get("audio")
-
- ass:append("\238\132\134" .. osc_styles.smallButtonsLlabel .. " " .. aid)
- end
-
- eventresponder.mouse_btn0_up = function () mp.send_command("osd-msg add audio 1") end
- eventresponder.mouse_btn2_up = function () mp.send_command("osd-msg add audio -1") end
- end
-
- register_button(posX - pos_offsetX, bigbuttonrowY, 1, 70, 18, osc_styles.smallButtonsL, contentF, eventresponder, metainfo)
-
-
- --cycle sub tracks
-
- local metainfo = {}
- local eventresponder = {}
- local contentF
-
- if not (user_opts.iamaprogrammer) then
- metainfo.enabled = (#tracks_osc.sub > 0)
-
- contentF = function (ass)
- local sid = "–"
- if not (get_track("sub") == 0) then
- sid = get_track("sub")
- end
- ass:append("\238\132\135" .. osc_styles.smallButtonsLlabel .. " " .. sid .. "/" .. #tracks_osc.sub)
- end
-
- eventresponder.mouse_btn0_up = function () set_track("sub", 1) end
- eventresponder.mouse_btn2_up = function () set_track("sub", -1) end
- eventresponder["shift+mouse_btn0_down"] = function ()
- show_message(get_tracklist("sub"), 2)
- end
- else
- metainfo.enabled = true
- contentF = function (ass)
- local sid = mp.property_get("sub")
-
- ass:append("\238\132\135" .. osc_styles.smallButtonsLlabel .. " " .. sid)
- end
-
- eventresponder.mouse_btn0_up = function () mp.send_command("osd-msg add sub 1") end
- eventresponder.mouse_btn2_up = function () mp.send_command("osd-msg add sub -1") end
- end
- register_button(posX - pos_offsetX, bigbuttonrowY, 7, 70, 18, osc_styles.smallButtonsL, contentF, eventresponder, metainfo)
-
-
- --toggle FS
- local contentF = function (ass)
- if mp.property_get("fullscreen") == "yes" then
- ass:append("\238\132\137")
- else
- ass:append("\238\132\136")
- end
- end
- local eventresponder = {}
- eventresponder.mouse_btn0_up = function () mp.send_command("no-osd cycle fullscreen") end
- register_button(posX+pos_offsetX, bigbuttonrowY, 6, 25, 25, osc_styles.smallButtonsR, contentF, eventresponder, nil)
-
-
- --
- -- Seekbar
- --
-
- local markerF = function ()
- local duration = 0
- if not (mp.property_get("length") == nil) then
- duration = tonumber(mp.property_get("length"))
- end
-