subed icon indicating copy to clipboard operation
subed copied to clipboard

How to read a property from mpv

Open notevenaperson opened this issue 3 years ago • 4 comments

Mpv's JSON IPC documentation describes getting replies, such as with the command get_property. Browsing in subed's code for examples, I was surprised subed doesn't rely on reading properties to work, rather its reply handling seems to be built around events (subed-mpv--client-filter and subed-mpv--client-handle-*). In summary I couldn't find examples of getting a property from mpv, so I'm asking here how to do that.

An extension I'm making to the subed package needs to read a few properties from mpv. subed-mpv--client-send can send commands to the JSON IPC, but I just can't figure out how to send a command and see the reply, or e.g. put in a variable.

To give some more background, this is a function in what I'm working on. For now, the function get_property is a placeholder.

(defun subed-mpv--extract-current ()
  "This function returns the full text of an embedded subtitle track currently selected in mpv.
   I made this because embedded subs are very common, and I don't want to extract them manually
   just to be able to see the file in Emacs."
  (let ((trackno (get_property "current-tracks/sub/ff-index"))
        (subformat (get_property "current-tracks/sub/codec"))
        (container-path (get_property "path")))
    (shell-command-to-string
        (concat
            "ffmpeg -nostdin -loglevel error -i " container-path
            " -c:s copy -map :" trackno " -f " subformat " pipe:"))))

notevenaperson avatar Mar 21 '22 13:03 notevenaperson

[Don't believe anything I say. It's been a long time since I worked on subed or wrote any Elisp.]

I don't think you can do that easily. subed communicates asynchronously with mpv, meaning it sends off a command and immediately continues whatever it was doing, and a callback function is called when the return value arrived.

You would have to come up with a callback system and call subed-mpv--get-property (new function you have to write) with the property name and a callback. The callback would be registered in a global variable, and subed-mpv--client-handle-event would call it when it gets the property value.

Another way would be to write subed-mpv--client-send-synchronously, which would send the command, wait for the return value and return it. Maybe Elisp has something like process-send-string that blocks until the response arrives. Otherwise, you would have to tell subed-mpv--client-handle-event that you are waiting for something and to notify you when it's there.

Have fun! :)

rndusr avatar Mar 21 '22 15:03 rndusr

Do you want to take advantage of the subed-mpv-video-file variable for getting the path, at least? Maybe you can query it outside the mpv process and just ask the user which subtitle to use. I haven't figured out a good pattern for the other things you want to do yet, sorry.

sachac avatar Apr 17 '22 01:04 sachac

mpv.el (which subed doesn't use) has a mpv-run-command that blocks while waiting for a response. I wonder if we can use something like that...

sachac avatar Apr 17 '22 01:04 sachac

https://github.com/kljohann/mpv.el/blob/master/mpv.el#L166=

Nice find! That seems to do exactly what is needed. Looks like cl-block is what we should use.

rndusr avatar Apr 17 '22 06:04 rndusr