mwolson.org Blog - /Tech

Sat, 29 Dec 2007

OLPC as a car audio player using Emacs, EMMS, and MusicPD

This blog post will explain how to use the OLPC XO laptop as a music player in a car, by using Emacs, EMMS, and MusicPD.

Step 1: Emacs

To install Emacs, launch the Terminal activity on your XO, and do the following.

su -c "yum install emacs"

When prompted about installing all of the dependencies, hit "y".

Step 2: MusicPD

Option 1: yum and rpm.livna.org repo

MusicPD is not available from the standard repositories, perhaps due to some patent worries on the part of Fedora. I find this strange, since Debian includes it.

First, you'll need to add another outside repository to your XO as follows.

wget http://rpm.livna.org/livna-release-7.rpm
su -c "rpm -ivh livna-release-7.rpm"

Then install mpd.

su -c "yum install mpd"

Option 2: Sonata

Alternatively, you could try installing the Sonata activity, and just use ~/Activities/sonata.activity/bin/mpd as the path to the mpd binary. To do this, download the activity using wget, and run:

sugar-install-bundle /path/to/Sonata.xo

If you try to just click on it from the browser activity, it will show the binary contents of the file, due to a misconfiguration on the third-party web server that hosts it.

Step 3: EMMS

To get my repository for EMMS, do:

darcs pull http://mwolson.org/darcs/emms2

Alternatively, download a snapshot at http://mwolson.org/static/dist/emms-snapshot.tar.gz.

Make an ~/elisp directory on the laptop and extract the tarball (or copy the directory) there.

Then some configuration is needed. Here is a working ~/.emacs.d/emms-init.el file. Be sure to add the snippet (load "~/.emacs.d/emms-init.el") to your Emacs init file (which is either ~/.emacs or ~/.emacs.d/init.el, depending on your tastes).

;;; emms-init.el --- Initialize emms

;;; Setup

