dotfiles/.config/mpv/scripts/progress.lua

2548 lines
83 KiB
Lua
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

local msg = require('mp.msg')
local log = {
debug = function(format, ...)
return msg.debug(format:format(...))
end,
info = function(format, ...)
return msg.info(format:format(...))
end,
warn = function(format, ...)
return msg.warn(format:format(...))
end,
dump = function(item, ignore)
if "table" ~= type(item) then
msg.info(tostring(item))
return
end
local count = 1
local tablecount = 1
local result = {
"{ @" .. tostring(tablecount)
}
local seen = {
[item] = tablecount
}
local recurse
recurse = function(item, space)
for key, value in pairs(item) do
if not (key == ignore) then
if "table" == type(value) then
if not (seen[value]) then
tablecount = tablecount + 1
seen[value] = tablecount
count = count + 1
result[count] = space .. tostring(key) .. ": { @" .. tostring(tablecount)
recurse(value, space .. " ")
count = count + 1
result[count] = space .. "}"
else
count = count + 1
result[count] = space .. tostring(key) .. ": @" .. tostring(seen[value])
end
else
if "string" == type(value) then
value = ("%q"):format(value)
end
count = count + 1
result[count] = space .. tostring(key) .. ": " .. tostring(value)
end
end
end
end
recurse(item, " ")
count = count + 1
result[count] = "}"
return msg.info(table.concat(result, "\n"))
end
}
local options = require('mp.options')
local utils = require('mp.utils')
local script_name = 'torque-progressbar'
mp.get_osd_size = mp.get_osd_size or mp.get_screen_size
local settings = {
_defaults = { }
}
local settingsMeta = {
_reload = function(self)
for key, value in pairs(self._defaults) do
settings[key] = value
end
options.read_options(self, script_name .. '/main')
if self['bar-height-inactive'] <= 0 then
self['bar-hide-inactive'] = true
self['bar-height-inactive'] = 1
end
end,
_migrate = function(self)
local pathSep = package.config:sub(1, 1)
local onWindows = pathSep == '\\'
local mv
mv = function(oldFile, newFile)
local cmd = {
args = {
'mv',
oldConfig,
newConfig
}
}
if onWindows then
local oldfile = oldFile:gsub('/', pathSep)
newFile = newFile:gsub('/', pathSep)
cmd = {
args = {
'cmd',
'/Q',
'/C',
'move',
'/Y',
oldfile,
newFile
}
}
end
return utils.subprocess(cmd)
end
local mkdir
mkdir = function(directory)
local cmd = {
args = {
'mkdir',
'-p',
directory
}
}
if onWindows then
directory = directory:gsub('/', pathSep)
cmd = {
args = {
'cmd',
'/Q',
'/C',
'mkdir',
directory
}
}
end
return utils.subprocess(cmd)
end
local settingsDirectories = {
'script-opts',
'lua-settings'
}
local oldConfigFiles
do
local _accum_0 = { }
local _len_0 = 1
for _index_0 = 1, #settingsDirectories do
local dir = settingsDirectories[_index_0]
_accum_0[_len_0] = ('%s/%s.conf'):format(dir, script_name)
_len_0 = _len_0 + 1
end
oldConfigFiles = _accum_0
end
local newConfigFiles
do
local _accum_0 = { }
local _len_0 = 1
for _index_0 = 1, #settingsDirectories do
local dir = settingsDirectories[_index_0]
_accum_0[_len_0] = ('%s/%s/main.conf'):format(dir, script_name)
_len_0 = _len_0 + 1
end
newConfigFiles = _accum_0
end
local oldConfig = nil
local oldConfigIndex = 1
local newConfigFile = nil
local newConfig = nil
for idx, file in ipairs(oldConfigFiles) do
log.debug(('checking for old config "%s"'):format(file))
oldConfig = mp.find_config_file(file)
if oldConfig then
log.debug(('found "%s"'):format(oldConfig))
oldConfigIndex = idx
break
end
end
if not (oldConfig) then
log.debug('No old config file found. Migration finished.')
return
end
for _index_0 = 1, #newConfigFiles do
local file = newConfigFiles[_index_0]
log.debug(('checking for new config "%s"'):format(file))
newConfig = mp.find_config_file(file)
if newConfig then
log.debug(('found "%s"'):format(newConfig))
newConfigFile = file
break
end
end
if oldConfig and not newConfig then
log.debug(('Found "%s". Processing migration.'):format(oldConfig))
newConfigFile = newConfigFiles[oldConfigIndex]
local baseConfigFolder, _ = utils.split_path(oldConfig)
local configDir = utils.join_path(baseConfigFolder, script_name)
newConfig = utils.join_path(configDir, 'main.conf')
log.info(('Old configuration detected. Attempting to migrate "%s" -> "%s"'):format(oldConfig, newConfig))
local dirExists = mp.find_config_file(configDir)
if dirExists and not utils.readdir(configDir) then
log.warn(('Configuration migration failed. "%s" exists and does not appear to be a folder'):format(configDir))
return
else
if not dirExists then
log.debug(('Attempting to create directory "%s"'):format(configDir))
local res = mkdir(configDir)
if res.error or res.status ~= 0 then
log.warn(('Making directory "%s" failed.'):format(configDir))
return
end
log.debug('successfully created directory.')
else
log.debug(('Directory "%s" already exists. Continuing.'):format(configDir))
end
end
log.debug(('Attempting to move "%s" -> "%s"'):format(oldConfig, newConfig))
local res = mv(oldConfig, newConfig)
if res.error or res.status ~= 0 then
log.warn(('Moving file "%s" -> "%s" failed.'):format(oldConfig, newConfig))
return
end
if mp.find_config_file(newConfigFile) then
return log.info('Configuration successfully migrated.')
else
return log.warn(('Cannot find "%s". Migration mysteriously failed?'):format(newConfigFile))
end
end
end,
__newindex = function(self, key, value)
self._defaults[key] = value
return rawset(self, key, value)
end
}
settingsMeta.__index = settingsMeta
setmetatable(settings, settingsMeta)
settings:_migrate()
local helpText = { }
settings['hover-zone-height'] = 40
helpText['hover-zone-height'] = [[Sets the height of the rectangular area at the bottom of the screen that expands
the progress bar and shows playback time information when the mouse is hovered
over it.
]]
settings['top-hover-zone-height'] = 40
helpText['top-hover-zone-height'] = [[Sets the height of the rectangular area at the top of the screen that shows the
file name and system time when the mouse is hovered over it.
]]
settings['display-scale-factor'] = 1
helpText['display-scale-factor'] = [[Acts as a multiplier to increase the size of every UI element. Useful for high-
DPI displays that cause the UI to be rendered too small (happens at least on
macOS).
]]
settings['default-style'] = [[\fnSource Sans Pro\b1\bord2\shad0\fs30\c&HFC799E&\3c&H2D2D2D&]]
helpText['default-style'] = [[Default style that is applied to all UI elements. A string of ASS override tags.
Individual elements have their own style settings which override the tags here.
Changing the font will likely require changing the hover-time margin settings
and the offscreen-pos settings.
Here are some useful ASS override tags (omit square brackets):
\fn[Font Name]: sets the font to the named font.
\fs[number]: sets the font size to the given number.
\b[1/0]: sets the text bold or not (\b1 is bold, \b0 is regular weight).
\i[1/0]: sets the text italic or not (same semantics as bold).
\bord[number]: sets the outline width to the given number (in pixels).
\shad[number]: sets the shadow size to the given number (pixels).
\c&H[BBGGRR]&: sets the fill color for the text to the given color (hex pairs in
the order, blue, green, red).
\3c&H[BBGGRR]&: sets the outline color of the text to the given color.
\4c&H[BBGGRR]&: sets the shadow color of the text to the given color.
\alpha&H[AA]&: sets the line's transparency as a hex pair. 00 is fully opaque
and FF is fully transparent. Some UI elements are composed of
multiple layered lines, so adding transparency may not look good.
For further granularity, \1a&H[AA]& controls the fill opacity,
\3a&H[AA]& controls the outline opacity, and \4a&H[AA]& controls
the shadow opacity.
]]
settings['enable-bar'] = true
helpText['enable-bar'] = [[Controls whether or not the progress bar is drawn at all. If this is disabled,
it also (naturally) disables the click-to-seek functionality.
]]
settings['bar-hide-inactive'] = false
helpText['bar-hide-inactive'] = [[Causes the bar to not be drawn unless the mouse is hovering over it or a
request-display call is active. This is somewhat redundant with setting bar-
height-inactive=0, except that it can allow for very rudimentary context-
sensitive behavior because it can be toggled at runtime. For example, by using
the binding `f cycle pause; script-binding progressbar/toggle-inactive-bar`, it
is possible to have the bar be persistently present only in windowed or
fullscreen contexts, depending on the default setting.
]]
settings['bar-height-inactive'] = 3
helpText['bar-height-inactive'] = [[Sets the height of the bar display when the mouse is not in the active zone and
there is no request-display active. A value of 0 or less will cause bar-hide-
inactive to be set to true and the bar height to be set to 1. This should result
in the desired behavior while avoiding annoying debug logging in mpv (libass
does not like zero-height objects).
]]
settings['bar-height-active'] = 8
helpText['bar-height-active'] = [[Sets the height of the bar display when the mouse is in the active zone or
request-display is active. There is no logic attached to this, so 0 or negative
values may have unexpected results.
]]
settings['progress-bar-width'] = 0
helpText['progress-bar-width'] = [[If greater than zero, changes the progress bar style to be a small segment
rather than a continuous bar and sets its width.
]]
settings['seek-precision'] = 'exact'
helpText['seek-precision'] = [[Affects precision of seeks due to clicks on the progress bar. Should be 'exact' or
'keyframes'. Exact is slightly slower, but won't jump around between two
different times when clicking in the same place.
Actually, this gets passed directly into the `seek` command, so the value can be
any of the arguments supported by mpv, though the ones above are the only ones
that really make sense.
]]
settings['bar-background-adaptive'] = true
helpText['bar-background-adaptive'] = [[Causes the progress bar background layer to automatically size itself to the
tallest of the cache or progress bars. Useful for improving contrast but can
make the bar take up more screen space. Has no effect if the cache bar height is
less than the bar height.
]]
settings['bar-cache-position'] = 'overlay'
helpText['bar-cache-position'] = [[Placement of the cache bar. Valid values are 'overlay' and 'underlay'.
'overlay' causes the cache bar to be drawn on top of the foreground layer of the
bar, allowing the display of seek ranges that have already been encountered.
'underlay' draws the cache bar between the foreground and background layers. Any
demuxer cache ranges that are prior to the current playback point will not be
shown. This matches the previous behavior.
]]
settings['bar-cache-height-inactive'] = 1.5
helpText['bar-cache-height-inactive'] = [[Sets the height of the cache bar display when the mouse is not in the active
zone and there is no request-display active. Useful in combination with bar-
cache-position to control whether or not the cache bar is occluded by (or
occludes) the progress bar.
]]
settings['bar-cache-height-active'] = 4
helpText['bar-cache-height-active'] = [[Sets the height of the cache bar display when the mouse is in the active zone or
request-display is active. Useful in combination with bar-cache- position to
control whether or not the cache bar is occluded by (or occludes) the progress
bar.
]]
settings['bar-default-style'] = [[\bord0\shad0]]
helpText['bar-default-style'] = [[A string of ASS override tags that get applied to all three layers of the bar:
progress, cache, and background. You probably don't want to remove \bord0 unless
your default-style includes it.
]]
settings['bar-foreground-style'] = ''
helpText['bar-foreground-style'] = [[A string of ASS override tags that get applied only to the progress layer of the
bar.
]]
settings['bar-cache-style'] = [[\c&H515151&]]
helpText['bar-cache-style'] = [[A string of ASS override tags that get applied only to the cache layer of the
bar, particularly the part of the cache bar that is behind the current playback
position. The default sets only the color.
]]
settings['bar-cache-background-style'] = [[]]
helpText['bar-cache-background-style'] = [[A string of ASS override tags that get applied only to the cache layer of the
bar, particularly the part of the cache bar that is after the current playback
position. The tags specified here are applied after bar-cache-style and override
them. Leaving this blank will leave the style the same as specified by bar-
cache-style. The split does not account for a nonzero progress-bar-width and may
look odd when used in tandem with that setting.
]]
settings['bar-background-style'] = [[\c&H2D2D2D&]]
helpText['bar-background-style'] = [[A string of ASS override tags that get applied only to the background layer of
the bar. The default sets only the color.
]]
settings['enable-elapsed-time'] = true
helpText['enable-elapsed-time'] = [[Sets whether or not the elapsed time is displayed at all.
]]
settings['elapsed-style'] = ''
helpText['elapsed-style'] = [[A string of ASS override tags that get applied only to the elapsed time display.
]]
settings['elapsed-left-margin'] = 4
helpText['elapsed-left-margin'] = [[Controls how far from the left edge of the window the elapsed time display is
positioned.
]]
settings['elapsed-bottom-margin'] = 0
helpText['elapsed-bottom-margin'] = [[Controls how far above the expanded progress bar the elapsed time display is
positioned.
]]
settings['enable-remaining-time'] = true
helpText['enable-remaining-time'] = [[Sets whether or not the remaining time is displayed at all.
]]
settings['remaining-style'] = ''
helpText['remaining-style'] = [[A string of ASS override tags that get applied only to the remaining time
display.
]]
settings['remaining-right-margin'] = 4
helpText['remaining-right-margin'] = [[Controls how far from the right edge of the window the remaining time display is
positioned.
]]
settings['remaining-bottom-margin'] = 0
helpText['remaining-bottom-margin'] = [[Controls how far above the expanded progress bar the remaining time display is
positioned.
]]
settings['enable-hover-time'] = true
helpText['enable-hover-time'] = [[Sets whether or not the calculated time corresponding to the mouse position
is displayed when the mouse hovers over the progress bar.
]]
settings['hover-time-style'] = [[\fs26]]
helpText['hover-time-style'] = [[A string of ASS override tags that get applied only to the hover time display.
Unfortunately, due to the way the hover time display is animated, alpha values
set here will be overridden. This is subject to change in future versions.
]]
settings['hover-time-left-margin'] = 120
helpText['hover-time-left-margin'] = [[Controls how close to the left edge of the window the hover time display can
get. If this value is too small, it will end up overlapping the elapsed time
display.
]]
settings['hover-time-right-margin'] = 130
helpText['hover-time-right-margin'] = [[Controls how close to the right edge of the window the hover time display can
get. If this value is too small, it will end up overlapping the remaining time
display.
]]
settings['hover-time-bottom-margin'] = 0
helpText['hover-time-bottom-margin'] = [[Controls how far above the expanded progress bar the remaining time display is
positioned.
]]
settings['enable-title'] = true
helpText['enable-title'] = [[Sets whether or not the video title is displayed at all.
]]
settings['title-style'] = ''
helpText['title-style'] = [[A string of ASS override tags that get applied only to the video title display.
]]
settings['title-left-margin'] = 4
helpText['title-left-margin'] = [[Controls how far from the left edge of the window the video title display is
positioned.
]]
settings['title-top-margin'] = 0
helpText['title-top-margin'] = [[Controls how far from the top edge of the window the video title display is
positioned.
]]
settings['title-print-to-cli'] = true
helpText['title-print-to-cli'] = [[Controls whether or not the script logs the video title and playlist position
to the console every time a new video starts.
]]
settings['enable-system-time'] = true
helpText['enable-system-time'] = [[Sets whether or not the system time is displayed at all.
]]
settings['system-time-style'] = ''
helpText['system-time-style'] = [[A string of ASS override tags that get applied only to the system time display.
]]
settings['system-time-format'] = '%H:%M'
helpText['system-time-format'] = [[Sets the format used for the system time display. This must be a strftime-
compatible format string.
]]
settings['system-time-right-margin'] = 4
helpText['system-time-right-margin'] = [[Controls how far from the right edge of the window the system time display is
positioned.
]]
settings['system-time-top-margin'] = 0
helpText['system-time-top-margin'] = [[Controls how far from the top edge of the window the system time display is
positioned.
]]
settings['pause-indicator'] = true
helpText['pause-indicator'] = [[Sets whether or not the pause indicator is displayed. The pause indicator is a
momentary icon that flashes in the middle of the screen, similar to youtube.
]]
settings['pause-indicator-foreground-style'] = [[\c&HFC799E&]]
helpText['pause-indicator-foreground-style'] = [[A string of ASS override tags that get applied only to the foreground of the
pause indicator.
]]
settings['pause-indicator-background-style'] = [[\c&H2D2D2D&]]
helpText['pause-indicator-background-style'] = [[A string of ASS override tags that get applied only to the background of the
pause indicator.
]]
settings['enable-chapter-markers'] = true
helpText['enable-chapter-markers'] = [[Sets whether or not the progress bar is decorated with chapter markers. Due to
the way the chapter markers are currently implemented, videos with a large
number of chapters may slow down the script somewhat, but I have yet to run
into this being a problem.
]]
settings['chapter-marker-width'] = 2
helpText['chapter-marker-width'] = [[Controls the width of each chapter marker when the progress bar is inactive.
]]
settings['chapter-marker-width-active'] = 4
helpText['chapter-marker-width-active'] = [[Controls the width of each chapter marker when the progress bar is active.
]]
settings['chapter-marker-active-height-fraction'] = 1
helpText['chapter-marker-active-height-fraction'] = [[Modifies the height of the chapter markers when the progress bar is active. Acts
as a multiplier on the height of the active progress bar. A value greater than 1
will cause the markers to be taller than the expanded progress bar, whereas a
value less than 1 will cause them to be shorter.
]]
settings['chapter-marker-before-style'] = [[\c&HFC799E&]]
helpText['chapter-marker-before-style'] = [[A string of ASS override tags that get applied only to chapter markers that have
not yet been passed.
]]
settings['chapter-marker-after-style'] = [[\c&H2D2D2D&]]
helpText['chapter-marker-after-style'] = [[A string of ASS override tags that get applied only to chapter markers that have
already been passed.
]]
settings['request-display-duration'] = 1
helpText['request-display-duration'] = [[Sets the amount of time in seconds that the UI stays on the screen after it
receives a request-display signal. A value of 0 will keep the display on screen
only as long as the key bound to it is held down.
]]
settings['redraw-period'] = 0.03
helpText['redraw-period'] = [[Controls how often the display is redrawn, in seconds. This does not seem to
significantly affect the smoothness of animations, and it is subject to the
accuracy limits imposed by the scheduler mpv uses. Probably not worth changing
unless you have major performance problems.
]]
settings['animation-duration'] = 0.25
helpText['animation-duration'] = [[Controls how long the UI animations take. A value of 0 disables all animations
(which breaks the pause indicator).
]]
settings['elapsed-offscreen-pos'] = -100
helpText['elapsed-offscreen-pos'] = [[Controls how far off the left side of the window the elapsed time display tries
to move when it is inactive. If you use a non-default font, this value may need
to be tweaked. If this value is not far enough off-screen, the elapsed display
will disappear without animating all the way off-screen. Positive values will
cause the display to animate the wrong direction.
]]
settings['remaining-offscreen-pos'] = -100
helpText['remaining-offscreen-pos'] = [[Controls how far off the left side of the window the remaining time display
tries to move when it is inactive. If you use a non-default font, this value may
need to be tweaked. If this value is not far enough off-screen, the elapsed
display will disappear without animating all the way off-screen. Positive values
will cause the display to animate the wrong direction.
]]
settings['hover-time-offscreen-pos'] = -50
helpText['hover-time-offscreen-pos'] = [[Controls how far off the bottom of the window the mouse hover time display tries
to move when it is inactive. If you use a non-default font, this value may need
to be tweaked. If this value is not far enough off-screen, the elapsed
display will disappear without animating all the way off-screen. Positive values
will cause the display to animate the wrong direction.
]]
settings['system-time-offscreen-pos'] = -100
helpText['system-time-offscreen-pos'] = [[Controls how far off the left side of the window the system time display tries
to move when it is inactive. If you use a non-default font, this value may need
to be tweaked. If this value is not far enough off-screen, the elapsed display
will disappear without animating all the way off-screen. Positive values will
cause the display to animate the wrong direction.
]]
settings['title-offscreen-pos'] = -40
helpText['title-offscreen-pos'] = [[Controls how far off the left side of the window the video title display tries
to move when it is inactive. If you use a non-default font, this value may need
to be tweaked. If this value is not far enough off-screen, the elapsed display
will disappear without animating all the way off-screen. Positive values will
cause the display to animate the wrong direction.
]]
settings:_reload()
local Stack
do
local _class_0
local removeElementMetadata, reindex
local _base_0 = {
insert = function(self, element, index)
if index then
table.insert(self, index, element)
element[self] = index
else
table.insert(self, element)
element[self] = #self
end
if self.containmentKey then
element[self.containmentKey] = true
end
end,
remove = function(self, element)
if element[self] == nil then
error("Trying to remove an element that doesn't exist in this stack.")
end
table.remove(self, element[self])
reindex(self, element[self])
return removeElementMetadata(self, element)
end,
clear = function(self)
local element = table.remove(self)
while element do
removeElementMetadata(self, element)
element = table.remove(self)
end
end,
removeSortedList = function(self, elementList)
if #elementList < 1 then
return
end
for i = 1, #elementList - 1 do
local element = table.remove(elementList)
table.remove(self, element[self])
removeElementMetadata(self, element)
end
local lastElement = table.remove(elementList)
table.remove(self, lastElement[self])
reindex(self, lastElement[self])
return removeElementMetadata(self, lastElement)
end,
removeList = function(self, elementList)
table.sort(elementList, function(a, b)
return a[self] < b[self]
end)
return self:removeSortedList(elementList)
end
}
_base_0.__index = _base_0
_class_0 = setmetatable({
__init = function(self, containmentKey)
self.containmentKey = containmentKey
end,
__base = _base_0,
__name = "Stack"
}, {
__index = _base_0,
__call = function(cls, ...)
local _self_0 = setmetatable({}, _base_0)
cls.__init(_self_0, ...)
return _self_0
end
})
_base_0.__class = _class_0
local self = _class_0
removeElementMetadata = function(self, element)
element[self] = nil
if self.containmentKey then
element[self.containmentKey] = false
end
end
reindex = function(self, start)
if start == nil then
start = 1
end
for i = start, #self do
(self[i])[self] = i
end
end
Stack = _class_0
end
local Window
do
local _class_0
local osdScale
local _base_0 = { }
_base_0.__index = _base_0
_class_0 = setmetatable({
__init = function() end,
__base = _base_0,
__name = "Window"
}, {
__index = _base_0,
__call = function(cls, ...)
local _self_0 = setmetatable({}, _base_0)
cls.__init(_self_0, ...)
return _self_0
end
})
_base_0.__class = _class_0
local self = _class_0
osdScale = settings['display-scale-factor']
self.__class.w, self.__class.h = 0, 0
self.update = function(self)
local w, h = mp.get_osd_size()
w, h = math.floor(w / osdScale), math.floor(h / osdScale)
if w ~= self.w or h ~= self.h then
self.w, self.h = w, h
return true
else
return false
end
end
Window = _class_0
end
local Mouse
do
local _class_0
local osdScale, scaledPosition
local _base_0 = { }
_base_0.__index = _base_0
_class_0 = setmetatable({
__init = function() end,
__base = _base_0,
__name = "Mouse"
}, {
__index = _base_0,
__call = function(cls, ...)
local _self_0 = setmetatable({}, _base_0)
cls.__init(_self_0, ...)
return _self_0
end
})
_base_0.__class = _class_0
local self = _class_0
osdScale = settings['display-scale-factor']
self.__class.x, self.__class.y = -1, -1
self.__class.inWindow, self.__class.dead = false, true
self.__class.clickX, self.__class.clickY = -1, -1
self.__class.clickPending = false
scaledPosition = function()
local x, y = mp.get_mouse_pos()
return math.floor(x / osdScale), math.floor(y / osdScale)
end
self.update = function(self)
local oldX, oldY = self.x, self.y
self.x, self.y = scaledPosition()
if self.dead and (oldX ~= self.x or oldY ~= self.y) then
self.dead = false
end
if not self.dead and self.clickPending then
self.clickPending = false
return true
end
return false
end
self.cacheClick = function(self)
if not self.dead then
self.clickX, self.clickY = scaledPosition()
self.clickPending = true
else
self.dead = false
end
end
Mouse = _class_0
end
mp.add_key_binding("mouse_btn0", "left-click", function()
return Mouse:cacheClick()
end)
mp.observe_property('fullscreen', 'bool', function()
Mouse:update()
Mouse.dead = true
end)
mp.add_forced_key_binding("mouse_leave", "mouse-leave", function()
Mouse.inWindow = false
end)
mp.add_forced_key_binding("mouse_enter", "mouse-enter", function()
Mouse.inWindow = true
end)
local Rect
do
local _class_0
local _base_0 = {
cacheMaxBounds = function(self)
self.xMax = self.x + self.w
self.yMax = self.y + self.h
end,
setPosition = function(self, x, y)
self.x = x or self.x
self.y = y or self.y
return self:cacheMaxBounds()
end,
setSize = function(self, w, h)
self.w = w or self.w
self.h = h or self.h
return self:cacheMaxBounds()
end,
reset = function(self, x, y, w, h)
self.x = x or self.x
self.y = y or self.y
self.w = w or self.w
self.h = h or self.h
return self:cacheMaxBounds()
end,
move = function(self, x, y)
self.x = self.x + (x or self.x)
self.y = self.y + (y or self.y)
return self:cacheMaxBounds()
end,
stretch = function(self, w, h)
self.w = self.w + (w or self.w)
self.h = self.h + (h or self.h)
return self:cacheMaxBounds()
end,
containsPoint = function(self, x, y)
return (x >= self.x) and (x < self.xMax) and (y >= self.y) and (y < self.yMax)
end
}
_base_0.__index = _base_0
_class_0 = setmetatable({
__init = function(self, x, y, w, h)
if x == nil then
x = -1
end
if y == nil then
y = -1
end
if w == nil then
w = -1
end
if h == nil then
h = -1
end
self.x, self.y, self.w, self.h = x, y, w, h
return self:cacheMaxBounds()
end,
__base = _base_0,
__name = "Rect"
}, {
__index = _base_0,
__call = function(cls, ...)
local _self_0 = setmetatable({}, _base_0)
cls.__init(_self_0, ...)
return _self_0
end
})
_base_0.__class = _class_0
Rect = _class_0
end
local ActivityZone
do
local _class_0
local _parent_0 = Rect
local _base_0 = {
reconfigure = function(self)
self.active = false
end,
addUIElement = function(self, element)
self.elements:insert(element)
return element:activate(self.active)
end,
removeUIElement = function(self, element)
return self.elements:remove(element)
end,
clickHandler = function(self)
if not (self:containsPoint(Mouse.clickX, Mouse.clickY)) then
return
end
for _, element in ipairs(self.elements) do
if element.clickHandler and not element:clickHandler() then
break
end
end
end,
activityCheck = function(self, displayRequested)
if displayRequested == true then
return true
end
if not (Mouse.inWindow) then
return false
end
if Mouse.dead then
return false
end
return self:containsPoint(Mouse.x, Mouse.y)
end,
update = function(self, displayRequested, clickPending)
local nowActive = self:activityCheck(displayRequested)
if self.active ~= nowActive then
self.active = nowActive
for id, element in ipairs(self.elements) do
element:activate(nowActive)
end
end
if clickPending then
self:clickHandler()
end
return nowActive
end
}
_base_0.__index = _base_0
setmetatable(_base_0, _parent_0.__base)
_class_0 = setmetatable({
__init = function(self, resize, activityCheck)
self.resize, self.activityCheck = resize, activityCheck
_class_0.__parent.__init(self)
self.active = false
self.elements = Stack()
end,
__base = _base_0,
__name = "ActivityZone",
__parent = _parent_0
}, {
__index = function(cls, name)
local val = rawget(_base_0, name)
if val == nil then
local parent = rawget(cls, "__parent")
if parent then
return parent[name]
end
else
return val
end
end,
__call = function(cls, ...)
local _self_0 = setmetatable({}, _base_0)
cls.__init(_self_0, ...)
return _self_0
end
})
_base_0.__class = _class_0
if _parent_0.__inherited then
_parent_0.__inherited(_parent_0, _class_0)
end
ActivityZone = _class_0
end
local AnimationQueue
do
local _class_0
local animationList, deletionQueue
local _base_0 = { }
_base_0.__index = _base_0
_class_0 = setmetatable({
__init = function() end,
__base = _base_0,
__name = "AnimationQueue"
}, {
__index = _base_0,
__call = function(cls, ...)
local _self_0 = setmetatable({}, _base_0)
cls.__init(_self_0, ...)
return _self_0
end
})
_base_0.__class = _class_0
local self = _class_0
animationList = Stack('active')
deletionQueue = { }
self.addAnimation = function(animation)
if not (animation.active) then
return animationList:insert(animation)
end
end
self.removeAnimation = function(animation)
if animation.active then
return animationList:remove(animation)
end
end
self.destroyAnimationStack = function()
return animationList:clear()
end
self.animate = function()
if #animationList == 0 then
return
end
local currentTime = mp.get_time()
for _, animation in ipairs(animationList) do
if animation:update(currentTime) then
table.insert(deletionQueue, animation)
end
end
if #deletionQueue > 0 then
return animationList:removeSortedList(deletionQueue)
end
end
self.active = function()
return #animationList > 0
end
AnimationQueue = _class_0
end
local EventLoop
do
local _class_0
local _base_0 = {
reconfigure = function(self)
settings:_reload()
AnimationQueue.destroyAnimationStack()
for _, zone in ipairs(self.activityZones) do
zone:reconfigure()
end
for _, element in ipairs(self.uiElements) do
element:reconfigure()
end
end,
addZone = function(self, zone)
if zone == nil then
return
end
return self.activityZones:insert(zone)
end,
removeZone = function(self, zone)
if zone == nil then
return
end
return self.activityZones:remove(zone)
end,
generateUIFromZones = function(self)
local seenUIElements = { }
self.script = { }
self.uiElements:clear()
AnimationQueue.destroyAnimationStack()
for _, zone in ipairs(self.activityZones) do
for _, uiElement in ipairs(zone.elements) do
if not (seenUIElements[uiElement]) then
self:addUIElement(uiElement)
seenUIElements[uiElement] = true
end
end
end
return self.updateTimer:resume()
end,
addUIElement = function(self, uiElement)
if uiElement == nil then
error('nil UIElement added.')
end
self.uiElements:insert(uiElement)
return table.insert(self.script, '')
end,
removeUIElement = function(self, uiElement)
if uiElement == nil then
error('nil UIElement removed.')
end
table.remove(self.script, uiElement[self.uiElements])
self.uiElements:remove(uiElement)
self.needsRedraw = true
end,
resize = function(self)
for _, zone in ipairs(self.activityZones) do
zone:resize()
end
for _, uiElement in ipairs(self.uiElements) do
uiElement:resize()
end
end,
redraw = function(self, forceRedraw)
local clickPending = Mouse:update()
if Window:update() then
self:resize()
end
for index, zone in ipairs(self.activityZones) do
zone:update(self.displayRequested, clickPending)
end
AnimationQueue.animate()
for index, uiElement in ipairs(self.uiElements) do
if uiElement:redraw() then
self.script[index] = uiElement:stringify()
self.needsRedraw = true
end
end
if self.needsRedraw then
mp.set_osd_ass(Window.w, Window.h, table.concat(self.script, '\n'))
self.needsRedraw = false
end
end
}
_base_0.__index = _base_0
_class_0 = setmetatable({
__init = function(self)
self.script = { }
self.uiElements = Stack()
self.activityZones = Stack()
self.displayRequested = false
self.needsRedraw = false
self.updateTimer = mp.add_periodic_timer(settings['redraw-period'], (function()
local _base_1 = self
local _fn_0 = _base_1.redraw
return function(...)
return _fn_0(_base_1, ...)
end
end)())
self.updateTimer:stop()
mp.register_event('shutdown', function()
return self.updateTimer:kill()
end)
local displayRequestTimer
local displayDuration = settings['request-display-duration']
mp.add_key_binding("tab", "request-display", function(event)
if event.event == "repeat" then
return
end
if event.event == "down" or event.event == "press" then
if displayRequestTimer then
displayRequestTimer:kill()
end
self.displayRequested = true
end
if event.event == "up" or event.event == "press" then
if displayDuration == 0 then
self.displayRequested = false
else
displayRequestTimer = mp.add_timeout(displayDuration, function()
self.displayRequested = false
end)
end
end
end, {
complex = true
})
return mp.add_key_binding('ctrl+r', 'reconfigure', (function()
local _base_1 = self
local _fn_0 = _base_1.reconfigure
return function(...)
return _fn_0(_base_1, ...)
end
end)(), {
repeatable = false
})
end,
__base = _base_0,
__name = "EventLoop"
}, {
__index = _base_0,
__call = function(cls, ...)
local _self_0 = setmetatable({}, _base_0)
cls.__init(_self_0, ...)
return _self_0
end
})
_base_0.__class = _class_0
EventLoop = _class_0
end
local Animation
do
local _class_0
local _base_0 = {
update = function(self, now)
if self.isReversed then
self.linearProgress = math.max(0, math.min(1, self.linearProgress + (self.lastUpdate - now) * self.durationR))
if self.linearProgress == 0 then
self.isFinished = true
end
else
self.linearProgress = math.max(0, math.min(1, self.linearProgress + (now - self.lastUpdate) * self.durationR))
if self.linearProgress == 1 then
self.isFinished = true
end
end
self.lastUpdate = now
local progress = math.pow(self.linearProgress, self.accel)
self.value = (1 - progress) * self.initialValue + progress * self.endValue
self.updateCb(self.value)
if self.isFinished and self.finishedCb then
self:finishedCb()
end
return self.isFinished
end,
interrupt = function(self, reverse)
self.finishedCb = nil
self.lastUpdate = mp.get_time()
self.isReversed = reverse
if not (self.active) then
self.isFinished = false
return AnimationQueue.addAnimation(self)
end
end
}
_base_0.__index = _base_0
_class_0 = setmetatable({
__init = function(self, initialValue, endValue, duration, updateCb, finishedCb, accel)
if accel == nil then
accel = 1
end
self.initialValue, self.endValue, self.duration, self.updateCb, self.finishedCb, self.accel = initialValue, endValue, duration, updateCb, finishedCb, accel
self.value = self.initialValue
self.linearProgress = 0
self.lastUpdate = mp.get_time()
self.durationR = 1 / self.duration
self.isFinished = (self.duration <= 0)
self.active = false
self.isReversed = false
end,
__base = _base_0,
__name = "Animation"
}, {
__index = _base_0,
__call = function(cls, ...)
local _self_0 = setmetatable({}, _base_0)
cls.__init(_self_0, ...)
return _self_0
end
})
_base_0.__class = _class_0
Animation = _class_0
end
local UIElement
do
local _class_0
local _base_0 = {
stringify = function(self)
self.needsUpdate = false
if not self.active then
return ''
else
return table.concat(self.line)
end
end,
activate = function(self, activate)
if activate == true then
self.animation:interrupt(false)
self.active = true
else
self.animation:interrupt(true)
self.animation.finishedCb = function()
self.active = false
end
end
end,
reconfigure = function(self)
self.needsUpdate = true
self.animationDuration = settings['animation-duration']
end,
resize = function(self)
return error('UIElement updateSize called')
end,
redraw = function(self)
return self.needsUpdate
end
}
_base_0.__index = _base_0
_class_0 = setmetatable({
__init = function(self)
self.needsUpdate = false
self.active = false
self.animationDuration = settings['animation-duration']
end,
__base = _base_0,
__name = "UIElement"
}, {
__index = _base_0,
__call = function(cls, ...)
local _self_0 = setmetatable({}, _base_0)
cls.__init(_self_0, ...)
return _self_0
end
})
_base_0.__class = _class_0
UIElement = _class_0
end
local BarAccent
do
local _class_0
local barSize
local _parent_0 = UIElement
local _base_0 = {
reconfigure = function(self)
_class_0.__parent.__base.reconfigure(self)
barSize = settings['bar-height-active']
end,
resize = function(self)
self.yPos = Window.h - barSize
self.needsUpdate = true
end,
redraw = function(self)
if self.barSize ~= barSize then
self.barSize = barSize
return self:resize()
end
end
}
_base_0.__index = _base_0
setmetatable(_base_0, _parent_0.__base)
_class_0 = setmetatable({
__init = function(self)
_class_0.__parent.__init(self)
self.yPos = Window.h - barSize
end,
__base = _base_0,
__name = "BarAccent",
__parent = _parent_0
}, {
__index = function(cls, name)
local val = rawget(_base_0, name)
if val == nil then
local parent = rawget(cls, "__parent")
if parent then
return parent[name]
end
else
return val
end
end,
__call = function(cls, ...)
local _self_0 = setmetatable({}, _base_0)
cls.__init(_self_0, ...)
return _self_0
end
})
_base_0.__class = _class_0
local self = _class_0
barSize = settings['bar-height-active']
self.changeBarSize = function(size)
barSize = size
end
if _parent_0.__inherited then
_parent_0.__inherited(_parent_0, _class_0)
end
BarAccent = _class_0
end
local BarBase
do
local _class_0
local hideInactive, lineBaseTemplate
local _parent_0 = UIElement
local _base_0 = {
_updateBarVisibility = function(self)
if hideInactive then
self.animationMinHeight = 0
else
self.animationMinHeight = self.minHeight
end
end,
reconfigure = function(self, prefix)
if prefix == nil then
prefix = 'bar-'
end
_class_0.__parent.__base.reconfigure(self)
self.minHeight = settings[prefix .. 'height-inactive'] * 100
self.maxHeight = settings[prefix .. 'height-active'] * 100
hideInactive = settings['bar-hide-inactive']
self:_updateBarVisibility()
self.line[4] = self.minHeight
self.line[8] = lineBaseTemplate:format(settings['default-style'], settings['bar-default-style'], '%s')
self.animation = Animation(0, 1, self.animationDuration, (function()
local _base_1 = self
local _fn_0 = _base_1.animate
return function(...)
return _fn_0(_base_1, ...)
end
end)())
end,
stringify = function(self)
self.needsUpdate = false
if hideInactive and not self.active then
return ""
else
return table.concat(self.line)
end
end,
resize = function(self)
self.line[2] = ([[%d,%d]]):format(0, Window.h)
self.line[9] = ([[m 0 0 l %d 0 %d 1 0 1]]):format(Window.w, Window.w)
self.needsUpdate = true
end,
animate = function(self, value)
self.line[4] = ([[%g]]):format((self.maxHeight - self.animationMinHeight) * value + self.animationMinHeight)
self.needsUpdate = true
end,
redraw = function(self)
if self.hideInactive ~= hideInactive then
self.hideInactive = hideInactive
if not (self.active) then
self:animate(0)
end
end
return self.needsUpdate
end
}
_base_0.__index = _base_0
setmetatable(_base_0, _parent_0.__base)
_class_0 = setmetatable({
__init = function(self)
self.minHeight = settings['bar-height-inactive'] * 100
self.animationMinHeight = minHeight
self.maxHeight = settings['bar-height-active'] * 100
self.line = {
[[{\pos(]],
0,
[[)\fscy]],
minHeight,
[[\fscx]],
0.001,
[[]],
lineBaseTemplate,
0
}
_class_0.__parent.__init(self)
table.insert(self.__class.instantiatedBars, self)
return self:reconfigure()
end,
__base = _base_0,
__name = "BarBase",
__parent = _parent_0
}, {
__index = function(cls, name)
local val = rawget(_base_0, name)
if val == nil then
local parent = rawget(cls, "__parent")
if parent then
return parent[name]
end
else
return val
end
end,
__call = function(cls, ...)
local _self_0 = setmetatable({}, _base_0)
cls.__init(_self_0, ...)
return _self_0
end
})
_base_0.__class = _class_0
local self = _class_0
hideInactive = settings['bar-hide-inactive']
self.instantiatedBars = { }
self.toggleInactiveVisibility = function(self)
hideInactive = not hideInactive
local _list_0 = self.instantiatedBars
for _index_0 = 1, #_list_0 do
local bar = _list_0[_index_0]
bar:_updateBarVisibility()
end
end
lineBaseTemplate = [[\an1%s%s%s\p1}]]
if _parent_0.__inherited then
_parent_0.__inherited(_parent_0, _class_0)
end
BarBase = _class_0
end
local ProgressBar
do
local _class_0
local seekString
local _parent_0 = BarBase
local _base_0 = {
reconfigure = function(self)
_class_0.__parent.__base.reconfigure(self)
seekString = ('absolute-percent+%s'):format(settings['seek-precision'])
self.barShift = settings['progress-bar-width'] / 2.0
self:resize()
self.line[7] = [[]]
self.line[8] = self.line[8]:format(settings['bar-foreground-style'])
end,
clickHandler = function(self)
return mp.commandv("seek", Mouse.clickX * 100 / Window.w, seekString)
end,
resize = function(self)
_class_0.__parent.__base.resize(self)
if self.barShift > 0 then
self.line[2] = ('%g,%g'):format(self.barShift, Window.h)
end
end,
redraw = function(self)
_class_0.__parent.__base.redraw(self)
if self.hideInactive and not self.active then
return self.needsUpdate
end
local position = mp.get_property_number('percent-pos', 0)
if position ~= self.lastPosition or self.needsUpdate then
self.line[6] = position
if self.barShift > 0 then
local followingEdge = Window.w * position * 1e-2 - self.barShift
self.line[7] = ([[\clip(m %g 0 l %g 0 %g %g %g %g)]]):format(followingEdge, Window.w, Window.w, Window.h, followingEdge, Window.h)
end
self.lastPosition = position
self.needsUpdate = true
end
return self.needsUpdate
end
}
_base_0.__index = _base_0
setmetatable(_base_0, _parent_0.__base)
_class_0 = setmetatable({
__init = function(self)
_class_0.__parent.__init(self)
self.lastPosition = 0
end,
__base = _base_0,
__name = "ProgressBar",
__parent = _parent_0
}, {
__index = function(cls, name)
local val = rawget(_base_0, name)
if val == nil then
local parent = rawget(cls, "__parent")
if parent then
return parent[name]
end
else
return val
end
end,
__call = function(cls, ...)
local _self_0 = setmetatable({}, _base_0)
cls.__init(_self_0, ...)
return _self_0
end
})
_base_0.__class = _class_0
local self = _class_0
seekString = ('absolute-percent+%s'):format(settings['seek-precision'])
if _parent_0.__inherited then
_parent_0.__inherited(_parent_0, _class_0)
end
ProgressBar = _class_0
end
local ProgressBarCache
do
local _class_0
local timestamp
local _parent_0 = BarBase
local _base_0 = {
reconfigure = function(self)
_class_0.__parent.__base.reconfigure(self, 'bar-cache-')
self.line[6] = 100
self.line[8] = self.line[8]:format(settings['bar-cache-style']) .. 'm 0 0'
self.line[10] = ([[{\p0%s\p1}]]):format(settings['bar-cache-background-style'])
self.line[11] = [[]]
self.fileDuration = mp.get_property_number('duration', nil)
end,
resize = function(self)
_class_0.__parent.__base.resize(self)
if self.fileDuration then
self.coordinateRemap = Window.w / self.fileDuration
end
self.line[9] = [[]]
end,
redraw = function(self)
_class_0.__parent.__base.redraw(self)
if self.hideInactive and not self.active then
return self.needsUpdate
end
if self.fileDuration and (self.fileDuration > 0) then
local barDrawing = {
past = { },
future = { }
}
local ranges
ranges = mp.get_property_native('demuxer-cache-state', { })['seekable-ranges']
if ranges and (#ranges > 0) then
local position = mp.get_property_number('percent-pos', 0)
local cacheKeyAggregator = {
Window.w,
position
}
for _index_0 = 1, #ranges do
local _des_0 = ranges[_index_0]
local rangeStart, rangeEnd
rangeStart, rangeEnd = _des_0.start, _des_0["end"]
table.insert(cacheKeyAggregator, rangeStart)
table.insert(cacheKeyAggregator, rangeEnd)
end
local cacheKey = table.concat(cacheKeyAggregator, '_')
if cacheKey == self.cacheKey then
return self.needsUpdate
end
local progressPosition = mp.get_property_number('percent-pos', 0) * Window.w * 0.01
for _index_0 = 1, #ranges do
local _des_0 = ranges[_index_0]
local rangeStart, rangeEnd
rangeStart, rangeEnd = _des_0.start, _des_0["end"]
rangeStart = rangeStart * self.coordinateRemap
rangeEnd = rangeEnd * self.coordinateRemap
if rangeEnd < progressPosition then
local rect = ('m %g 0 l %g 1 %g 1 %g 0'):format(rangeStart, rangeStart, rangeEnd, rangeEnd)
table.insert(barDrawing.past, rect)
elseif rangeStart > progressPosition then
rangeStart = rangeStart - progressPosition
rangeEnd = rangeEnd - progressPosition
local rect = ('m %g 0 l %g 1 %g 1 %g 0'):format(rangeStart, rangeStart, rangeEnd, rangeEnd)
table.insert(barDrawing.future, rect)
else
rangeEnd = rangeEnd - progressPosition
local rectPast = ('m %g 0 l %g 1 %g 1 %g 0'):format(rangeStart, rangeStart, progressPosition, progressPosition)
local rectFuture = ('m %g 0 l %g 1 %g 1 %g 0'):format(0, 0, rangeEnd, rangeEnd)
table.insert(barDrawing.past, rectPast)
table.insert(barDrawing.future, rectFuture)
end
end
self.line[9] = table.concat(barDrawing.past, ' ') .. ('m %g 0'):format(progressPosition)
self.line[11] = table.concat(barDrawing.future, ' ')
self.cacheKey = cacheKey
self.needsUpdate = true
end
end
return self.needsUpdate
end
}
_base_0.__index = _base_0
setmetatable(_base_0, _parent_0.__base)
_class_0 = setmetatable({
__init = function(self)
_class_0.__parent.__init(self)
self.cacheKey = nil
self.coordinateRemap = 0
return mp.observe_property('duration', 'number', function(name, value)
if value and (value > 0) then
self.fileDuration = value
self.coordinateRemap = Window.w / value
end
end)
end,
__base = _base_0,
__name = "ProgressBarCache",
__parent = _parent_0
}, {
__index = function(cls, name)
local val = rawget(_base_0, name)
if val == nil then
local parent = rawget(cls, "__parent")
if parent then
return parent[name]
end
else
return val
end
end,
__call = function(cls, ...)
local _self_0 = setmetatable({}, _base_0)
cls.__init(_self_0, ...)
return _self_0
end
})
_base_0.__class = _class_0
local self = _class_0
timestamp = os.time()
if _parent_0.__inherited then
_parent_0.__inherited(_parent_0, _class_0)
end
ProgressBarCache = _class_0
end
local ProgressBarBackground
do
local _class_0
local _parent_0 = BarBase
local _base_0 = {
reconfigure = function(self)
_class_0.__parent.__base.reconfigure(self)
if settings['bar-background-adaptive'] then
local _list_0 = self.__class.instantiatedBars
for _index_0 = 1, #_list_0 do
local bar = _list_0[_index_0]
self.minHeight = math.max(self.minHeight, bar.minHeight)
self.maxHeight = math.max(self.maxHeight, bar.maxHeight)
end
self:_updateBarVisibility()
end
self.line[6] = 100
self.line[8] = self.line[8]:format(settings['bar-background-style'])
end
}
_base_0.__index = _base_0
setmetatable(_base_0, _parent_0.__base)
_class_0 = setmetatable({
__init = function(self, ...)
return _class_0.__parent.__init(self, ...)
end,
__base = _base_0,
__name = "ProgressBarBackground",
__parent = _parent_0
}, {
__index = function(cls, name)
local val = rawget(_base_0, name)
if val == nil then
local parent = rawget(cls, "__parent")
if parent then
return parent[name]
end
else
return val
end
end,
__call = function(cls, ...)
local _self_0 = setmetatable({}, _base_0)
cls.__init(_self_0, ...)
return _self_0
end
})
_base_0.__class = _class_0
if _parent_0.__inherited then
_parent_0.__inherited(_parent_0, _class_0)
end
ProgressBarBackground = _class_0
end
local ChapterMarker
do
local _class_0
local beforeStyle, afterStyle
local _base_0 = {
stringify = function(self)
return table.concat(self.line)
end,
resize = function(self)
self.line[2] = ('%d,%d'):format(math.floor(self.position * Window.w), Window.h)
end,
animate = function(self, width, height)
self.line[4] = ('%g'):format(width)
self.line[6] = ('%g'):format(height)
end,
redraw = function(self, position, update)
if update == nil then
update = false
end
if not self.passed and (position > self.position) then
self.line[7] = afterStyle
self.passed = true
update = true
elseif self.passed and (position < self.position) then
self.line[7] = beforeStyle
self.passed = false
update = true
end
return update
end
}
_base_0.__index = _base_0
_class_0 = setmetatable({
__init = function(self, position, minWidth, minHeight)
self.position = position
self.line = {
[[{\an2\bord0\p1\pos(]],
([[%g,%g]]):format(self.position * Window.w, Window.h),
[[)\fscx]],
minWidth,
[[\fscy]],
minHeight,
beforeStyle,
'}m 0 0 l 1 0 1 1 0 1\n'
}
self.passed = false
end,
__base = _base_0,
__name = "ChapterMarker"
}, {
__index = _base_0,
__call = function(cls, ...)
local _self_0 = setmetatable({}, _base_0)
cls.__init(_self_0, ...)
return _self_0
end
})
_base_0.__class = _class_0
local self = _class_0
beforeStyle = settings['chapter-marker-before-style']
afterStyle = settings['chapter-marker-after-style']
self.reconfigure = function(self)
beforeStyle = settings['chapter-marker-before-style']
afterStyle = settings['chapter-marker-after-style']
end
ChapterMarker = _class_0
end
local Chapters
do
local _class_0
local minWidth, maxWidth, maxHeight, maxHeightFrac
local _parent_0 = BarBase
local _base_0 = {
createMarkers = function(self)
self.line = { }
self.markers = { }
local totalTime = mp.get_property_number('duration', 0.01)
local chapters = mp.get_property_native('chapter-list', { })
local markerHeight = self.active and maxHeight * maxHeightFrac or BarBase.instantiatedBars[1].animationMinHeight
local markerWidth = self.active and maxWidth or minWidth
for _index_0 = 1, #chapters do
local chapter = chapters[_index_0]
local marker = ChapterMarker(chapter.time / totalTime, markerWidth, markerHeight)
table.insert(self.markers, marker)
table.insert(self.line, marker:stringify())
end
self.needsUpdate = true
end,
reconfigure = function(self)
UIElement.reconfigure(self)
minWidth = settings['chapter-marker-width'] * 100
maxWidth = settings['chapter-marker-width-active'] * 100
maxHeight = settings['bar-height-active'] * 100
maxHeightFrac = settings['chapter-marker-active-height-fraction']
ChapterMarker:reconfigure()
self:createMarkers()
self.animation = Animation(0, 1, self.animationDuration, (function()
local _base_1 = self
local _fn_0 = _base_1.animate
return function(...)
return _fn_0(_base_1, ...)
end
end)())
end,
resize = function(self)
for i, marker in ipairs(self.markers) do
marker:resize()
self.line[i] = marker:stringify()
end
self.needsUpdate = true
end,
animate = function(self, value)
local width = (maxWidth - minWidth) * value + minWidth
local height = (maxHeight * maxHeightFrac - BarBase.instantiatedBars[1].animationMinHeight) * value + BarBase.instantiatedBars[1].animationMinHeight
for i, marker in ipairs(self.markers) do
marker:animate(width, height)
self.line[i] = marker:stringify()
end
self.needsUpdate = true
end,
redraw = function(self)
_class_0.__parent.__base.redraw(self)
local currentPosition = mp.get_property_number('percent-pos', 0) * 0.01
local update = false
for i, marker in ipairs(self.markers) do
if marker:redraw(currentPosition) then
self.line[i] = marker:stringify()
update = true
end
end
return self.needsUpdate or update
end
}
_base_0.__index = _base_0
setmetatable(_base_0, _parent_0.__base)
_class_0 = setmetatable({
__init = function(self)
_class_0.__parent.__init(self)
self.line = { }
self.markers = { }
self.animation = Animation(0, 1, self.animationDuration, (function()
local _base_1 = self
local _fn_0 = _base_1.animate
return function(...)
return _fn_0(_base_1, ...)
end
end)())
end,
__base = _base_0,
__name = "Chapters",
__parent = _parent_0
}, {
__index = function(cls, name)
local val = rawget(_base_0, name)
if val == nil then
local parent = rawget(cls, "__parent")
if parent then
return parent[name]
end
else
return val
end
end,
__call = function(cls, ...)
local _self_0 = setmetatable({}, _base_0)
cls.__init(_self_0, ...)
return _self_0
end
})
_base_0.__class = _class_0
local self = _class_0
minWidth = settings['chapter-marker-width'] * 100
maxWidth = settings['chapter-marker-width-active'] * 100
maxHeight = settings['bar-height-active'] * 100
maxHeightFrac = settings['chapter-marker-active-height-fraction']
if _parent_0.__inherited then
_parent_0.__inherited(_parent_0, _class_0)
end
Chapters = _class_0
end
local TimeElapsed
do
local _class_0
local bottomMargin
local _parent_0 = BarAccent
local _base_0 = {
reconfigure = function(self)
_class_0.__parent.__base.reconfigure(self)
bottomMargin = settings['elapsed-bottom-margin']
local offscreenPos = settings['elapsed-offscreen-pos']
self.line[2] = ('%g,%g'):format(self.position, self.yPos - bottomMargin)
self.line[3] = ([[)\an1%s%s}]]):format(settings['default-style'], settings['elapsed-style'])
self.animation = Animation(offscreenPos, settings['elapsed-left-margin'], self.animationDuration, (function()
local _base_1 = self
local _fn_0 = _base_1.animate
return function(...)
return _fn_0(_base_1, ...)
end
end)(), nil, 0.5)
end,
resize = function(self)
_class_0.__parent.__base.resize(self)
self.line[2] = ('%g,%g'):format(self.position, self.yPos - bottomMargin)
end,
animate = function(self, value)
self.position = value
self.line[2] = ('%g,%g'):format(value, self.yPos - bottomMargin)
self.needsUpdate = true
end,
redraw = function(self)
if self.active then
_class_0.__parent.__base.redraw(self)
local timeElapsed = math.floor(mp.get_property_number('time-pos', 0))
if timeElapsed ~= self.lastTime then
local update = true
self.line[4] = ('%d:%02d:%02d'):format(math.floor(timeElapsed / 3600), math.floor((timeElapsed / 60) % 60), math.floor(timeElapsed % 60))
self.lastTime = timeElapsed
self.needsUpdate = true
end
end
return self.needsUpdate
end
}
_base_0.__index = _base_0
setmetatable(_base_0, _parent_0.__base)
_class_0 = setmetatable({
__init = function(self)
_class_0.__parent.__init(self)
local offscreenPos = settings['elapsed-offscreen-pos']
self.line = {
[[{\pos(]],
([[%g,0]]):format(offscreenPos),
([[)\an1%s%s}]]):format(settings['default-style'], settings['elapsed-style']),
[[????]]
}
self.lastTime = -1
self.position = offscreenPos
self.animation = Animation(offscreenPos, settings['elapsed-left-margin'], self.animationDuration, (function()
local _base_1 = self
local _fn_0 = _base_1.animate
return function(...)
return _fn_0(_base_1, ...)
end
end)(), nil, 0.5)
end,
__base = _base_0,
__name = "TimeElapsed",
__parent = _parent_0
}, {
__index = function(cls, name)
local val = rawget(_base_0, name)
if val == nil then
local parent = rawget(cls, "__parent")
if parent then
return parent[name]
end
else
return val
end
end,
__call = function(cls, ...)
local _self_0 = setmetatable({}, _base_0)
cls.__init(_self_0, ...)
return _self_0
end
})
_base_0.__class = _class_0
local self = _class_0
bottomMargin = settings['elapsed-bottom-margin']
if _parent_0.__inherited then
_parent_0.__inherited(_parent_0, _class_0)
end
TimeElapsed = _class_0
end
local TimeRemaining
do
local _class_0
local bottomMargin
local _parent_0 = BarAccent
local _base_0 = {
reconfigure = function(self)
_class_0.__parent.__base.reconfigure(self)
bottomMargin = settings['remaining-bottom-margin']
local offscreenPos = settings['remaining-offscreen-pos']
self.line[2] = ('%g,%g'):format(self.position, self.yPos - bottomMargin)
self.line[3] = ([[)\an3%s%s}]]):format(settings['default-style'], settings['remaining-style'])
self.animation = Animation(offscreenPos, settings['remaining-right-margin'], self.animationDuration, (function()
local _base_1 = self
local _fn_0 = _base_1.animate
return function(...)
return _fn_0(_base_1, ...)
end
end)(), nil, 0.5)
end,
resize = function(self)
_class_0.__parent.__base.resize(self)
self.position = Window.w - self.animation.value
self.line[2] = ('%g,%g'):format(self.position, self.yPos - bottomMargin)
end,
animate = function(self, value)
self.position = Window.w - value
self.line[2] = ('%g,%g'):format(self.position, self.yPos - bottomMargin)
self.needsUpdate = true
end,
redraw = function(self)
if self.active then
_class_0.__parent.__base.redraw(self)
local timeRemaining = math.floor(mp.get_property_number('playtime-remaining', 0))
if timeRemaining ~= self.lastTime then
local update = true
self.line[4] = ('%d:%02d:%02d'):format(math.floor(timeRemaining / 3600), math.floor((timeRemaining / 60) % 60), math.floor(timeRemaining % 60))
self.lastTime = timeRemaining
self.needsUpdate = true
end
end
return self.needsUpdate
end
}
_base_0.__index = _base_0
setmetatable(_base_0, _parent_0.__base)
_class_0 = setmetatable({
__init = function(self)
_class_0.__parent.__init(self)
local offscreenPos = settings['remaining-offscreen-pos']
self.line = {
[[{\pos(]],
([[%g,0]]):format(offscreenPos),
([[)\an3%s%s}]]):format(settings['default-style'], settings['remaining-style']),
[[????]]
}
self.lastTime = -1
self.position = offscreenPos
self.animation = Animation(offscreenPos, settings['remaining-right-margin'], self.animationDuration, (function()
local _base_1 = self
local _fn_0 = _base_1.animate
return function(...)
return _fn_0(_base_1, ...)
end
end)(), nil, 0.5)
end,
__base = _base_0,
__name = "TimeRemaining",
__parent = _parent_0
}, {
__index = function(cls, name)
local val = rawget(_base_0, name)
if val == nil then
local parent = rawget(cls, "__parent")
if parent then
return parent[name]
end
else
return val
end
end,
__call = function(cls, ...)
local _self_0 = setmetatable({}, _base_0)
cls.__init(_self_0, ...)
return _self_0
end
})
_base_0.__class = _class_0
local self = _class_0
bottomMargin = settings['remaining-bottom-margin']
if _parent_0.__inherited then
_parent_0.__inherited(_parent_0, _class_0)
end
TimeRemaining = _class_0
end
local HoverTime
do
local _class_0
local rightMargin, leftMargin, bottomMargin, offScreenPos
local _parent_0 = BarAccent
local _base_0 = {
reconfigure = function(self)
_class_0.__parent.__base.reconfigure(self)
rightMargin = settings['hover-time-right-margin']
leftMargin = settings['hover-time-left-margin']
bottomMargin = settings['hover-time-bottom-margin']
offScreenPos = settings['hover-time-offscreen-pos']
self.line[2] = ('%g,%g'):format(math.min(Window.w - rightMargin, math.max(leftMargin, Mouse.x)), self.position)
self.line[1] = ([[{%s%s\pos(]]):format(settings['default-style'], settings['hover-time-style'])
self.animation = Animation(offScreenPos, bottomMargin, self.animationDuration, (function()
local _base_1 = self
local _fn_0 = _base_1.animate
return function(...)
return _fn_0(_base_1, ...)
end
end)(), nil, 0.5)
end,
resize = function(self)
_class_0.__parent.__base.resize(self)
self.line[2] = ("%g,%g"):format(math.min(Window.w - rightMargin, math.max(leftMargin, Mouse.x)), self.yPos - self.animation.value)
end,
animate = function(self, value)
self.position = self.yPos - value
self.line[2] = ("%g,%g"):format(math.min(Window.w - rightMargin, math.max(leftMargin, Mouse.x)), self.position)
self.needsUpdate = true
end,
redraw = function(self)
if self.active then
_class_0.__parent.__base.redraw(self)
if Mouse.x ~= self.lastX then
self.line[2] = ("%g,%g"):format(math.min(Window.w - rightMargin, math.max(leftMargin, Mouse.x)), self.position)
self.lastX = Mouse.x
local hoverTime = mp.get_property_number('duration', 0) * Mouse.x / Window.w
if hoverTime ~= self.lastTime then
self.line[4] = ([[%d:%02d:%02d]]):format(math.floor(hoverTime / 3600), math.floor((hoverTime / 60) % 60), math.floor(hoverTime % 60))
self.lastTime = hoverTime
end
self.needsUpdate = true
end
end
return self.needsUpdate
end
}
_base_0.__index = _base_0
setmetatable(_base_0, _parent_0.__base)
_class_0 = setmetatable({
__init = function(self)
_class_0.__parent.__init(self)
self.line = {
([[{%s%s\pos(]]):format(settings['default-style'], settings['hover-time-style']),
[[-100,0]],
[[)\an2}]],
[[????]]
}
self.lastTime = 0
self.lastX = -1
self.position = offScreenPos
self.animation = Animation(offScreenPos, bottomMargin, self.animationDuration, (function()
local _base_1 = self
local _fn_0 = _base_1.animate
return function(...)
return _fn_0(_base_1, ...)
end
end)(), nil, 0.5)
end,
__base = _base_0,
__name = "HoverTime",
__parent = _parent_0
}, {
__index = function(cls, name)
local val = rawget(_base_0, name)
if val == nil then
local parent = rawget(cls, "__parent")
if parent then
return parent[name]
end
else
return val
end
end,
__call = function(cls, ...)
local _self_0 = setmetatable({}, _base_0)
cls.__init(_self_0, ...)
return _self_0
end
})
_base_0.__class = _class_0
local self = _class_0
rightMargin = settings['hover-time-right-margin']
leftMargin = settings['hover-time-left-margin']
bottomMargin = settings['hover-time-bottom-margin']
offScreenPos = settings['hover-time-offscreen-pos']
if _parent_0.__inherited then
_parent_0.__inherited(_parent_0, _class_0)
end
HoverTime = _class_0
end
local PauseIndicator
do
local _class_0
local _base_0 = {
stringify = function(self)
return table.concat(self.line)
end,
resize = function(self)
local w, h = 0.5 * Window.w, 0.5 * Window.h
self.line[5] = ([[%g,%g]]):format(w, h)
self.line[12] = ([[%g,%g]]):format(w, h)
end,
redraw = function()
return true
end,
animate = function(self, value)
local scale = value * 50 + 100
local scaleStr = ([[{\fscx%g\fscy%g]]):format(scale, scale)
local alphaStr = ('%02X'):format(value * value * 255)
self.line[1] = scaleStr
self.line[8] = scaleStr
self.line[3] = alphaStr
self.line[10] = alphaStr
end,
destroy = function(self, animation)
return self.eventLoop:removeUIElement(self)
end
}
_base_0.__index = _base_0
_class_0 = setmetatable({
__init = function(self, eventLoop, paused)
self.eventLoop = eventLoop
local w, h = 0.5 * Window.w, 0.5 * Window.h
self.line = {
[[{\fscx0\fscy0]],
[[\alpha&H]],
0,
[[&\pos(]],
([[%g,%g]]):format(w, h),
([[)\an5\bord0%s\p1}]]):format(settings['pause-indicator-background-style']),
0,
[[{\fscx0\fscy0]],
[[\alpha&H]],
0,
[[&\pos(]],
([[%g,%g]]):format(w, h),
([[)\an5\bord0%s\p1}]]):format(settings['pause-indicator-foreground-style']),
0
}
if paused then
self.line[7] = 'm 75 37.5 b 75 58.21 58.21 75 37.5 75 16.79 75 0 58.21 0 37.5 0 16.79 16.79 0 37.5 0 58.21 0 75 16.79 75 37.5 m 23 20 l 23 55 33 55 33 20 m 42 20 l 42 55 52 55 52 20\n'
self.line[14] = 'm 0 0 m 75 75 m 23 20 l 23 55 33 55 33 20 m 42 20 l 42 55 52 55 52 20'
else
self.line[7] = 'm 75 37.5 b 75 58.21 58.21 75 37.5 75 16.79 75 0 58.21 0 37.5 0 16.79 16.79 0 37.5 0 58.21 0 75 16.79 75 37.5 m 25.8333 17.18 l 25.8333 57.6 60.8333 37.39\n'
self.line[14] = 'm 0 0 m 75 75 m 25.8333 17.18 l 25.8333 57.6 60.8333 37.39'
end
AnimationQueue.addAnimation(Animation(0, 1, settings['animation-duration'], (function()
local _base_1 = self
local _fn_0 = _base_1.animate
return function(...)
return _fn_0(_base_1, ...)
end
end)(), (function()
local _base_1 = self
local _fn_0 = _base_1.destroy
return function(...)
return _fn_0(_base_1, ...)
end
end)()))
return self.eventLoop:addUIElement(self)
end,
__base = _base_0,
__name = "PauseIndicator"
}, {
__index = _base_0,
__call = function(cls, ...)
local _self_0 = setmetatable({}, _base_0)
cls.__init(_self_0, ...)
return _self_0
end
})
_base_0.__class = _class_0
PauseIndicator = _class_0
end
local Title
do
local _class_0
local _parent_0 = UIElement
local _base_0 = {
reconfigure = function(self)
_class_0.__parent.__base.reconfigure(self)
local offscreenPos = settings['title-offscreen-pos']
self.line[2] = ('%g,%g'):format(settings['title-left-margin'], self.animation.value)
self.line[3] = ([[)\an7%s%s}]]):format(settings['default-style'], settings['title-style'])
self.animation = Animation(offscreenPos, settings['title-top-margin'], self.animationDuration, (function()
local _base_1 = self
local _fn_0 = _base_1.animate
return function(...)
return _fn_0(_base_1, ...)
end
end)(), nil, 0.5)
end,
resize = function(self) end,
animate = function(self, value)
self.line[2] = ('%g,%g'):format(settings['title-left-margin'], value)
self.needsUpdate = true
end,
_forceUpdatePlaylistInfo = function(self)
self.playlistInfo = {
['media-title'] = mp.get_property('media-title', '????'),
['playlist-pos-1'] = mp.get_property_number('playlist-pos-1', 1),
['playlist-count'] = mp.get_property_number('playlist-count', 1)
}
end,
generateTitleString = function(self, quote)
if quote == nil then
quote = false
end
local title, position, total
do
local _obj_0 = self.playlistInfo
title, position, total = _obj_0['media-title'], _obj_0['playlist-pos-1'], _obj_0['playlist-count']
end
local prefix = (total > 1) and ('%d/%d - '):format(position, total) or ''
if quote then
return prefix .. ('%q'):format(title)
else
return prefix .. title
end
end,
updatePlaylistInfo = function(self, changedProp, newValue)
if newValue then
self.playlistInfo[changedProp] = newValue
self.line[4] = self:generateTitleString()
self.needsUpdate = true
end
end,
print = function(self)
if settings['title-print-to-cli'] then
return log.warn("Playing: %s", self:generateTitleString(true))
end
end
}
_base_0.__index = _base_0
setmetatable(_base_0, _parent_0.__base)
_class_0 = setmetatable({
__init = function(self)
_class_0.__parent.__init(self)
local offscreenPos = settings['title-offscreen-pos']
self.line = {
[[{\pos(]],
([[%g,%g]]):format(settings['title-left-margin'], offscreenPos),
([[)\an7%s%s}]]):format(settings['default-style'], settings['title-style']),
[[????]]
}
self.position = offscreenPos
self.animation = Animation(offscreenPos, settings['title-top-margin'], self.animationDuration, (function()
local _base_1 = self
local _fn_0 = _base_1.animate
return function(...)
return _fn_0(_base_1, ...)
end
end)(), nil, 0.5)
self:_forceUpdatePlaylistInfo()
local updatePlaylistInfo
do
local _base_1 = self
local _fn_0 = _base_1.updatePlaylistInfo
updatePlaylistInfo = function(...)
return _fn_0(_base_1, ...)
end
end
mp.observe_property('media-title', 'string', updatePlaylistInfo)
mp.observe_property('playlist-pos-1', 'number', updatePlaylistInfo)
return mp.observe_property('playlist-count', 'number', updatePlaylistInfo)
end,
__base = _base_0,
__name = "Title",
__parent = _parent_0
}, {
__index = function(cls, name)
local val = rawget(_base_0, name)
if val == nil then
local parent = rawget(cls, "__parent")
if parent then
return parent[name]
end
else
return val
end
end,
__call = function(cls, ...)
local _self_0 = setmetatable({}, _base_0)
cls.__init(_self_0, ...)
return _self_0
end
})
_base_0.__class = _class_0
if _parent_0.__inherited then
_parent_0.__inherited(_parent_0, _class_0)
end
Title = _class_0
end
local SystemTime
do
local _class_0
local offscreenPosition, topMargin, timeFormat
local _parent_0 = UIElement
local _base_0 = {
reconfigure = function(self)
_class_0.__parent.__base.reconfigure(self)
offscreenPosition = settings['system-time-offscreen-pos']
topMargin = settings['system-time-top-margin']
timeFormat = settings['system-time-format']
self.line[2] = ('%g,%g'):format(self.position, topMargin)
self.line[3] = ([[)\an9%s%s}]]):format(settings['default-style'], settings['system-time-style'])
self.animation = Animation(offscreenPosition, settings['system-time-right-margin'], self.animationDuration, (function()
local _base_1 = self
local _fn_0 = _base_1.animate
return function(...)
return _fn_0(_base_1, ...)
end
end)(), nil, 0.5)
end,
resize = function(self)
self.position = Window.w - self.animation.value
self.line[2] = ('%g,%g'):format(self.position, topMargin)
end,
animate = function(self, value)
self.position = Window.w - value
self.line[2] = ('%g,%g'):format(self.position, topMargin)
self.needsUpdate = true
end,
redraw = function(self)
if self.active then
local systemTime = os.time()
if systemTime ~= self.lastTime then
local update = true
self.line[4] = os.date(timeFormat, systemTime)
self.lastTime = systemTime
self.needsUpdate = true
end
end
return self.needsUpdate
end
}
_base_0.__index = _base_0
setmetatable(_base_0, _parent_0.__base)
_class_0 = setmetatable({
__init = function(self)
_class_0.__parent.__init(self)
self.line = {
[[{\pos(]],
[[-100,0]],
([[)\an9%s%s}]]):format(settings['default-style'], settings['system-time-style']),
[[????]]
}
self.lastTime = -1
self.position = offscreenPosition
self.animation = Animation(offscreenPosition, settings['system-time-right-margin'], self.animationDuration, (function()
local _base_1 = self
local _fn_0 = _base_1.animate
return function(...)
return _fn_0(_base_1, ...)
end
end)(), nil, 0.5)
end,
__base = _base_0,
__name = "SystemTime",
__parent = _parent_0
}, {
__index = function(cls, name)
local val = rawget(_base_0, name)
if val == nil then
local parent = rawget(cls, "__parent")
if parent then
return parent[name]
end
else
return val
end
end,
__call = function(cls, ...)
local _self_0 = setmetatable({}, _base_0)
cls.__init(_self_0, ...)
return _self_0
end
})
_base_0.__class = _class_0
local self = _class_0
offscreenPosition = settings['system-time-offscreen-pos']
topMargin = settings['system-time-top-margin']
timeFormat = settings['system-time-format']
if _parent_0.__inherited then
_parent_0.__inherited(_parent_0, _class_0)
end
SystemTime = _class_0
end
local eventLoop = EventLoop()
local activeHeight = settings['hover-zone-height']
local ignoreRequestDisplay
ignoreRequestDisplay = function(self)
if not (Mouse.inWindow) then
return false
end
if Mouse.dead then
return false
end
return self:containsPoint(Mouse.x, Mouse.y)
end
local bottomZone = ActivityZone(function(self)
return self:reset(0, Window.h - activeHeight, Window.w, activeHeight)
end)
local hoverTimeZone = ActivityZone(function(self)
return self:reset(0, Window.h - activeHeight, Window.w, activeHeight)
end, ignoreRequestDisplay)
local topZone = ActivityZone(function(self)
return self:reset(0, 0, Window.w, activeHeight)
end, ignoreRequestDisplay)
local chapters, progressBar, barCache, barBackground, elapsedTime, remainingTime, hoverTime
if settings['enable-bar'] then
progressBar = ProgressBar()
barCache = ProgressBarCache()
barBackground = ProgressBarBackground()
bottomZone:addUIElement(barBackground)
if settings['bar-cache-position'] == 'overlay' then
bottomZone:addUIElement(progressBar)
bottomZone:addUIElement(barCache)
else
bottomZone:addUIElement(barCache)
bottomZone:addUIElement(progressBar)
end
mp.add_key_binding("c", "toggle-inactive-bar", function()
return BarBase:toggleInactiveVisibility()
end)
end
if settings['enable-chapter-markers'] then
chapters = Chapters()
bottomZone:addUIElement(chapters)
end
if settings['enable-elapsed-time'] then
elapsedTime = TimeElapsed()
bottomZone:addUIElement(elapsedTime)
end
if settings['enable-remaining-time'] then
remainingTime = TimeRemaining()
bottomZone:addUIElement(remainingTime)
end
if settings['enable-hover-time'] then
hoverTime = HoverTime()
hoverTimeZone:addUIElement(hoverTime)
end
local title = nil
if settings['enable-title'] then
title = Title()
bottomZone:addUIElement(title)
topZone:addUIElement(title)
end
if settings['enable-system-time'] then
local systemTime = SystemTime()
bottomZone:addUIElement(systemTime)
topZone:addUIElement(systemTime)
end
eventLoop:addZone(hoverTimeZone)
eventLoop:addZone(bottomZone)
eventLoop:addZone(topZone)
local notFrameStepping = false
if settings['pause-indicator'] then
local PauseIndicatorWrapper
PauseIndicatorWrapper = function(event, paused)
if notFrameStepping then
return PauseIndicator(eventLoop, paused)
elseif paused then
notFrameStepping = true
end
end
mp.add_key_binding('.', 'step-forward', function()
notFrameStepping = false
return mp.commandv('frame_step')
end, {
repeatable = true
})
mp.add_key_binding(',', 'step-backward', function()
notFrameStepping = false
return mp.commandv('frame_back_step')
end, {
repeatable = true
})
mp.observe_property('pause', 'bool', PauseIndicatorWrapper)
end
local streamMode = false
local initDraw
initDraw = function()
if chapters then
chapters:createMarkers()
end
if title then
title:_forceUpdatePlaylistInfo()
title:print()
end
notFrameStepping = true
local duration = mp.get_property('duration')
if not (streamMode or duration) then
BarAccent.changeBarSize(0)
if progressBar then
bottomZone:removeUIElement(progressBar)
bottomZone:removeUIElement(barCache)
bottomZone:removeUIElement(barBackground)
end
if chapters then
bottomZone:removeUIElement(chapters)
end
if hoverTime then
hoverTimeZone:removeUIElement(hoverTime)
end
if remainingTime then
bottomZone:removeUIElement(remainingTime)
end
streamMode = true
elseif streamMode and duration then
BarAccent.changeBarSize(settings['bar-height-active'])
if progressBar then
bottomZone:addUIElement(barBackground)
bottomZone:addUIElement(barCache)
bottomZone:addUIElement(progressBar)
end
if chapters then
bottomZone:addUIElement(chapters)
end
if hoverTime then
hoverTimeZone:addUIElement(hoverTime)
end
if remainingTime then
bottomZone:addUIElement(remainingTime)
end
streamMode = false
end
mp.command('script-message-to osc disable-osc')
eventLoop:generateUIFromZones()
eventLoop:resize()
return eventLoop:redraw()
end
return mp.register_event('file-loaded', initDraw)