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.
Showing the changes to player/javascript (1 of 2 files). Show all
Unified · Split
| @@ -17,7 +17,7 @@ function new_cache() { · 16 unmodified lines | |||
| 17 | } | 17 | } |
| 18 | 18 | ||
| 19 | /********************************************************************** | 19 | /********************************************************************** |
| 20 | * event handlers, property observers, client messages, hooks | 20 | * event handlers, property observers, idle, client messages, hooks |
| 21 | *********************************************************************/ | 21 | *********************************************************************/ |
| 22 | var ehandlers = new_cache() // items of event-name: array of {maybe cb: fn} | 22 | var ehandlers = new_cache() // items of event-name: array of {maybe cb: fn} |
| 23 | 23 | ||
| @@ -54,6 +54,31 @@ function dispatch_event(e) { · 30 unmodified lines | |||
| 54 | } | 54 | } |
| 55 | } | 55 | } |
| 56 | 56 | ||
| 57 | // ----- idle observers ----- | ||
| 58 | var iobservers = [], // array of callbacks | ||
| 59 | ideleted = false; | ||
| 60 | |||
| 61 | mp.register_idle = function(fn) { | ||
| 62 | iobservers.push(fn); | ||
| 63 | } | ||
| 64 | |||
| 65 | mp.unregister_idle = function(fn) { | ||
| 66 | iobservers.forEach(function(f, i) { | ||
| 67 | if (f == fn) | ||
| 68 | delete iobservers[i]; // -> same length but [more] sparse | ||
| 69 | }); | ||
| 70 | ideleted = true; | ||
| 71 | } | ||
| 72 | |||
| 73 | function notify_idle_observers() { | ||
| 74 | // forEach and filter skip deleted items and newly added items | ||
| 75 | iobservers.forEach(function(f) { f() }); | ||
| 76 | if (ideleted) { | ||
| 77 | iobservers = iobservers.filter(function() { return true }); | ||
| 78 | ideleted = false; | ||
| 79 | } | ||
| 80 | } | ||
| 81 | |||
| 57 | // ----- property observers ----- | 82 | // ----- property observers ----- |
| 58 | var next_oid = 1, | 83 | var next_oid = 1, |
| 59 | observers = new_cache(); // items of id: fn | 84 | observers = new_cache(); // items of id: fn |
| @@ -254,6 +279,10 @@ function peek_wait(arr) { · 194 unmodified lines | |||
| 254 | return arr.length ? Math.max(0, arr[arr.length - 1].when - now()) : -1; | 279 | return arr.length ? Math.max(0, arr[arr.length - 1].when - now()) : -1; |
| 255 | } | 280 | } |
| 256 | 281 | ||
| 282 | function peek_timers_wait() { | ||
| 283 | return peek_wait(timers); // must not be called while in process_timers | ||
| 284 | } | ||
| 285 | |||
| 257 | // Callback all due non-canceled timers which were inserted before calling us. | 286 | // Callback all due non-canceled timers which were inserted before calling us. |
| 258 | // Returns wait in ms till the next timer (possibly 0), or -1 if nothing pends. | 287 | // Returns wait in ms till the next timer (possibly 0), or -1 if nothing pends. |
| 259 | function process_timers() { | 288 | function process_timers() { |
| @@ -481,6 +510,8 @@ mp.get_time = function() { return mp.get_time_ms() / 1000 }; · 221 unmodified lines | |||
| 481 | mp.utils.getcwd = function() { return mp.get_property("working-directory") }; | 510 | mp.utils.getcwd = function() { return mp.get_property("working-directory") }; |
| 482 | mp.dispatch_event = dispatch_event; | 511 | mp.dispatch_event = dispatch_event; |
| 483 | mp.process_timers = process_timers; | 512 | mp.process_timers = process_timers; |
| 513 | mp.notify_idle_observers = notify_idle_observers; | ||
| 514 | mp.peek_timers_wait = peek_timers_wait; | ||
| 484 | 515 | ||
| 485 | mp.get_opt = function(key, def) { | 516 | mp.get_opt = function(key, def) { |
| 486 | var v = mp.get_property_native("options/script-opts")[key]; | 517 | var v = mp.get_property_native("options/script-opts")[key]; |
| @@ -533,13 +564,17 @@ mp.register_script_message("key-binding", dispatch_key_binding); · 46 unmodified lines | |||
| 533 | 564 | ||
| 534 | g.mp_event_loop = function mp_event_loop() { | 565 | g.mp_event_loop = function mp_event_loop() { |
| 535 | var wait = 0; // seconds | 566 | var wait = 0; // seconds |
| 536 | do { // distapch events as long as they arrive, then do the timers | 567 | do { // distapch events as long as they arrive, then do the timers/idle |
| 537 | var e = mp.wait_event(wait); | 568 | var e = mp.wait_event(wait); |
| 538 | if (e.event != "none") { | 569 | if (e.event != "none") { |
| 539 | dispatch_event(e); | 570 | dispatch_event(e); |
| 540 | wait = 0; // poll the next one | 571 | wait = 0; // poll the next one |
| 541 | } else { | 572 | } else { |
| 542 | wait = process_timers() / 1000; | 573 | wait = process_timers() / 1000; |
| 574 | if (wait != 0) { | ||
| 575 | notify_idle_observers(); // can add timers -> recalculate wait | ||
| 576 | wait = peek_timers_wait() / 1000; | ||
| 577 | } | ||
| 543 | } | 578 | } |
| 544 | } while (mp.keep_running); | 579 | } while (mp.keep_running); |
| 545 | }; | 580 | }; |