UP | HOME

Emms-remote :: Interfacing the shell to emms

Table of Contents

Emms is the wounderful Emacs MultiMedia System. It allows the average GNU/Emacs user to manage his/her playlist inside the beloved environment (i mean, emacs).

Emms is able to invoke several mp3 player application (I use mplayer, but it can also handle mpg123, mpg321 and other easily, and ways to invoke other players can be defined in emacs-lisp).

The problem

So, what's the problem if EMMS is so figo ?

The point is that it works like a charm… Inside GNU/Emacs. Although I use GNU/Emacs to carry out a wide variety of tasks, there still are some tasks that requires other application.

Think to Mozilla Firefox, Xpdf, Transmission, aMule, OpenOffice and things like theese. I know emacs is capable of carrying out most of the tasks i've taken as example, but this is an example.

And… This is a trivial one. I use Conky to have some nice statistics and reminders on my desktop. It has some modules to interact with some audio players applications. Emms is not among the players supported. But I want it to be.

So, what to do?

So, let's warm up our Emacs and write some code!

First of all, i have to preface i always run Emacs in daemon mode, for many reasons.

Second, emacsclient provides the -e switch, that allows us to query emacs and make it eval some expressions.

Theese two things are absolutely great, and actually that's enough, we don't need anything else.

An example?

manu@joker:~$ emacsclient -e "(emacs-version)"
"GNU Emacs 23.1.1 (i486-pc-linux-gnu, GTK+ Version 2.18.2)\n of 2009-11-02 on raven, modified by Debian"
manu@joker:~$ 

We can use this syntax for about anything we need. Ok then, let's move on.

Our aim is to be able to:

  • Query the now-playing track title
  • Switch forward to the next track
  • Switch back to the previous track
  • Pause the player
  • Resume the player
  • Stop the player

Reading though the EMMS documentation, i see that the function emms-track-description is what i need to gather information about the track being played currently. Fine.

To switch forward and backward in the playlist, emms itself provides the emms-next and emms-previous functions.

Then, emms-pause toggles state between pause and resume.

Last task is carried out by emms-stop.

The code

The code is pretty straightforward. Anyway, i want to write something "general" to be used in many occasion. Here's how the code looks like at the moment of writing (30/03/2010):

#! /usr/bin/env bash

case "$1" in
    --toggle-pause )
        emacsclient -e "(emms-pause)"
        ;;

    --next )
        emacsclient -e "(emms-next)"
        ;;

    --prev )
        emacsclient -e "(emms-previous)"
        ;;

    --start )
        emacsclient -e "(emms-start)"
        ;;
    
    --stop )
        emacsclient -e "(emms-stop)"
        ;;

    --query )
        emacsclient -e "(emms-track-description (emms-playlist-current-selected-track))" \
            | sed s/\"//g
        ;;

    "")
        echo "Usage: emms-remote --option"
        echo "--toggle-pause : Plays/Pauses EMMS"
        echo "--next : Plays next track in EMMS's Playlist"
        echo "--prev : Plays previous track in EMMS's Playlist"
        echo "--start : Starts EMMS"
        echo "--stop : Stops EMMS"
        ;;

    * )
        exit
        ;;
esac

For a more accurated description of the tool, see: http://git.santoro.tk/?p=emms-remote.git;a=summary.

WM bindings

That's your business. On my laptop running fluxbox, I addes theese lines in my ~/.fluxbox/keys:

### ~/.Bin/Emms-Remote invocation
# file: ~/.fluxbox/keys
Mod4 space :ExecCommand ~/.bin/emms-remote --toggle-pause
Mod4 Down :ExecCommand ~/.bin/emms-remote --stop
Mod4 Up :ExecCommand ~/.bin/emms-remote --start
Mod4 Right :ExecCommand ~/.bin/emms-remote --next
Mod4 Left :ExecCommand ~/.bin/emms-remote --prev

Reloaded fluxbox's configuration, it worked.

Fancy notification

I also like fancy notification. This is achieved via some python code, some elisp expressions and python-libnotify.

Firt, install libnotify and its python bindings. In Debian (I'm running debian squeeze, which is testing at the moment) the packages are:

manu@joker:~$ dpkg -l | grep -i libnotify
ii  libnotify-dev                        0.4.5-1                    sends desktop notifications to a notificatio
ii  libnotify1                           0.4.5-1                    sends desktop notifications to a notificatio
ii  python-notify                        0.1.1-2+b2                 Python bindings for libnotify
manu@joker:~$ 

Then comes the python code:

#! /usr/bin/env python

import sys
import pynotify
from optparse import *

parser = OptionParser()

parser.add_option("-t", "--title", help="title of the notification widget",
                  metavar="TEXT", dest="title")

parser.add_option("-m", "--message", help="message of the notification widget",
                  metavar="MESSAGE", dest="message")

(options, args) = parser.parse_args() 

if pynotify.init("emms-notifier"):
        n = pynotify.Notification(
                options.title, 
                options.message,
                "/usr/share/emacs/23.1/etc/images/icons/hicolor/48x48/apps/emacs.png")
        n.show()
        sys.exit(0)
else:
        print "there was a problem initializing the pynotify module"
        sys.exit(1)

I've saved all this code in ~/.bin/ and added this directory to the $PATH environmental variable.

Now comes the elisp code.

;; system-notify: make a nice notification widget on the screen
(defun system-notify (title message)
  "invoke easy-notify with a title and shows a message"
  (interactive "")
  (start-process-shell-command "*Output*" nil 
                               (concat "easy-notify -t \"" title "\" -m \"" message "\"")))
;; use system-notify with emms
(add-hook 
 'emms-player-started-hook 
 '(lambda ()(system-notify 
             "emms is now playing..." 
             (emms-track-description (emms-playlist-current-selected-track)))))

The first function is a little bit general, and it's useful to make notification of any type. The second expression add a hook to the emms-player-started-hook hook, so that everytime emms begins playing a song, it calls system-notify in the appropriate way and make a nice notification on the right bottom corner of the screen.

Result is something like this:

pics/emms-easy-notify.png

For hints and anything else: santoro@autistici.org.

Enjoy!

Date: 2012-03-11 15:00:45 CET

Author: Emanuele Santoro

Org version 7.6 with Emacs version 23

Validate XHTML 1.0