Created
July 6, 2015 01:06
-
-
Save iGlitch/27f509973cb9d7f38d2b to your computer and use it in GitHub Desktop.
MPV Minimal Progress Bar
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
local msg = require('mp.msg') | |
local bar_height = 2 | |
local hover_zone = 20 | |
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) | |
local level = 2 | |
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 OSDAggregator | |
do | |
local _base_0 = { | |
addSubscriber = function(self, subscriber) | |
if not subscriber then | |
return | |
end | |
self.subscriberCount = self.subscriberCount + 1 | |
subscriber.aggregatorIndex = self.subscriberCount | |
self.subscribers[self.subscriberCount] = subscriber | |
self.script[self.subscriberCount] = subscriber:stringify() | |
end, | |
removeSubscriber = function(self, index) | |
table.remove(self.subscribers, index) | |
table.remove(self.script, index) | |
self.subscriberCount = self.subscriberCount - 1 | |
for i = index, self.subscriberCount do | |
self.subscribers[i].aggregatorIndex = i | |
end | |
end, | |
update = function(self, force) | |
if force == nil then | |
force = false | |
end | |
local needsRedraw = force | |
local x, y = mp.get_mouse_pos() | |
local w, h = mp.get_screen_size() | |
local needsResize = false | |
if w ~= self.w or h ~= self.h then | |
self.w, self.h = w, h | |
needsResize = true | |
end | |
for sub = 1, self.subscriberCount do | |
local theSub = self.subscribers[sub] | |
local update = false | |
if theSub:update(x, y, self.mouseOver) then | |
update = true | |
end | |
if (needsResize and theSub:updateSize(w, h)) or update then | |
needsRedraw = true | |
self.script[sub] = theSub:stringify() | |
end | |
end | |
if true == needsRedraw then | |
return mp.set_osd_ass(self.w, self.h, table.concat(self.script, '\n')) | |
end | |
end, | |
pause = function(self, event, paused) | |
self.paused = paused | |
if self.paused then | |
return self.updateTimer:stop() | |
else | |
return self.updateTimer:resume() | |
end | |
end, | |
forceUpdate = function(self) | |
self.updateTimer:kill() | |
self:update(true) | |
if not (self.paused) then | |
return self.updateTimer:resume() | |
end | |
end | |
} | |
_base_0.__index = _base_0 | |
local _class_0 = setmetatable({ | |
__init = function(self) | |
self.script = { } | |
self.subscribers = { } | |
self.subscriberCount = 0 | |
self.mouseOver = false | |
self.w = 0 | |
self.h = 0 | |
local redrawFrequency = 0.05 | |
self.updateTimer = mp.add_periodic_timer(redrawFrequency, (function() | |
local _base_1 = self | |
local _fn_0 = _base_1.update | |
return function(...) | |
return _fn_0(_base_1, ...) | |
end | |
end)()) | |
mp.register_event('shutdown', function() | |
return self.updateTimer:kill() | |
end) | |
mp.add_key_binding("MOUSE_LEAVE", function() | |
self.mouseOver = false | |
end) | |
return mp.add_key_binding("MOUSE_ENTER", function() | |
self.mouseOver = true | |
end) | |
end, | |
__base = _base_0, | |
__name = "OSDAggregator" | |
}, { | |
__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 | |
OSDAggregator = _class_0 | |
end | |
local AnimationQueue | |
do | |
local _base_0 = { | |
registerAnimation = function(self, animation) | |
if self.list then | |
self.list.next = animation | |
end | |
animation.prev = self.list | |
animation.isRegistered = true | |
self.list = animation | |
self.animationCount = self.animationCount + 1 | |
return self:startAnimation() | |
end, | |
unregisterAnimation = function(self, animation) | |
local prev = animation.prev | |
local next = animation.next | |
if prev then | |
prev.next = next | |
end | |
if next then | |
next.prev = prev | |
end | |
if self.list == animation then | |
self.list = prev | |
end | |
animation.next = nil | |
animation.prev = nil | |
animation.isRegistered = false | |
self.animationCount = self.animationCount - 1 | |
if 0 == self.animationCount then | |
self:stopAnimation() | |
end | |
return prev | |
end, | |
startAnimation = function(self) | |
if self.animating then | |
return | |
end | |
self.timer:resume() | |
self.animating = true | |
end, | |
stopAnimation = function(self) | |
if not (self.animating) then | |
return | |
end | |
self.timer:kill() | |
self.animating = false | |
end, | |
destroyAnimationStack = function(self) | |
self:stopAnimation() | |
local currentAnimation = self.list | |
while currentAnimation do | |
currentAnimation = self.list.prev | |
self.list.prev = nil | |
self.list.next = nil | |
self.list = currentAnimation | |
end | |
end, | |
animate = function(self) | |
local currentAnimation = self.list | |
local currentTime = mp.get_time() | |
while currentAnimation do | |
if currentAnimation:update(currentTime) then | |
currentAnimation = self:unregisterAnimation(currentAnimation) | |
else | |
currentAnimation = currentAnimation.prev | |
end | |
end | |
return self.aggregator:forceUpdate() | |
end | |
} | |
_base_0.__index = _base_0 | |
local _class_0 = setmetatable({ | |
__init = function(self, aggregator) | |
self.aggregator = aggregator | |
self.list = nil | |
self.animationCount = 0 | |
self.animating = false | |
self.timer = mp.add_periodic_timer(0.05, (function() | |
local _base_1 = self | |
local _fn_0 = _base_1.animate | |
return function(...) | |
return _fn_0(_base_1, ...) | |
end | |
end)()) | |
return self.timer:kill() | |
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 | |
AnimationQueue = _class_0 | |
end | |
local Animation | |
do | |
local _base_0 = { | |
update = function(self, currentTime) | |
self.currentTime = currentTime | |
local progress = math.max(0, math.min(1, (self.currentTime - self.startTime) * self.durationR)) | |
if progress == 1 then | |
self.isFinished = true | |
end | |
if self.accel then | |
progress = math.pow(progress, self.accel) | |
end | |
local value = (1 - progress) * self.initialValue + progress * self.endValue | |
self:updateCb(value) | |
if self.isFinished and self.finishedCb then | |
self:finishedCb() | |
end | |
return self.isFinished | |
end, | |
interrupt = function(self, reverse, queue) | |
if reverse ~= self.isReversed then | |
self:reverse() | |
end | |
if not (self.isRegistered) then | |
self:restart() | |
return queue:registerAnimation(self) | |
end | |
end, | |
reverse = function(self) | |
self.isReversed = not self.isReversed | |
self.initialValue, self.endValue = self.endValue, self.initialValue | |
self.startTime = 2 * self.currentTime - self.duration - self.startTime | |
self.accel = 1 / self.accel | |
end, | |
restart = function(self) | |
self.startTime = mp.get_time() | |
self.currentTime = self.startTime | |
self.isFinished = false | |
end | |
} | |
_base_0.__index = _base_0 | |
local _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.startTime = mp.get_time() | |
self.currentTime = self.startTime | |
self.durationR = 1 / self.duration | |
self.isFinished = (self.duration <= 0) | |
self.isRegistered = 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 Rect | |
do | |
local _base_0 = { | |
setPosition = function(self, x, y) | |
self.x = x or self.x | |
self.y = y or self.y | |
end, | |
setDimensions = function(self, w, h) | |
self.w = w or self.w | |
self.h = h or self.h | |
end, | |
move = function(self, x, y) | |
self.x = self.x + (x or 0) | |
self.y = self.y + (y or 0) | |
end, | |
stretch = function(self, w, h) | |
self.w = self.w + (w or 0) | |
self.h = self.h + (h or 0) | |
end, | |
containsPoint = function(self, x, y) | |
return ((x >= self.x) and (y >= self.y) and (x < self.x + self.w) and (y < self.y + self.h)) | |
end | |
} | |
_base_0.__index = _base_0 | |
local _class_0 = setmetatable({ | |
__init = function(self, x, y, w, h) | |
self.x, self.y, self.w, self.h = x, y, w, h | |
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 Subscriber | |
do | |
local _parent_0 = Rect | |
local _base_0 = { | |
stringify = function(self) | |
if not self.hovered and not self.animation.isRegistered then | |
return "" | |
end | |
return table.concat(self.line) | |
end, | |
updateSize = function(self, w, h) | |
self.y = h - hover_zone * bar_height | |
self.w, self.h = w, hover_zone * bar_height | |
end, | |
update = function(self, mouseX, mouseY, mouseOver, hoverCondition) | |
if hoverCondition == nil then | |
hoverCondition = self:containsPoint(mouseX, mouseY) | |
end | |
local update = self.needsUpdate | |
self.needsUpdate = false | |
if mouseOver and hoverCondition then | |
if not (self.hovered) then | |
update = true | |
self.hovered = true | |
self.animation:interrupt(false, self.animationQueue) | |
end | |
else | |
if self.hovered then | |
update = true | |
self.hovered = false | |
self.animation:interrupt(true, self.animationQueue) | |
end | |
end | |
return update | |
end | |
} | |
_base_0.__index = _base_0 | |
setmetatable(_base_0, _parent_0.__base) | |
local _class_0 = setmetatable({ | |
__init = function(self) | |
_parent_0.__init(self, 0, 0, 0, 0) | |
self.hovered = false | |
self.needsUpdate = false | |
end, | |
__base = _base_0, | |
__name = "Subscriber", | |
__parent = _parent_0 | |
}, { | |
__index = function(cls, name) | |
local val = rawget(_base_0, name) | |
if val == nil then | |
return _parent_0[name] | |
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 | |
Subscriber = _class_0 | |
end | |
local ProgressBar | |
do | |
local _parent_0 = Subscriber | |
local _base_0 = { | |
clickUpSeek = function(self) | |
local x, y = mp.get_mouse_pos() | |
if self:containsPoint(x, y) then | |
return mp.commandv("seek", x * 100 / self.w, "absolute-percent", "keyframes") | |
end | |
end, | |
stringify = function(self) | |
return table.concat(self.line) | |
end, | |
updateSize = function(self, w, h) | |
_parent_0.updateSize(self, w, h) | |
self.line[2] = ([[%d,%d]]):format(0, h) | |
self.line[8] = ([[%d 0 %d %d 0 %d]]):format(w * 4, w * 4, bar_height * 4, bar_height * 4) | |
return true | |
end, | |
animateHeight = function(self, animation, value) | |
self.line[6] = ([[%g]]):format(value) | |
self.needsUpdate = true | |
end, | |
update = function(self, mouseX, mouseY, mouseOver) | |
local update = _parent_0.update(self, mouseX, mouseY, mouseOver) | |
local position = mp.get_property_number('percent-pos', 0) | |
if position ~= self.lastPosition then | |
update = true | |
self.line[4] = ([[%g]]):format(position) | |
self.lastPosition = position | |
end | |
return update | |
end | |
} | |
_base_0.__index = _base_0 | |
setmetatable(_base_0, _parent_0.__base) | |
local _class_0 = setmetatable({ | |
__init = function(self, animationQueue) | |
self.animationQueue = animationQueue | |
_parent_0.__init(self) | |
self.line = { | |
[[{\an1\bord0\c&HFFFFFF&\p3\pos(]], | |
0, | |
[[)\fscx]], | |
0, | |
[[\fscy]], | |
100, | |
[[}m 0 0 l ]], | |
0 | |
} | |
self.lastPosition = 0 | |
self.animation = Animation(100, 400, 0.25, (function() | |
local _base_1 = self | |
local _fn_0 = _base_1.animateHeight | |
return function(...) | |
return _fn_0(_base_1, ...) | |
end | |
end)()) | |
return mp.add_key_binding("MOUSE_BTN0", (function() | |
local _base_1 = self | |
local _fn_0 = _base_1.clickUpSeek | |
return function(...) | |
return _fn_0(_base_1, ...) | |
end | |
end)()) | |
end, | |
__base = _base_0, | |
__name = "ProgressBar", | |
__parent = _parent_0 | |
}, { | |
__index = function(cls, name) | |
local val = rawget(_base_0, name) | |
if val == nil then | |
return _parent_0[name] | |
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 | |
ProgressBar = _class_0 | |
end | |
local ProgressBarBackground | |
do | |
local _parent_0 = Subscriber | |
local _base_0 = { | |
stringify = function(self) | |
return table.concat(self.line) | |
end, | |
updateSize = function(self, w, h) | |
_parent_0.updateSize(self, w, h) | |
self.line[2] = ([[%d,%d]]):format(0, h) | |
self.line[6] = ([[%d 0 %d %d 0 %d]]):format(w, w, bar_height, bar_height) | |
return true | |
end, | |
animateHeight = function(self, animation, value) | |
self.line[4] = ([[%g]]):format(value) | |
self.needsUpdate = true | |
end, | |
update = function(self, mouseX, mouseY, mouseOver) | |
return _parent_0.update(self, mouseX, mouseY, mouseOver) | |
end | |
} | |
_base_0.__index = _base_0 | |
setmetatable(_base_0, _parent_0.__base) | |
local _class_0 = setmetatable({ | |
__init = function(self, animationQueue) | |
self.animationQueue = animationQueue | |
_parent_0.__init(self) | |
self.line = { | |
[[{\an1\bord0\c&H262626&\p1\pos(]], | |
0, | |
[[)\fscy]], | |
100, | |
[[}m 0 0 l ]], | |
0 | |
} | |
self.animation = Animation(100, 400, 0.25, (function() | |
local _base_1 = self | |
local _fn_0 = _base_1.animateHeight | |
return function(...) | |
return _fn_0(_base_1, ...) | |
end | |
end)()) | |
end, | |
__base = _base_0, | |
__name = "ProgressBarBackground", | |
__parent = _parent_0 | |
}, { | |
__index = function(cls, name) | |
local val = rawget(_base_0, name) | |
if val == nil then | |
return _parent_0[name] | |
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 _parent_0 = Subscriber | |
local _base_0 = { | |
stringify = function(self) | |
if self.passed then | |
self.line[2][7] = [[\c&H262626&]] | |
else | |
self.line[2][7] = [[\c&HFFFFFF&]] | |
end | |
if self.hovered or self.animation.isRegistered then | |
return table.concat({ | |
table.concat(self.line[1]), | |
table.concat(self.line[2]) | |
}, '\n') | |
else | |
return table.concat(self.line[2]) | |
end | |
end, | |
updateSize = function(self, w, h) | |
self.x = math.floor(w * self.position) | |
self.y = h - hover_zone * bar_height | |
self.line[1][2] = ([[%d,%d]]):format(self.x + 10, h - hover_zone - 10) | |
self.line[2][2] = ([[%d,%d]]):format(self.x + 10, h) | |
return true | |
end, | |
animateAlpha = function(self, animation, value) | |
self.line[1][4] = ([[%02X]]):format(value) | |
self.needsUpdate = true | |
end, | |
animateSize = function(self, value) | |
self.line[2][4] = ([[%g]]):format(value * 100 + 100) | |
self.line[2][6] = ([[%g]]):format(value * 300 + 100) | |
end, | |
update = function(self, mouseX, mouseY, mouseOver, position) | |
local update = _parent_0.update(self, mouseX, mouseY, mouseOver) | |
local changed = self.passed | |
self.passed = position > self.position | |
update = update or changed ~= self.passed | |
return update | |
end | |
} | |
_base_0.__index = _base_0 | |
setmetatable(_base_0, _parent_0.__base) | |
local _class_0 = setmetatable({ | |
__init = function(self, animationQueue, title, position, w, h) | |
self.animationQueue, self.position = animationQueue, position | |
_parent_0.__init(self) | |
self.x = math.floor(w * self.position) - 10 | |
self.y = h - hover_zone * bar_height | |
self.w = 20 | |
self.h = hover_zone * bar_height | |
self.line = { | |
{ | |
[[{\an2\bord2\c&H262626&\3c&HFFFFFF\fs30\pos(]], | |
([[%d,%d]]):format(self.x + 10, h - hover_zone - 10), | |
[[)\alpha&H]], | |
[[FF]], | |
([[&}%s]]):format(title) | |
}, | |
{ | |
[[{\an2\bord0\p1\pos(]], | |
([[%d,%d]]):format(self.x + 10, h), | |
[[)\fscx]], | |
100, | |
[[\fscy]], | |
100, | |
[[\c&HFFFFFF&]], | |
[[}m 0 0 l 2 0 2 2 0 2]] | |
} | |
} | |
self.passed = false | |
self.animation = Animation(255, 0, 0.25, (function() | |
local _base_1 = self | |
local _fn_0 = _base_1.animateAlpha | |
return function(...) | |
return _fn_0(_base_1, ...) | |
end | |
end)()) | |
end, | |
__base = _base_0, | |
__name = "ChapterMarker", | |
__parent = _parent_0 | |
}, { | |
__index = function(cls, name) | |
local val = rawget(_base_0, name) | |
if val == nil then | |
return _parent_0[name] | |
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 | |
ChapterMarker = _class_0 | |
end | |
local Chapters | |
do | |
local _parent_0 = Subscriber | |
local _base_0 = { | |
createMarkers = function(self, w, h) | |
self.markers = { } | |
local totalTime = mp.get_property_number('length', 0) | |
local chapters = mp.get_property_native('chapter-list', { }) | |
for _index_0 = 1, #chapters do | |
local chapter = chapters[_index_0] | |
table.insert(self.markers, ChapterMarker(self.animationQueue, chapter.title, chapter.time / totalTime, w, h)) | |
end | |
end, | |
stringify = function(self) | |
return table.concat(self.line, '\n') | |
end, | |
redrawMarkers = function(self) | |
self.line = { } | |
local _list_0 = self.markers | |
for _index_0 = 1, #_list_0 do | |
local marker = _list_0[_index_0] | |
table.insert(self.line, marker:stringify()) | |
end | |
end, | |
updateSize = function(self, w, h) | |
_parent_0.updateSize(self, w, h) | |
local _list_0 = self.markers | |
for _index_0 = 1, #_list_0 do | |
local marker = _list_0[_index_0] | |
marker:updateSize(w, h) | |
end | |
self:redrawMarkers() | |
return true | |
end, | |
animateSize = function(self, animation, value) | |
local _list_0 = self.markers | |
for _index_0 = 1, #_list_0 do | |
local marker = _list_0[_index_0] | |
marker:animateSize(value) | |
end | |
self.needsUpdate = true | |
end, | |
update = function(self, mouseX, mouseY, mouseOver) | |
local update = _parent_0.update(self, mouseX, mouseY, mouseOver) | |
local currentPosition = mp.get_property_number('percent-pos', 0) * 0.01 | |
local _list_0 = self.markers | |
for _index_0 = 1, #_list_0 do | |
local marker = _list_0[_index_0] | |
if marker:update(mouseX, mouseY, mouseOver, currentPosition) then | |
update = true | |
end | |
end | |
if update then | |
self:redrawMarkers() | |
end | |
return update | |
end | |
} | |
_base_0.__index = _base_0 | |
setmetatable(_base_0, _parent_0.__base) | |
local _class_0 = setmetatable({ | |
__init = function(self, animationQueue) | |
self.animationQueue = animationQueue | |
_parent_0.__init(self) | |
self.line = { } | |
self.markers = { } | |
self.animation = Animation(0, 1, 0.25, (function() | |
local _base_1 = self | |
local _fn_0 = _base_1.animateSize | |
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 | |
return _parent_0[name] | |
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 | |
Chapters = _class_0 | |
end | |
local TimeElapsed | |
do | |
local _parent_0 = Subscriber | |
local _base_0 = { | |
updateSize = function(self, w, h) | |
_parent_0.updateSize(self, w, h) | |
self.line[2] = ([[%g,%g]]):format(self.position, self.y + (hover_zone - 4) * bar_height) | |
return true | |
end, | |
animatePos = function(self, animation, value) | |
self.position = value | |
self.line[2] = ([[%g,%g]]):format(self.position, self.y + (hover_zone - 4) * bar_height) | |
self.needsUpdate = true | |
end, | |
update = function(self, mouseX, mouseY, mouseOver) | |
local update = _parent_0.update(self, mouseX, mouseY, mouseOver) | |
local timeElapsed = math.floor(mp.get_property_number('time-pos', 0)) | |
if timeElapsed ~= self.lastTime then | |
update = true | |
self.line[4] = ([[%d:%02d:%02d]]):format(math.floor(timeElapsed / 3600), math.floor(timeElapsed / 60) % 60, timeElapsed % 60) | |
self.lastTime = timeElapsed | |
end | |
return update | |
end | |
} | |
_base_0.__index = _base_0 | |
setmetatable(_base_0, _parent_0.__base) | |
local _class_0 = setmetatable({ | |
__init = function(self, animationQueue) | |
self.animationQueue = animationQueue | |
_parent_0.__init(self) | |
self.line = { | |
[[{\fnSource Sans Pro Semibold\bord2\fs30\pos(]], | |
[[-100,0]], | |
[[)\3c&H262626&\c&HFFFFFF&\an1}]], | |
0 | |
} | |
self.lastTime = -1 | |
self.position = -100 | |
self.animation = Animation(-100, 2, 0.25, (function() | |
local _base_1 = self | |
local _fn_0 = _base_1.animatePos | |
return function(...) | |
return _fn_0(_base_1, ...) | |
end | |
end)(), nil, 0.25) | |
end, | |
__base = _base_0, | |
__name = "TimeElapsed", | |
__parent = _parent_0 | |
}, { | |
__index = function(cls, name) | |
local val = rawget(_base_0, name) | |
if val == nil then | |
return _parent_0[name] | |
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 | |
TimeElapsed = _class_0 | |
end | |
local TimeRemaining | |
do | |
local _parent_0 = Subscriber | |
local _base_0 = { | |
updateSize = function(self, w, h) | |
_parent_0.updateSize(self, w, h) | |
self.line[2] = ([[%g,%g]]):format(self.position, self.y + (hover_zone - 4) * bar_height) | |
return true | |
end, | |
animatePos = function(self, animation, value) | |
self.position = self.w - value | |
self.line[2] = ([[%g,%g]]):format(self.position, self.y + (hover_zone - 4) * bar_height) | |
self.needsUpdate = true | |
end, | |
update = function(self, mouseX, mouseY, mouseOver) | |
local update = _parent_0.update(self, mouseX, mouseY, mouseOver) | |
local timeRemaining = math.floor(mp.get_property_number('playtime-remaining', 0)) | |
if timeRemaining ~= self.lastTime then | |
update = true | |
self.line[4] = ([[–%d:%02d:%02d]]):format(math.floor(timeRemaining / 3600), math.floor(timeRemaining / 60) % 60, timeRemaining % 60) | |
self.lastTime = timeRemaining | |
end | |
return update | |
end | |
} | |
_base_0.__index = _base_0 | |
setmetatable(_base_0, _parent_0.__base) | |
local _class_0 = setmetatable({ | |
__init = function(self, animationQueue) | |
self.animationQueue = animationQueue | |
_parent_0.__init(self, 0, 0, 0, 0) | |
self.line = { | |
[[{\fnSource Sans Pro Semibold\bord2\fs30\pos(]], | |
[[-100,0]], | |
[[)\3c&H262626&\c&HFFFFFF&\an3}]], | |
0 | |
} | |
self.lastTime = -1 | |
self.position = -100 | |
self.animation = Animation(-100, 4, 0.25, (function() | |
local _base_1 = self | |
local _fn_0 = _base_1.animatePos | |
return function(...) | |
return _fn_0(_base_1, ...) | |
end | |
end)(), nil, 0.25) | |
end, | |
__base = _base_0, | |
__name = "TimeRemaining", | |
__parent = _parent_0 | |
}, { | |
__index = function(cls, name) | |
local val = rawget(_base_0, name) | |
if val == nil then | |
return _parent_0[name] | |
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 | |
TimeRemaining = _class_0 | |
end | |
local HoverTime | |
do | |
local _parent_0 = Subscriber | |
local _base_0 = { | |
animateAlpha = function(self, animation, value) | |
self.line[4] = ([[%02X]]):format(value) | |
self.needsUpdate = true | |
end, | |
update = function(self, mouseX, mouseY, mouseOver) | |
local update = _parent_0.update(self, mouseX, mouseY, mouseOver) | |
if mouseX ~= self.lastX or mouseY ~= self.lastY then | |
self.line[2] = ("%g,%g"):format(math.min(self.w - 130, math.max(120, mouseX)), self.y + (hover_zone - 4) * bar_height) | |
self.lastX, self.lastY = mouseX, mouseY | |
local hoverTime = mp.get_property_number('length', 0) * mouseX / self.w | |
if hoverTime ~= self.lastTime and (self.hovered or self.animation.isRegistered) then | |
update = true | |
self.line[6] = ([[%d:%02d:%02d]]):format(math.floor(hoverTime / 3600), math.floor(hoverTime / 60) % 60, hoverTime % 60) | |
self.lastTime = hoverTime | |
end | |
end | |
return update | |
end | |
} | |
_base_0.__index = _base_0 | |
setmetatable(_base_0, _parent_0.__base) | |
local _class_0 = setmetatable({ | |
__init = function(self, animationQueue) | |
self.animationQueue = animationQueue | |
_parent_0.__init(self) | |
self.line = { | |
[[{\fnSource Sans Pro Semibold\bord2\fs26\pos(]], | |
[[-100,0]], | |
[[)\3c&H262626&\c&HFFFFFF&\an2\&H]], | |
[[FF]], | |
[[&}]], | |
0 | |
} | |
self.lastTime = 0 | |
self.lastX = -1 | |
self.lastY = -1 | |
self.position = -100 | |
self.animation = Animation(255, 0, 0.25, (function() | |
local _base_1 = self | |
local _fn_0 = _base_1.animateAlpha | |
return function(...) | |
return _fn_0(_base_1, ...) | |
end | |
end)()) | |
end, | |
__base = _base_0, | |
__name = "HoverTime", | |
__parent = _parent_0 | |
}, { | |
__index = function(cls, name) | |
local val = rawget(_base_0, name) | |
if val == nil then | |
return _parent_0[name] | |
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 | |
HoverTime = _class_0 | |
end | |
local PauseIndicator | |
do | |
local scaleTags | |
local _base_0 = { | |
stringify = function(self) | |
return table.concat(self.line) | |
end, | |
updateSize = function(self, w, h) | |
w, h = 0.5 * w, 0.5 * h | |
self.line[6] = ([[%g,%g]]):format(w, h) | |
self.line[14] = ([[%g,%g]]):format(w, h) | |
return true | |
end, | |
update = function() | |
return true | |
end, | |
animate = function(self, animation, value) | |
local scale = value * 50 + 100 | |
local scaleStr = scaleTags:format(scale, scale) | |
local alphaStr = ("%02X"):format(value * 255) | |
self.line[2] = scaleStr | |
self.line[10] = scaleStr | |
self.line[4] = alphaStr | |
self.line[12] = alphaStr | |
end, | |
destroy = function(self, animation) | |
return self.aggregator:removeSubscriber(self.aggregatorIndex) | |
end | |
} | |
_base_0.__index = _base_0 | |
local _class_0 = setmetatable({ | |
__init = function(self, queue, aggregator, paused) | |
self.aggregator = aggregator | |
local w, h = mp.get_screen_size() | |
w, h = 0.5 * w, 0.5 * h | |
self.line = { | |
[[{\an5\bord0\c&H2D2D2D&]], | |
[[\fscx0\fscy0]], | |
[[\alpha&H]], | |
0, | |
[[&\pos(]], | |
([[%g,%g]]):format(w, h), | |
[[)\p1}]], | |
0, | |
[[{\an5\bord0\c&HFC799E&]], | |
[[\fscx0\fscy0]], | |
[[\alpha&H]], | |
0, | |
[[&\pos(]], | |
([[%g,%g]]):format(w, h), | |
[[)\p1}]], | |
0 | |
} | |
if paused then | |
self.line[8] = "m 15 0 l 60 0 b 75 0 75 0 75 15 l 75 60 b 75 75 75 75 60 75 l 15 75 b 0 75 0 75 0 60 l 0 15 b 0 0 0 0 15 0 m 23 20 l 23 55 33 55 33 20 m 42 20 l 42 55 52 55 52 20\n" | |
self.line[16] = [[m 0 0 l 0 75 m 23 20 l 23 55 33 55 33 20 m 42 20 l 42 55 52 55 52 20 m 75 0 l 75 75]] | |
else | |
self.line[8] = "m 15 0 l 60 0 b 75 0 75 0 75 15 l 75 60 b 75 75 75 75 60 75 l 15 75 b 0 75 0 75 0 60 l 0 15 b 0 0 0 0 15 0 m 23 18 l 23 57 58 37.5\n" | |
self.line[16] = [[m 0 0 l 0 75 m 23 18 l 23 57 58 37.5 m 75 0 l 75 75]] | |
end | |
do | |
local _base_1 = self | |
local _fn_0 = _base_1.animate | |
self.animationCb = function(...) | |
return _fn_0(_base_1, ...) | |
end | |
end | |
do | |
local _base_1 = self | |
local _fn_0 = _base_1.destroy | |
self.finishedCb = function(...) | |
return _fn_0(_base_1, ...) | |
end | |
end | |
queue:registerAnimation(Animation(0, 1, 0.3, self.animationCb, self.finishedCb)) | |
return self.aggregator:addSubscriber(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 | |
local self = _class_0 | |
scaleTags = [[\fscx%g\fscy%g]] | |
PauseIndicator = _class_0 | |
end | |
local Playlist | |
do | |
local _parent_0 = Subscriber | |
local _base_0 = { | |
updateSize = function(self, w, h) | |
_parent_0.updateSize(self, w, h) | |
self.topBox.w = w | |
end, | |
animatePos = function(self, animation, value) | |
self.line[2] = ([[4,%g]]):format(value) | |
self.needsUpdate = true | |
end, | |
updatePlaylistInfo = function(self) | |
local title = mp.get_property('media-title', '') | |
local position = mp.get_property_number('playlist-pos', 0) | |
local total = mp.get_property_number('playlist-count', 1) | |
self.line[4] = ([[%d/%d – %s]]):format(position + 1, total, title) | |
self.needsUpdate = true | |
end, | |
update = function(self, mouseX, mouseY, mouseOver) | |
return _parent_0.update(self, mouseX, mouseY, mouseOver, (self:containsPoint(mouseX, mouseY) or self.topBox:containsPoint(mouseX, mouseY))) | |
end | |
} | |
_base_0.__index = _base_0 | |
setmetatable(_base_0, _parent_0.__base) | |
local _class_0 = setmetatable({ | |
__init = function(self, animationQueue) | |
self.animationQueue = animationQueue | |
_parent_0.__init(self) | |
self.line = { | |
[[{\an7\fnSource Sans Pro Semibold\bord2\fs30\pos(]], | |
[[4,-40]], | |
[[)\3c&H2D2D2D&\c&HFC799E&}]], | |
0 | |
} | |
self.topBox = Rect(0, 0, 0, hover_zone * bar_height) | |
self.animation = Animation(-40, 0, 0.25, (function() | |
local _base_1 = self | |
local _fn_0 = _base_1.animatePos | |
return function(...) | |
return _fn_0(_base_1, ...) | |
end | |
end)(), nil, 0.25) | |
end, | |
__base = _base_0, | |
__name = "Playlist", | |
__parent = _parent_0 | |
}, { | |
__index = function(cls, name) | |
local val = rawget(_base_0, name) | |
if val == nil then | |
return _parent_0[name] | |
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 | |
Playlist = _class_0 | |
end | |
local aggregator = OSDAggregator() | |
local animationQueue = AnimationQueue(aggregator) | |
local progressBar = ProgressBar(animationQueue) | |
local progressBarBackground = ProgressBarBackground(animationQueue) | |
local chapters = Chapters(animationQueue) | |
local timeElapsed = TimeElapsed(animationQueue) | |
local timeRemaining = TimeRemaining(animationQueue) | |
local hoverTime = HoverTime(animationQueue) | |
local playlist = Playlist(animationQueue) | |
aggregator:addSubscriber(progressBarBackground) | |
aggregator:addSubscriber(progressBar) | |
aggregator:addSubscriber(chapters) | |
aggregator:addSubscriber(timeElapsed) | |
aggregator:addSubscriber(timeRemaining) | |
aggregator:addSubscriber(hoverTime) | |
aggregator:addSubscriber(playlist) | |
local notFrameStepping = true | |
local PauseIndicatorWrapper | |
PauseIndicatorWrapper = function(event, paused) | |
if notFrameStepping then | |
return PauseIndicator(animationQueue, aggregator, paused) | |
else | |
if paused then | |
notFrameStepping = true | |
end | |
end | |
end | |
mp.add_key_binding('.', 'mp_progbar_stepforward', function() | |
notFrameStepping = false | |
return mp.commandv('frame_step') | |
end, { | |
repeatable = true | |
}) | |
mp.add_key_binding(',', 'mp_progbar_stepbackward', function() | |
notFrameStepping = false | |
return mp.commandv('frame_back_step') | |
end, { | |
repeatable = true | |
}) | |
mp.observe_property('pause', 'bool', PauseIndicatorWrapper) | |
local initDraw | |
initDraw = function() | |
mp.unregister_event(initDraw) | |
local width, height = mp.get_screen_size() | |
chapters:createMarkers(width, height) | |
return playlist:updatePlaylistInfo() | |
end | |
local fileLoaded | |
fileLoaded = function() | |
return mp.register_event('playback-restart', initDraw) | |
end | |
return mp.register_event('file-loaded', fileLoaded) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment