mpv.el icon indicating copy to clipboard operation
mpv.el copied to clipboard

Add the ability to connect to running MPV processes

Open ghost opened this issue 2 years ago • 9 comments

It'd be useful to be able to control MPV processes which are not necessarily started with mpv-start, for example by hooking into the EMMS mpv process given by the emms-player-mpv-proc variable. Once this is done, allowing users to select what MPV process they want to manipulate would be a plus.

ghost avatar May 10 '22 15:05 ghost

Thanks sharing for your idea. I'm not sure whether that is feasible in all cases. It could probably be made to work if mpv has already been started with --input-ipc-server (which used to be called --input-unix-socket). Then mpv.el could try to connect to that socket instead of spawning mpv itself.

kljohann avatar May 14 '22 20:05 kljohann

Hey @kljohann, just wanted to let you know I gave this a shot in my personal setup specifically for EMMS, as I don't have any other use case atm. I found that defining the following function, which is very similar to mpv-start:

(defun my-mpv-connect-to-emms-proc ()
  "Connect to a running EMMS MPV process."
  (interactive)
  (mpv-kill)
  (setq mpv--process emms-player-mpv-proc)
  (set-process-query-on-exit-flag mpv--process nil)
  (set-process-sentinel
   mpv--process
   (lambda (p _e)
     (when (memq (process-status p) '(exit signal))
       (mpv-kill)
       (run-hooks 'mpv-on-exit-hook))))
  (setq mpv--queue (tq-create (make-network-process
                               :name "mpv-socket"
                               :family 'local
                               :service emms-player-mpv-ipc-socket)))
  (set-process-filter
   (tq-process mpv--queue)
   (lambda (_proc string)
     (mpv--tq-filter mpv--queue string)))
  (run-hooks 'mpv-on-start-hook)
  t)

Along with an advice to mpv-kill as follows:

(defun my-mpv-kill ()
  "Kills the mpv process unless this is not currently `emms-player-mpv-proc'."
  (interactive)
  (when (equal mpv--process
               emms-player-mpv-proc)
    (emms-stop))
  (when mpv--queue
    (tq-close mpv--queue))
  (when (and (mpv-live-p)
             (not (equal mpv--process
                         emms-player-mpv-proc)))
    (kill-process mpv--process))
  (with-timeout
      (0.5 (error "Failed to kill mpv"))
    (while (and (mpv-live-p)
                (not (equal mpv--process
                            emms-player-mpv-proc)))
      (sleep-for 0.05)))
  (setq mpv--process nil)
  (setq mpv--queue nil))

(advice-add #'mpv-kill :override #'my-mpv-kill)

Allowed me to connect to a running EMMS mpv process (invoking my-mpv-connect-to-emms-proc after starting to play a track with EMMS) and then stop its playback once I open other URLs or files with mpv-start. However, I could not reuse the IPC network process emms-player-mpv-ipc-proc as defined here and instead had to create a new one, otherwise when mpv-kill was invoked it would kill the EMMS IPC connection and not allow me to play any more tracks with it afterwards. I'm not sure why this is the case, as if I manually (through M-x list-processes) kill either the process emms-player-mpv-proc or the IPC connection emms-player-mpv-ipc-proc, a new EMMS mpv IPC connection is established and I can play tracks again. Thus, the approach I've currently taken involves essentially not killing those processes.

I'm curious I've you've ever used EMMS and what do you think we could do to improve this, and maybe abstract it away for arbitrary MPV processes started with an IPC socket.

ghost avatar Jul 06 '22 15:07 ghost

Thanks for the update! I don't use EMMS myself, so I did not know that it already enables the IPC server in the spawned mpv process. Opening another connection instead of hooking into the network process created by EMMS sounds like the right thing to do. The connect-to-IPC part of mpv-start could be split out for this purpose. But, as you are probably aware, the current implementation of mpv.el assumes that a single mpv process is spawned, which it controls exclusively. For this reason mpv-start tries to clean up any previous process via mpv-kill. (IIRC mpv-kill is also called in the process sentinel, to clean up the state variables in Emacs when mpv is terminated.) mpv.el could be changed to allow a nil mpv--process (with a non-nil mpv--queue), which would mean that the mpv process controlled via IPC was not spawned by mpv.el and should not be killed. The connect-to-IPC function would still kill any mpv process spawned by mpv.el before connecting to a different instance.

kljohann avatar Aug 01 '22 09:08 kljohann

@kljohann: Thank you for a great tool! I love that you've included all the good stuff, including mpv-set-ab-loop. My toolkit for learning new songs is now complete! @efimerspan: I'm curious to know why you need such functionality - are the emms commands themselves not comprehensive enough?

kinleyd avatar Jan 09 '23 10:01 kinleyd

@kinleyd : Yes, there are many lacking features in EMMS in comparison to mpv.el in regards to playback. After submitting some patches to do with chapter selection and chapter looping, I came to the realization that it only made sense for me to leverage this package as my global system player and use EMMS only as a local music library interface and for tagging and playlist management purposes.

ghost avatar Jan 10 '23 08:01 ghost

@kinleyd : Yes, there are many lacking features in EMMS in comparison to mpv.el in regards to playback. After submitting some patches to do with chapter selection and chapter looping, I came to the realization that it only made sense for me to leverage this package as my global system player and use EMMS only as a local music library interface and for tagging and playlist management purposes.

I've been playing around with mpv and emms, and I now see how useful it would be to be able to connect to a mpv process started by emms. Since I am in the habit of having an emms playlist window always open, such a feature would save me several keystrokes opening a playlist with mpv. I am a bit tied up just now, but I will definitely explore this space when I'm free.

kinleyd avatar Jan 12 '23 09:01 kinleyd

I had some free time today and I tried out your solution - it works just fine.

I've added emms-mark-mode-map shortkeys 'c' to connect to the running emms socket, 'l' to toggle mpv-set-ab-loop and 'x' for mpv-speed-set. It works nicely on an emms playlist as those features do on the mpv gui. Only mpv-playlist-next and -prev don't work, which isn't a problem as we have emms-next and -previous.

I'm chuffed, and thank you!

kinleyd avatar Jan 14 '23 11:01 kinleyd

That's great to hear; maybe for now this issue can serve as a hint for others that want to accomplish this? (Until I get around to look into the changes proposed above: https://github.com/kljohann/mpv.el/issues/24#issuecomment-1200960871) Thank you both for sharing your use cases. EMMS sounds neat, for those with a local music library.

kljohann avatar Jan 28 '23 19:01 kljohann

That's great to hear; maybe for now this issue can serve as a hint for others that want to accomplish this?

Oh for sure! In addition to all its other features, for me getting mpv to work on emms sessions is fantastic. And mpv also integrates well with org links. I'm pleased to have org links to often referenced videos in my local library.

kinleyd avatar Jan 29 '23 11:01 kinleyd