1
mirror of https://github.com/mpv-player/mpv synced 2024-10-02 16:25:33 +02:00

lua: add a timer API

This commit is contained in:
wm4 2014-02-10 21:07:23 +01:00
parent 206616b697
commit 92a004bf87

View File

@ -63,6 +63,69 @@ local function script_dispatch(event)
end
end
local timers = {}
-- Install a one-shot timer. Once the given amount of seconds has passed from
-- now, the callback will be called as cb(), and the timer is removed.
function mp.add_timeout(seconds, cb)
local t = mp.add_periodic_timer(seconds, cb)
t.oneshot = true
return t
end
-- Install a periodic timer. It works like add_timeout(), but after cb() is
-- called, the timer is re-added.
function mp.add_periodic_timer(seconds, cb)
local t = {
timeout = seconds,
cb = cb,
oneshot = false,
next_deadline = mp.get_timer() + seconds,
}
timers[t] = t
return t
end
function mp.cancel_timer(t)
if t then
timers[t] = nil
end
end
-- Return the timer that expires next.
local function get_next_timer()
local best = nil
for t, _ in pairs(timers) do
if (best == nil) or (t.next_deadline < best.next_deadline) then
best = t
end
end
return best
end
-- Run timers that have met their deadline.
-- Return: next absolute time a timer expires as number, or nil if no timers
local function process_timers()
while true do
local timer = get_next_timer()
if not timer then
return
end
local wait = timer.next_deadline - mp.get_timer()
if wait > 0 then
return wait
else
if timer.oneshot then
timers[timer] = nil
end
timer.cb()
if not timer.oneshot then
timer.next_deadline = mp.get_timer() + timer.timeout
end
end
end
end
-- used by default event loop (mp_event_loop()) to decide when to quit
mp.keep_running = true
@ -93,21 +156,27 @@ package.loaded["mp"] = mp
package.loaded["mp.msg"] = mp.msg
_G.mp_event_loop = function()
wait = 0
local more_events = true
mp.suspend()
while mp.keep_running do
-- Drop all locks - important especially if an error happened while
-- locked, and the error was handled, but the lock not dropped.
local wait = process_timers()
if wait == nil then
wait = 1e20 -- infinity for all practical purposes
end
if more_events then
wait = 0
end
-- Resume playloop - important especially if an error happened while
-- suspended, and the error was handled, but no resume was done.
if wait > 0 then
mp.resume("all")
end
local e = mp.wait_event(wait)
if e.event == "none" then
wait = 1e20
else
-- Empty the event queue while suspended; otherwise, each
-- event will keep us waiting until the core suspends again.
mp.suspend()
wait = 0
-- Empty the event queue while suspended; otherwise, each
-- event will keep us waiting until the core suspends again.
mp.suspend()
more_events = (e.event ~= "none")
if more_events then
local handler = event_handlers[e.event]
if handler then
handler(e)