commit 5cd4b2c4f723c618665cd5c8a576dbab0ba4d898
parent 308efab69a5d70ba9753eb2b724c6f1eb1361e57
Author: lostd <lostd@2f30.org>
Date: Mon, 24 Nov 2014 12:33:48 +0200
My Raspberry Pi TV setup
Diffstat:
A | guides/rpi-tv.md | | | 299 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
1 file changed, 299 insertions(+), 0 deletions(-)
diff --git a/guides/rpi-tv.md b/guides/rpi-tv.md
@@ -0,0 +1,299 @@
+### Raspberry Pi console media center with TV remote on Arch Linux
+
+This guide shows how to build a home entertainment system with the
+Raspberry Pi and Arch Linux on the console. I made this as a
+replacement to XBMC which I was using before for watching stuff; only
+this setup also integrates nicely with MPD for accessing our music
+fast!
+
+
+#### Environment
+
+Most TVs nowadays support the CEC (Consumer Electronics Control)
+capability through the HDMI connection. This lets us control other
+devices (such as the Raspberry Pi) using our remote. The available
+buttons for CEC on my TV remote control are: Up, Down, Left, Right,
+Select, Exit. The idea is to map those buttons to keyboard events using
+a `libcec` client and have programs configured to handle them. We will
+use the `libcec-daemon` client that does exactly that:
+
+ https://github.com/bramp/libcec-daemon
+
+First of all I added some keypresses to the CEC events, like this:
+
+ --- a/src/main.cpp
+ +++ b/src/main.cpp
+ @@ -231,7 +231,7 @@ const std::vector<list<__u16>> & Main::setupUinputMap() {
+
+ if (uinputCecMap.empty()) {
+ uinputCecMap.resize(CEC_USER_CONTROL_CODE_MAX + 1, {});
+ - uinputCecMap[CEC_USER_CONTROL_CODE_SELECT ] = { KEY_OK };
+ + uinputCecMap[CEC_USER_CONTROL_CODE_SELECT ] = { KEY_OK, KEY_ENTER };
+ uinputCecMap[CEC_USER_CONTROL_CODE_UP ] = { KEY_UP };
+ uinputCecMap[CEC_USER_CONTROL_CODE_DOWN ] = { KEY_DOWN };
+ uinputCecMap[CEC_USER_CONTROL_CODE_LEFT ] = { KEY_LEFT };
+ @@ -244,7 +244,7 @@ const std::vector<list<__u16>> & Main::setupUinputMap() {
+ uinputCecMap[CEC_USER_CONTROL_CODE_SETUP_MENU ] = { KEY_SETUP };
+ uinputCecMap[CEC_USER_CONTROL_CODE_CONTENTS_MENU ] = { KEY_MENU };
+ uinputCecMap[CEC_USER_CONTROL_CODE_FAVORITE_MENU ] = { KEY_FAVORITES };
+ - uinputCecMap[CEC_USER_CONTROL_CODE_EXIT ] = { KEY_EXIT };
+ + uinputCecMap[CEC_USER_CONTROL_CODE_EXIT ] = { KEY_EXIT, KEY_Q };
+ uinputCecMap[CEC_USER_CONTROL_CODE_NUMBER0 ] = { KEY_0 };
+ uinputCecMap[CEC_USER_CONTROL_CODE_NUMBER1 ] = { KEY_1 };
+ uinputCecMap[CEC_USER_CONTROL_CODE_NUMBER2 ] = { KEY_2 };
+
+And made the program start automatically as a service using our beloved
+init system.
+
+`/usr/local/lib/systemd/system/libcec-daemon.service`:
+
+ [Unit]
+ Description = CEC to uinput mapper
+ After = remote-fs.target
+
+ [Service]
+ User = root
+ Group = root
+ Type = simple
+ ExecStart = /home/tv/bin/libcec-daemon
+ Restart = always
+
+Note that similar results can be achieved using a LIRC setup. LIRC may
+be be a more flexible option simply because we'll probably have all
+buttons on the remote control to play with. We won't explore that here
+however.
+
+So our keys now are:
+
+ * Up
+ * Down
+ * Left
+ * Right
+ * Enter
+ * q
+
+Let's see the programs selection and their configuration.
+
+
+#### The file browser
+
+The other main component of this setup is the actual filesystem
+navigation. We will be using the `noice` file browser:
+
+ http://git.2f30.org/noice/
+
+Build it with a custom `config.h` to match our available keys and file
+associations, using applications and wrapper scripts:
+
+ struct assoc assocs[] = {
+ { "anime/.*\\.mkv$", "omxplayer-audio-stream-two" },
+ { "\\.(avi|mp4|mkv)$", "omxplayer-wrapper" },
+ { "\\.(mp3|ogg|flac|m4a)$", "mplayer" },
+ { "\\.radio$", "mpc-add-from-file" },
+ { ".*", "less" },
+ };
+
+ struct key bindings[] = {
+ { 'q', SEL_BACK},
+ { KEY_ENTER, SEL_GOIN },
+ { KEY_DOWN, SEL_NEXT },
+ { KEY_UP, SEL_PREV },
+ { KEY_RIGHT, SEL_PGDN },
+ { KEY_LEFT, SEL_PGUP },
+ };
+
+Of course we can also retain all other key bindings and resort to the
+keyboard for operations that don't make sense to support from the remote
+control. With the wrappers we add functionality specific to our setup.
+For example using the `mpc-add-from-file`:
+
+ #!/bin/sh
+
+ cat $1 | mpc add
+
+We can create files with the `.radio` extension that contain radio
+stream URLs and organise them like that. The action on them would add
+the stream to our running `mpd` queue. We'll see the
+`omxplayer-wrapper` in more detail later on.
+
+
+#### Autostarting in file browser view
+
+Create a local user, let's say `tv`:
+
+ $ useradd -m -g users -G audio,video -s tv-shell tv
+
+Create the `tv-shell` script in `~tv/bin/`:
+
+ #!/bin/sh
+
+ export PATH=$PATH:$HOME/bin
+ cd $HOME
+ noice menu/
+
+And the menu will be the directory structure we will be navigating into
+using the remote control. The last part is to auto-login the `tv` user,
+and can be done with an init script like this.
+
+`/usr/local/lib/systemd/system/getty@tty1.service.d/autologin.conf`:
+
+ [Service]
+ ExecStart=
+ ExecStart=-/usr/bin/agetty --autologin tv --noclear %I 38400 linux
+
+
+#### The video player
+
+Install `omxplayer` from packages and create the following files with
+the appropriate ownership and permissions.
+
+`~tv/bin/omxplayer-wrapper`:
+
+ #!/bin/sh
+
+ args=
+ args="$args --font /usr/share/fonts/TTF/DejaVuSans-Bold.ttf"
+ args="$args --italic-font /usr/share/fonts/TTF/DejaVuSans-BoldOblique.ttf"
+ args="$args --align center"
+ args="$args --font-size 58"
+ args="$args --no-ghost-box --blank"
+
+ keyconf=~/.omxplayer/keys
+ test -f "$keyconf" && {
+ args="$args --key-config $keyconf"
+ }
+
+ subs="${1%.*}.srt"
+ test -f "$subs" && {
+ omxplayer $args --subtitle "$subs" "$1"
+ } || {
+ omxplayer $args "$1"
+ }
+
+`~tv/.omxplayer/keys`:
+
+ PAUSE:
+ PAUSE:hex 0xa
+ SEEK_FORWARD_SMALL:right
+ SEEK_BACK_SMALL:left
+ SEEK_FORWARD_LARGE:up
+ SEEK_BACK_LARGE:down
+ EXIT:q
+
+The wrapper script selects subtitle fonts and looks for SubRip subtitle
+files (under the same name ignoring the file extension), among other
+preferences. The other one specifies keybindings to match our remote
+control. Note that the first line is a Space key and the second on is
+the key code fr the Enter key. You can use the `showkey` utility from
+the `kbd` package to identify key codes on the console.
+
+
+#### Setup MPD over NFS
+
+Create a link to our NFS mounted music directory:
+
+ $ ln -s /mnt/store/music /var/lib/mpd/music/master
+
+We now create this configuration that uses the MPD database proxy plugin
+to receive metadata from a remote MPD instance instead of using it's
+local db file.
+
+`/etc/mpd.conf`:
+
+ pid_file "/run/mpd/mpd.pid"
+ state_file "/var/lib/mpd/mpdstate"
+ playlist_directory "/home/tv/playlists"
+ music_directory "/var/lib/mpd/music"
+
+ database {
+ plugin "proxy"
+ host "store"
+ port "6600"
+ }
+
+ input {
+ plugin "curl"
+ }
+
+ audio_output {
+ type "alsa"
+ name "Speakers"
+ }
+
+Care must be taken to have the file paths match in both our `store` host
+and here. In this setup all MPD file paths will start with `master/`.
+Another thing is that playlists are not handled by the database so we
+need to synchronise them manually. My choice is a private revision
+controlled playlists directory for that purpose.
+
+
+#### Audio visualizer
+
+We also build and install our console audio visualizer now:
+
+ http://git.2f30.org/nausea/
+
+We need this to our `/etc/mpd.conf`:
+
+ audio_output {
+ type "fifo"
+ name "Pipe"
+ path "/tmp/audio.fifo"
+ format "44100:16:2"
+ }
+
+
+#### Youtube
+
+And if you need Youtube in your TV here is a Python package that deals
+with it:
+
+ $ pip2 install mps-youtube
+
+To configure it to use `omxplayer` too:
+
+ $ mpsyt
+ > set player omxplayer
+ > set playerargs --blank
+
+And video is disabled by default, so enable it:
+
+ > set search_music false
+ > set show_video true
+
+Note, however, that a keyboard will be needed for the searches here :)
+
+
+#### The glue
+
+Finally, under the `~tv/menu` directory we will be creating simple
+scripts and symlinks to organise our media files.
+
+ $ ln -s /mnt/store/movies ~tv/menu/
+ $ ln -s /mnt/store/series ~tv/menu/
+
+`~tv/menu/music.sh`:
+
+ #!/bin/sh
+
+ ncmpc
+
+`~tv/menu/music-off.sh`:
+
+ #!/bin/sh
+
+ mpc stop
+
+`~tv/menu/nausea.sh`:
+
+ #!/bin/sh
+
+ nausea -d 2
+
+
+#### Other stuff
+
+
+Cheers!
+
+lostd@