Previous: Simple Player for `play', Up: Extending Emms

19.3 More Complex Player

The most players you use will be simple players so you don't need to read this chapter. But if you are curious how you can use (almost) every player in emms read further...

In this chapter we will use mpg321 to construct a player that actually can pause a track, restart it and show rest time. We won't implement all of that, but after that chapter you will know how to define it.

The command define-emms-simple-player is just a abstraction layer for define-emms-player, which is a little bit more complicated but much more powerful!

     (define-emms-player "emms-mpg321-remote"
       :start 'emms-mpg321-remote-start
       :stop 'emms-mpg321-remote-stop
       :playablep 'emms-mpg321-remote-playable-p)

So, that is almost all! define-emms-player takes a minimum of three arguments. The first is the name of the player. The rest are methods with functions to call. Three methods are required: start, stop and playable. Start says Emms how to start a track (sic!), stop how to stop a player and playablep should return non-nil if the player can play the track.

So we just need these three functions to get our mpg321-remote:

First we code the start function. We will check if there's a open process and start one otherwise. Then we send a string to the process with the filename and set a filter.

     (defun emms-mpg321-remote-start ()
       (unless (get-process ``mpg321-remote'')
         (setq emms-mpg321-remote-process
               (start-process "mpg321-remote-process"
                              "*mpg321*" "mpg321" "-R" "abc"))
       (process-send-string "mpg321-remote-process"
                            (concat "l " (emms-track-name track)))
       (set-process-filter emms-mpg321-remote-process 'emms-mpg321-remote-filter)))

We need the filter, as mpg321-remote won't quit after playing the track as the simple player do. We wait until the process sends the output “(at-sign)P 0” (the signal of mpg321 that the song ended) to the filter and call emms-mpg321-remote-stop.

     (defun emms-mpg321-remote-filter (process output)
       (when (string-match "(at-sign)P 0" output)

emms-mpg321-remote-stop won't do anything interesting. It just test if there are other files to play and close the process otherwise.

     (defun emms-mpg321-remote-stop ()
       (unless emms-playlist
         (process-send-string "mpg321-remote-process" "Q\n"))

And to make that a playable example I also added emms-mpg321-remote-playablep, which I really just steal from emms-player-simple.el

     (defun emms-mpg321-remote-playablep (track)
            "Return non-nil when we can play this track."
            (and (eq 'file (emms-track-type track))

Now we have a ready player and we could add commands like emms-mpg321-remote-pause for example.