mirror of https://github.com/mpv-player/mpv
js: implement mp.register_idle
Due to earlier misinterpretation of the Lua docs as if mp.register_idle registers a one-shot callback, the JS docs suggested to use setTimeout. But the behavior and Lua docs are such that it's a repeating callback which fires just before the script thread goes to sleep. Implement it for JS too.
This commit is contained in:
parent
b04f0cad43
commit
9a47023c44
|
@ -67,10 +67,6 @@ Unsupported Lua APIs and their JS alternatives
|
|||
|
||||
``mp.add_periodic_timer(seconds, fn)`` JS: ``id = setInterval(fn, ms)``
|
||||
|
||||
``mp.register_idle(fn)`` JS: ``id = setTimeout(fn)``
|
||||
|
||||
``mp.unregister_idle(fn)`` JS: ``clearTimeout(id)``
|
||||
|
||||
``utils.parse_json(str [, trail])`` JS: ``JSON.parse(str)``
|
||||
|
||||
``utils.format_json(v)`` JS: ``JSON.stringify(v)``
|
||||
|
@ -142,6 +138,10 @@ Otherwise, where the Lua APIs return ``nil`` on error, JS returns ``undefined``.
|
|||
|
||||
``mp.get_wakeup_pipe()``
|
||||
|
||||
``mp.register_idle(fn)``
|
||||
|
||||
``mp.unregister_idle(fn)``
|
||||
|
||||
``mp.enable_messages(level)``
|
||||
|
||||
``mp.register_script_message(name, fn)``
|
||||
|
@ -267,7 +267,7 @@ event loop iteration or at a later event loop iteration. This is true also for
|
|||
intervals - which also never call back twice at the same event loop iteration.
|
||||
|
||||
Additionally, timers are processed after the event queue is empty, so it's valid
|
||||
to use ``setTimeout(fn)`` instead of Lua's ``mp.register_idle(fn)``.
|
||||
to use ``setTimeout(fn)`` as a one-time idle observer.
|
||||
|
||||
CommonJS modules and ``require(id)``
|
||||
------------------------------------
|
||||
|
@ -320,6 +320,10 @@ also print every event which mpv sends to your script:
|
|||
wait = 0;
|
||||
} else {
|
||||
wait = mp.process_timers() / 1000;
|
||||
if (wait != 0) {
|
||||
mp.notify_idle_observers();
|
||||
wait = mp.peek_timers_wait() / 1000;
|
||||
}
|
||||
}
|
||||
} while (mp.keep_running);
|
||||
}
|
||||
|
@ -339,5 +343,12 @@ if there are such (event handlers, property observers, script messages, etc).
|
|||
and returns the duration in ms till the next due timer (possibly 0), or -1 if
|
||||
there are no pending timers. Must not be called recursively.
|
||||
|
||||
``mp.notify_idle_observers()`` calls back the idle observers, which we do when
|
||||
we're about to sleep (wait != 0), but the observers may add timers or take
|
||||
non-negligible duration to complete, so we re-calculate ``wait`` afterwards.
|
||||
|
||||
``mp.peek_timers_wait()`` returns the same values as ``mp.process_timers()``
|
||||
but without doing anything. Invalid result if called from a timer callback.
|
||||
|
||||
Note: ``exit()`` is also registered for the ``shutdown`` event, and its
|
||||
implementation is a simple ``mp.keep_running = false``.
|
||||
|
|
|
@ -17,7 +17,7 @@ function new_cache() {
|
|||
}
|
||||
|
||||
/**********************************************************************
|
||||
* event handlers, property observers, client messages, hooks
|
||||
* event handlers, property observers, idle, client messages, hooks
|
||||
*********************************************************************/
|
||||
var ehandlers = new_cache() // items of event-name: array of {maybe cb: fn}
|
||||
|
||||
|
@ -54,6 +54,31 @@ function dispatch_event(e) {
|
|||
}
|
||||
}
|
||||
|
||||
// ----- idle observers -----
|
||||
var iobservers = [], // array of callbacks
|
||||
ideleted = false;
|
||||
|
||||
mp.register_idle = function(fn) {
|
||||
iobservers.push(fn);
|
||||
}
|
||||
|
||||
mp.unregister_idle = function(fn) {
|
||||
iobservers.forEach(function(f, i) {
|
||||
if (f == fn)
|
||||
delete iobservers[i]; // -> same length but [more] sparse
|
||||
});
|
||||
ideleted = true;
|
||||
}
|
||||
|
||||
function notify_idle_observers() {
|
||||
// forEach and filter skip deleted items and newly added items
|
||||
iobservers.forEach(function(f) { f() });
|
||||
if (ideleted) {
|
||||
iobservers = iobservers.filter(function() { return true });
|
||||
ideleted = false;
|
||||
}
|
||||
}
|
||||
|
||||
// ----- property observers -----
|
||||
var next_oid = 1,
|
||||
observers = new_cache(); // items of id: fn
|
||||
|
@ -254,6 +279,10 @@ function peek_wait(arr) {
|
|||
return arr.length ? Math.max(0, arr[arr.length - 1].when - now()) : -1;
|
||||
}
|
||||
|
||||
function peek_timers_wait() {
|
||||
return peek_wait(timers); // must not be called while in process_timers
|
||||
}
|
||||
|
||||
// Callback all due non-canceled timers which were inserted before calling us.
|
||||
// Returns wait in ms till the next timer (possibly 0), or -1 if nothing pends.
|
||||
function process_timers() {
|
||||
|
@ -481,6 +510,8 @@ mp.get_time = function() { return mp.get_time_ms() / 1000 };
|
|||
mp.utils.getcwd = function() { return mp.get_property("working-directory") };
|
||||
mp.dispatch_event = dispatch_event;
|
||||
mp.process_timers = process_timers;
|
||||
mp.notify_idle_observers = notify_idle_observers;
|
||||
mp.peek_timers_wait = peek_timers_wait;
|
||||
|
||||
mp.get_opt = function(key, def) {
|
||||
var v = mp.get_property_native("options/script-opts")[key];
|
||||
|
@ -533,13 +564,17 @@ mp.register_script_message("key-binding", dispatch_key_binding);
|
|||
|
||||
g.mp_event_loop = function mp_event_loop() {
|
||||
var wait = 0; // seconds
|
||||
do { // distapch events as long as they arrive, then do the timers
|
||||
do { // distapch events as long as they arrive, then do the timers/idle
|
||||
var e = mp.wait_event(wait);
|
||||
if (e.event != "none") {
|
||||
dispatch_event(e);
|
||||
wait = 0; // poll the next one
|
||||
} else {
|
||||
wait = process_timers() / 1000;
|
||||
if (wait != 0) {
|
||||
notify_idle_observers(); // can add timers -> recalculate wait
|
||||
wait = peek_timers_wait() / 1000;
|
||||
}
|
||||
}
|
||||
} while (mp.keep_running);
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue