Command Rhythmbox from Emacs
09 Jul 2015I might have mentioned before that I'm using GNU/Linux on all of my
computers. The particular flavor is Ubuntu, although it shouldn't
matter much, since I can count the graphical applications that I use
at all, besides Emacs, on one hand. They are: Firefox, Evince,
Rhythmbox and VLC. Of course, as most true Emacs-ers, I strive to
reduce this number to zero. So I got quite excited when I saw
helm-rhythmbox show up in
my package list. It works great: you can play and enqueue tracks with
completion without leaving Emacs. Big thanks to
@mrBliss, and, of course, the authors
for dbus.el
which makes interaction with D-Bus possible through
Elisp.
I'm not as big a fan of Helm as I used to be, so I quickly implemented an Ivy equivalent:
(defun counsel-rhythmbox-enqueue-song (song)
"Let Rhythmbox enqueue SONG."
(let ((service "org.gnome.Rhythmbox3")
(path "/org/gnome/Rhythmbox3/PlayQueue")
(interface "org.gnome.Rhythmbox3.PlayQueue"))
(dbus-call-method :session service path interface
"AddToQueue" (rhythmbox-song-uri song))))
;;;###autoload
(defun counsel-rhythmbox ()
"Choose a song from the Rhythmbox library to play or enqueue."
(interactive)
(unless (require 'helm-rhythmbox nil t)
(error "Please install `helm-rhythmbox'"))
(unless rhythmbox-library
(rhythmbox-load-library)
(while (null rhythmbox-library)
(sit-for 0.1)))
(ivy-read "Rhythmbox: "
(helm-rhythmbox-candidates)
:action
'(1
("Play song" helm-rhythmbox-play-song)
("Enqueue song" counsel-rhythmbox-enqueue-song))))
I listed the whole code just to show how easy it is to interact with
D-Bus, and also to show-off the shiny new multi-action interface of
ivy-read
. Besides being discoverable via C-o, the
multi-action interface is extensible as well. Here's how to add a
"Dequeue" action without touching the original code:
(defun counsel-rhythmbox-dequeue-song (song)
"Let Rhythmbox dequeue SONG."
(let ((service "org.gnome.Rhythmbox3")
(path "/org/gnome/Rhythmbox3/PlayQueue")
(interface "org.gnome.Rhythmbox3.PlayQueue"))
(dbus-call-method :session service path interface
"RemoveFromQueue" (rhythmbox-song-uri song))))
(ivy-set-actions
'counsel-rhythmbox
'(("Dequeue song" counsel-rhythmbox-dequeue-song)))
Very simple, counsel-rhythmbox-dequeue-song
is a clone of
counsel-rhythmbox-enqueue-song
with only the method change from
AddToQueue
to RemoveFromQueue
(I blind-guessed the name, but there
should be a reference somewhere). If you got tired of having a whole
three actions to choose from, you can revert to the initial two with:
(ivy-set-actions 'counsel-rhythmbox nil)
And here's how the updated C-o option panel now looks like:
A bit of descriptions:
- j moves to the next one of the 18 current candidates.
- k moves to the previous candidate.
- h moves to the first candidate.
- l moves to the last candidate.
- g calls the current action without exiting.
- d calls the current action and exits.
- s moves to the next action.
- w moves to the previous action.
- i and C-o close the options panel without exiting.
- o closes the panel and exits.
Similarly to hydra
, each action has a short docstring, like "Play
song"
that should describe what it does. Here are a few usage
scenarios:
- If I wanted to play the first song and enqueue the third and the sixth and exit the minibuffer, I would press gsjjgjjjd.
- If I wanted to play the third and enqueue all the following, I would press jjgsjcjjjjjjjjjjjo. The many j is just me holding j until the selection reaches the end, then I simply exit without doing anything else by pressing o. The way c works is that it toggles the "calling" state - a state where the current action is called whenever a different candidate is selected.
Almost forgot, if this little intro got you excited, the packages that you should install from MELPA are: helm-rhythmbox
and counsel
.