summaryrefslogtreecommitdiffstats
path: root/player
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2014-02-10 21:07:23 +0100
committerwm4 <wm4@nowhere>2014-02-10 21:07:23 +0100
commit92a004bf8746ebe3f0f4288f645acd1549002029 (patch)
treee0de79f04df8ab1f95f67b9f6b06e14718a8a69e /player
parent206616b697672d973b24330af9b094ac851f7ca4 (diff)
downloadmpv-92a004bf8746ebe3f0f4288f645acd1549002029.tar.bz2
mpv-92a004bf8746ebe3f0f4288f645acd1549002029.tar.xz
lua: add a timer API
Diffstat (limited to 'player')
-rw-r--r--player/lua/defaults.lua89
1 files changed, 79 insertions, 10 deletions
diff --git a/player/lua/defaults.lua b/player/lua/defaults.lua
index 7dca478252..88270253c8 100644
--- a/player/lua/defaults.lua
+++ b/player/lua/defaults.lua
@@ -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)