(add-to-list 'load-path "~/elisp/emms")

;; Initialize
(require 'emms)
(require 'emms-info)
(require 'emms-player-mpd)
(require 'emms-playing-time)
(require 'emms-playlist-mode)
(require 'emms-streams)
(require 'emms-volume)

(emms-playing-time 1)

;; The name of emms-playlist-mode is *way* too long
(add-hook 'emms-playlist-mode-hook
          #'(lambda ()
              (setq mode-name "EMMS")))

;;; Utilities

(defun my-start-mpd ()
  "Start MPD and sync to its playlist."
  (interactive)
  (shell-command "mpd ~/.mpd/mpd.conf")
  (emms-player-mpd-connect)
  (switch-to-buffer emms-playlist-buffer))

(defun my-stop-mpd ()
  "Stop MPD."
  (interactive)
  (shell-command "mpd --kill ~/.mpd/mpd.conf")
  (emms-playlist-current-kill)
  (emms-player-mpd-disconnect))

;; Switch to the radio buffer
(defun my-emms-streams ()
  (interactive)
  (let ((buf (get-buffer emms-stream-buffer-name)))
    (if buf
        (switch-to-buffer buf)
      (emms-streams))))

;; Switch to either the radio buffer or the current EMMS playlist
(defun my-emms-switch-to-current-playlist ()
  (interactive)
  (if (and (boundp 'emms-stream-playlist-buffer)
           (eq emms-stream-playlist-buffer emms-playlist-buffer))
      (switch-to-buffer emms-stream-buffer-name)
    (if (or (null emms-playlist-buffer)
            (not (buffer-live-p emms-playlist-buffer)))
        (error "No current Emms buffer")
      (switch-to-buffer emms-playlist-buffer))))

;;; Key customizations

(define-key emms-playlist-mode-map "q" 'emms-playlist-current-kill)
(define-key emms-playlist-mode-map (kbd "SPC") 'emms-pause)
;; this is the "O" button on the gamepad
(define-key emms-playlist-mode-map (kbd "<prior>") 'emms-player-mpd-previous)
;; this is the "X" button on the gamepad
(define-key emms-playlist-mode-map (kbd "<next>") 'emms-player-mpd-next)

;; this is the largest dot on the top row, in the middle section
(global-set-key (kbd "<f8>") 'my-start-mpd)
;; this is the smallest dot on the top row, in the middle section
(global-set-key (kbd "<f5>") 'my-stop-mpd)
;; this is the check-mark button on the gamepad
(global-set-key (kbd "<select>") 'emms-pause)

(global-set-key "\C-cm" nil)
(global-set-key "\C-cm " 'emms-pause)
(global-set-key "\C-cm0" 'emms-playlist-current-clear)
(global-set-key "\C-cmc" 'emms-player-mpd-connect)
(global-set-key "\C-cmn" 'emms-player-mpd-next)
(global-set-key "\C-cmo" 'my-emms-switch-to-current-playlist)
(global-set-key "\C-cmp" 'emms-player-mpd-previous)
(global-set-key "\C-cmq" 'emms-stop)
(global-set-key "\C-cmQ" #'(lambda () (interactive) (emms-player-mpd-clear)))
(global-set-key "\C-cmr" 'my-emms-streams)
(global-set-key "\C-cms" 'emms-seek)
(global-set-key "\C-cm-" 'emms-volume-mode-minus)
(global-set-key "\C-cm+" 'emms-volume-mode-plus)
(global-set-key "\C-cm\C-c" 'my-emms-reset-cache)

;;; Custom variables

(custom-set-variables
 '(emms-cache-file "~/.emacs.d/.emms-cache")
 '(emms-info-asynchronously nil)
 '(emms-info-functions (quote (emms-info-mpd)))
 '(emms-player-list (quote (emms-player-mpd)))
 '(emms-player-mpd-music-directory "~/Music")
 '(emms-playlist-buffer-name "*EMMS Playlist*")
 '(emms-playlist-default-major-mode (quote emms-playlist-mode))
 '(emms-playlist-mode-open-playlists t)
 '(emms-stream-default-action "play")
 '(emms-volume-change-function (quote emms-volume-mpd-change)))
(custom-set-faces)

;;; Initialization

(define-emms-combined-source all nil
  '((emms-source-directory "~/Music")))

;; Type M-x emms-add-all to add all music in your ~/Music directory.

;;; emms-init.el ends here

Step 4: Configuring MusicPD

What I do is make two directories called Music and mpd on the SD card. Symlinks are then made on the XO from /home/olpc/Music -> /media/XXXX-XXXX/Music and /home/olpc/.mpd -> /media/XXXX-XXXX/mpd, where XXXX-XXXX depends on where your SD card is mounted.

The configuration file is placed in mpd/mpd.conf. Here is a quick summary of its contents, with comments removed.

music_directory		"~/Music"
playlist_directory	"~/Music"

db_file			"~/.mpd/db"
log_file		"~/.mpd/mpd.log"
error_file		"~/.mpd/errors.log"
pid_file                "~/.mpd/pid"
state_file              "~/.mpd/state"

audio_output {
        type                    "alsa"
        name                    "My ALSA Device"
}

mixer_type                      "alsa"
mixer_device                    "default"
mixer_control                   "PCM"

replaygain                      "track"
buffer_before_play              "0%"
http_buffer_size                "256"
filesystem_charset              "UTF-8"
id3v1_encoding                  "UTF-8"

When I want to put music on the SD card, I use the cardreader of my desktop computer to copy the music on, and also generate the mpd database file with mpd --create-db and a similar mpd.conf file to the above.

Step 5: Using EMMS

After the XO laptop is on, the SD card has been inserted, start Emacs with emacs -nw from the Terminal activity. I had to use the non-GTK GUI, because only one too-small font was being detected by Xorg.

To start mpd and bring up a buffer with the current mpd playlist, hit F8, which is the largest dot on the top row, in the middle section.

To stop mpd and delete the window, saving state, hit F5, which is the key with the smallest dot in that same section.

To skip to the previous track, hit "O" on the gamepad. To skip to the next track, hit "X" on the gamepad. To pause, hit either the check mark key or the space bar.

For other keys, read the emms-init.el file above. I use the key prefix C-c m to do all the mpd commands that I need.

Posted by Robert Goldman at Mon Dec 31 11:25:32 2007

This looks neat, but I was wondering --- what does it have to do with your car?  Does it somehow playback through your car stereo?

Posted by Michael Olson at Mon Dec 31 12:28:28 2007

I have a tape deck in my car, so I just plug a tape adapter into the
headphone jack of the OLPC.

Posted by Fred Lacoste at Wed Jan 23 01:37:56 2008

Why dont you use sonata?

It's easy and it's sugarized.

Fred

Posted by Michael Olson at Wed Jan 23 02:02:53 2008

I mentioned Sonata as an alternative in the blog entry.

I prefer to use EMMS rather than the Sonata interface for several reasons.  For starters, it locked up on me when trying to play music off of an SD card (I made ~/Music a symlink to the the card).  Also, I like using the same program (EMMS) that I use on the desktop.  Also, I am a developer for EMMS, and hence have even more reason to plug it.

Add a comment

Name: 
Your email address: 
Your website: 
 
Comment: