mpv-player / mpv

🎥 Command line video player
https://mpv.io
Other
28.62k stars 2.92k forks source link

Undeprecate `mp.get_wakeup_pipe()` #14933

Open ruihe774 opened 1 month ago

ruihe774 commented 1 month ago

Expected behavior of the wanted feature

I propose to revert the deprecation of the Lua API mp.get_wakeup_pipe() and its underlying C API mpv_get_wakeup_pipe(). mp.get_wakeup_pipe() is the only method to implement a custom event loop in the Lua script. It is useful when a scripter wants to wait for multiple event sources. (In contrast, mp.wait_event() can only listen to events from mpv, not external event sources.)

The deprecation message of mpv_get_wakeup_pipe() suggests to use mpv_set_wakeup_callback(); however, it is not possible to implement a similar alternative for Lua. The callback set by mpv_set_wakeup_callback() can be called in arbitrary threads, and can be called when Lua runtime is concurrently running, which breaks the single-thread assumption of Lua runtime.

Alternative behavior of the wanted feature

No response

Log File

No response

Sample Files

No response

na-na-hi commented 1 month ago

mp.get_wakeup_pipe() is the only method to implement a custom event loop in the Lua script.

Not really. You can always do periodic polling. Either by adding a periodic timer with mp.add_periodic_timer() which polls external events, or polling mpv and external events explicitly in a loop.

Also there is no reason to undeprecate mpv_get_wakeup_pipe() C API, since it's trivial to write a wrapper over mpv_set_wakeup_callback() to do the same thing, and it can be more powerful than a pipe. It also doesn't work on Windows, so the use is limited even if the Lua API is undeprecated.

ruihe774 commented 1 month ago

Not really. You can always do periodic polling. Either by adding a periodic timer with mp.add_periodic_timer() which polls external events, or polling mpv and external events explicitly in a loop.

Yes, but suboptimal.

sfan5 commented 1 month ago

Isn't the usability of this rubbish? How do you read from an fd from Lua? Not possible with the stdlib AFAIK.

ruihe774 commented 1 month ago

Isn't the usability of this rubbish? How do you read from an fd from Lua? Not possible with the stdlib AFAIK.

Yes, not possible with the stdlib.

However, LuaJIT FFI can be used to call read, poll, etc, with which it is possible to implement a custom event loop (I actually wrote one); or existing wrappers like luv can be used, which is easier.

na-na-hi commented 1 month ago

If you're using FFI already, it should be possible to create a separate therad in lua which basically implements mpv_get_wakeup_pipe(), right? Does the "single thread assumption" apply to threads created this way?

na-na-hi commented 1 month ago

Also if using multiple scripts is an option, the requested feature can be achieved by adding dedicated scripts to listen to mpv and external events and then sending them to the processing script with script-message-to.

ruihe774 commented 1 month ago

it should be possible to create a separate therad in lua which basically implements mpv_get_wakeup_pipe(), right?

It's not possible. Creating a separate thread is not allowed in Lua. Lua has no concept about threads. The global state in the lua runtime is not thread-safe. Calling lua functions from multiple threads will corrupt the runtime.

e.g., the following is invalid in lua:

-- start_thread is pthread_create or similar things
start_thread(function()
  -- this function will be called in another thread
  -- this corrupts the lua runtime
end)

run_my_event_loop()
ruihe774 commented 1 month ago

Also if using multiple scripts is an option, the requested feature can be achieved by adding dedicated scripts to listen to mpv and external events and then sending them to the processing script with script-message-to.

Sounds possible. But I'm afraid the dedicated script that listens to external events still has to have a way to listen to some fundamental mpv events like shutdown, otherwise it cannot even stop when mpv is going to quit.

ruihe774 commented 1 month ago

FWIW, it is actually possible to create a (named) pipe in Windows to dispatch events, which is what libuv does. I have the idea to make mpv_get_wakeup_pipe() cross-platform.

na-na-hi commented 1 month ago

It's not possible. Creating a separate thread is not allowed in Lua. Lua has no concept about threads. The global state in the lua runtime is not thread-safe. Calling lua functions from multiple threads will corrupt the runtime.

The function running in the separate thread can come from FFI which doesn't touch Lua runtime.

But I'm afraid the dedicated script that listens to external events still has to have a way to listen to some fundamental mpv events like shutdown, otherwise it cannot even stop when mpv is going to quit.

Even if you insist infinite wait timeout (otherwise it can check for termination after each timeout), the mpv event listening script can send the shutdown notification to one of the fd that external event script is listening.

ruihe774 commented 1 month ago

The function running in the separate thread can come from FFI which doesn't touch Lua runtime.

Yes, C functions are allowed. But limited things can be done without writing the C function by myself. And consider the signature of the C function must confirm the signature required by pthread_create (void *(*start_routine)(void *)), I really doubt it is doable.

ffi.C.pthread_create(
  thread,
  attr,
  ffi.C.thread_routine,
  arg,
)

-- ffi.C.thread_routine must be a function pointer of `void *(*start_routine)(void *)`
-- we have to implement it in C, which is out of the scope of Lua scripting.

the mpv event listening script can send the shutdown notification to one of the fd that external event script is listening.

Sure.