divzeroweb

2f30.org website
git clone git://git.2f30.org/divzeroweb.git
Log | Files | Refs | README | LICENSE

commit 5cd4b2c4f723c618665cd5c8a576dbab0ba4d898
parent 308efab69a5d70ba9753eb2b724c6f1eb1361e57
Author: lostd <lostd@2f30.org>
Date:   Mon Nov 24 12:33:48 +0200

My Raspberry Pi TV setup

Diffstat:
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@