Vaughan Harper's blog Linux, Misc Technical, Raspberry Pi Configuring an Infrared Remote Control to Control RuneAudio Archlinux (without needing LIRC)
Configuring an Infrared Remote Control to Control RuneAudio Archlinux (without needing LIRC)

Linux Misc Technical Raspberry Pi

Configuring an Infrared Remote Control to Control RuneAudio Archlinux (without needing LIRC)

Introduction

As I’ve mentioned in a previous blog article, I have started using a brilliant Raspberry Pi-based music player called RuneAudio (which uses Music Player Daemon – MPD – at its heart). I have this connected to a home cinema system, and I wanted to be able to use its remote control to control the music player (play/pause, next track, previous track, etc). This article describes how to set this up.

RuneAudio can be found at https://www.runeaudio.com/ . At the time of writing the latest version of RuneAudio is RuneAudio+R e4 which can be found at https://www.runeaudio.com/forum/runeaudio-r-e4-t7084.html, but it is worth checking this thread in case a later version has been released. (Frustratingly this seems to be only a semi-official version of RuneAudio, so it can’t be found at the RuneAudio download page https://www.runeaudio.com/download/.)

Previously LIRC (Linux Infrared Remote Control) would have been an essential component of this setup, but now support for infrared remote controls has been built into the Linux kernel.

The latest releases of RuneAudio use Archlinux, and I have tested this approach on RuneAudio+R e3 and RuneAudio+R e4, but the same principles may work with other flavours of Linux or with other music players.

I should add that many of the ideas in this article are derived from other web articles which I have listed in the Further Reading section below. Grateful thanks to those authors who have taken the trouble to document their work.

Step-by-step approach

Note that the operating system used by RuneAudio is Archlinux, and the user logs in as root. This approach may work with systems, but with other types of Linux the user may log in with a non-root account so some of the commands with will have to be prefaced with sudo.

  1. You need an infrared receiver: there are many articles on the Internet about how to build or buy a receiver, so I haven’t duplicated that information here. For convenience I used an Energenie ENER314-IR Infrared Controller board which I got from an Internet supplier for about £9.00 (US$12). This worked well and the receiver was very sensitive; it includes both an infrared receiver and infrared transmitter. (The only potential disadvantages with it that I could think of were (a) if you’re using the Official Raspberry Pi Case then you need to drill a hole in it to expose the receiver, and (b) both the receiver and the transmitter point in the same direction and can’t be moved.)
  1. You need to know which GPIO pin is used by the infrared receiver: with the Energenie ENER314-IR the IR signal in is on GPIO pin 18.
  1. Log in as root.
  1. Add the following to /boot/config.txt:
    dtoverlay=gpio-ir,gpio_pin=18

    (Change the GPIO pin number as necessary to match the hardware that you are using.)
  1. Re-boot the Raspberry Pi:
    reboot
  1. Confirm that the gpio module has been loaded:
    lsmod | grep gpio

    The output should look similar to the following:
    root@runeaudio+R e4:~ # lsmod | grep gpio
    gpio_ir_recv 16384 0
    rc_core 40960 4 ir_rc6_decoder,rc_rc6_mce,gpio_ir_recv
    root@runeaudio+R e4:~ #


    Show the corresponding input device:
    cat /proc/bus/input/devices

    The output should look similar to the following:
    root@runeaudio+R e4:~ # cat /proc/bus/input/devices
    I: Bus=0019 Vendor=0001 Product=0001 Version=0100
    N: Name="gpio_ir_recv"
    P: Phys=gpio_ir_recv/input0
    S: Sysfs=/devices/platform/ir-receiver@12/rc/rc0/input0
    U: Uniq=
    H: Handlers=kbd event0
    B: PROP=20
    B: EV=100017
    B: KEY=fff 0 0 4200 108fc32e 2376051 0 0 0 7 158000 4192 4001 8e9680 0 0 10000000
    B: REL=3
    B: MSC=10
    root@runeaudio+R e4:~ #
  1. Ensure that ir-keytable is installed:
    ir-keytable

    The output should look similar to the following:
    root@runeaudio+R e4:~ # ir-keytable
    Found /sys/class/rc/rc0/ with:
    Name: gpio_ir_recv
    Driver: gpio_ir_recv
    Default keymap: rc-rc6-mce
    Input device: /dev/input/event0
    LIRC device: /dev/lirc0
    Supported kernel protocols: lirc rc-5 rc-5-sz jvc sony nec sanyo mce_kbd rc-6 sharp xmp imon rc-mm
    Enabled kernel protocols: lirc rc-6
    bus: 25, vendor/product: 0001:0001, version: 0x0100
    Repeat delay = 500 ms, repeat period = 125 ms
    root@runeaudio+R e4:~ #
  1. Enable all the kernel protocols:
    ir-keytable -p all

    The output should look similar to the following:
    root@runeaudio+R e4:~ # ir-keytable -p all
    Protocols changed to unknown other lirc rc-5 rc-5-sz jvc sony nec sanyo mce_kbd rc-6 sharp xmp cec imon rc-mm
    Can't find xbox-dvd bpf protocol in /etc/rc_keymaps/protocols or /usr/lib/udev/rc_keymaps/protocols
    root@runeaudio+R e4:~ #
  1. Test the infrared remote control with ir-keytable
    ir-keytable -t -s rc0

    Point the infrared remote control at the receiver, press some buttons on the controller, and observe the output. The output may look similar to the following:
root@runeaudio+R e4:~ # ir-keytable -t -s rc0
Testing events. Please, press CTRL-C to abort.
216.380035: lirc protocol(sony20): scancode = 0x101000
216.380059: event type EV_MSC(0x04): scancode = 0x101000
216.380059: event type EV_SYN(0x00).
...
248.820027: lirc protocol(sony12): scancode = 0x10025
248.820050: event type EV_MSC(0x04): scancode = 0x10025
248.820050: event type EV_SYN(0x00).
...
353.510019: lirc protocol(rc5_sz): scancode = 0x2fff toggle=1
353.510051: event type EV_MSC(0x04): scancode = 0x2fff
353.510051: event type EV_SYN(0x00).
353.510082: event type EV_MSC(0x04): scancode = 0xd00002
353.510082: event type EV_SYN(0x00).
353.510079: lirc protocol(sony15): scancode = 0xd00002

In this case the controller is using various sony protocols: 20 bit protocol for some keys, 15 bit protocol for some other keys, and 12 bit protocol for the remaining keys.

  1. Look in /lib/udev/rc_keymaps to see whether a keymap .toml file exists for the controller being used – if so copy the keymap file to /etc/rc_keymaps.
  1. If the keymap file for the controller being used doesn’t exist in /lib/udev/rc_keymaps then it’s possible that one exists somewhere on the Internet.
  1. In my case the wasn’t an existing keymap for the controller that I was using (a Sony RM-ADP090), so I therefore created my own keymap by doing the following steps.

    As I knew from the above that my controller was using Sony protocol I ran this command to select only the Sony protocols:
    ir-keytable -p sony

    The output looked like this:
    root@runeaudio+R e4:~ # ir-keytable -p sony
    Protocols changed to sony
    root@runeaudio+R e4:~ #


    I then ran:
    ir-keytable -v -t
    and noted the scancodes that were shown for each button.

    I then constructed a keymap file (Sony_RM-ADP090.toml in my case) which I placed in /etc/rc_keymaps.
    The definition of the format of the keymap file can be found at https://manpages.debian.org/testing/ir-keytable/rc_keymap.5.en.html

    My resulting keymap file was as follows:
[[protocols]]
name = "sony_RM-ADP090"
protocol = "sony"
variant = "sony20"
[protocols.scancodes]

# brand:   Sony 
# model:   RM-ADP090
# devices: Sony BDV-E2100 Home Cinema System
#
# Vaughan Harper, July 2020
#
# remote layout:
# +-------------------------------------------------+
# | (EJECTCD)  (TV_SPEAKER)   (TV_POWER)    (POWER) |
# | (SLEEP)        (1)        (2)               (3) |
# | (BLUETOOTH)    (4)        (5)               (6) |
# | (FUNCTION)     (7)        (8)               (9) |
# | (FOOTBALL)   (AUDIO)      (0)        (SUBTITLE) |
# | (RED)        (GREEN)      (YELLOW)       (BLUE) |
# | (TOP MENU)            (UP)        (POP UP/MENU) |
# | (LEFT)                (OK)              (RIGHT) |
# | (RETURN)             (DOWN)           (OPTIONS) |
# | (SOUND_MODE_DOWN)    (HOME)     (SOUND_MODE_UP) |
# | (MUSIC_EQ)   (PREVIOUS)   (NEXT)          (SEN) |
# | (REWIND)              (PLAY)      (FASTFORWARD) |
# | (DISPLAY)            (PAUSE)             (STOP) |
# |             (VOLUMEUP)     (TV_VOL_UP)          |
# | (MUTE)                              (TV_SOURCE) |
# |            (VOLUMEDOWN)    (TV_VOL_DOWN)        |
# +-------------------------------------------------+

0x10103c = "KEY_EJECTCD"
0x103045 = "KEY_TV_SPEAKER"
0x101000 = "KEY_1"
0x101001 = "KEY_2"
0x101002 = "KEY_3"
0x103071 = "KEY_BLUETOOTH"
0x101003 = "KEY_4"
0x101004 = "KEY_5"
0x101005 = "KEY_6"
0x101006 = "KEY_7"
0x101007 = "KEY_8"
0x101008 = "KEY_9"
0x107017 = "KEY_FOOTBALL"
0x101012 = "KEY_AUDIO"
0x101009 = "KEY_0"
0x101011 = "KEY_SUBTITLE"
0x103005 = "KEY_RED"
0x103006 = "KEY_GREEN"
0x103007 = "KEY_YELLOW"
0x103004 = "KEY_BLUE"
0x101019 = "KEY_MEDIA_TOP_MENU"  # labelled 'TOP MENU'
0x101078 = "KEY_UP"
0x10101a = "KEY_MENU"  # labelled 'POP UP/MENU
0x10107a = "KEY_LEFT"
0x10107c = "KEY_OK"
0x10107b = "KEY_RIGHT"
0x10107d = "KEY_RETURN"
0x101079 = "KEY_DOWN"
0x101073 = "KEY_OPTION"  # labelled 'OPTIONS'
0x101030 = "KEY_PREVIOUS"
0x101031 = "KEY_NEXT"
0x107050 = "KEY_SEN"
0x101033 = "KEY_REWIND"
0x101034 = "KEY_FASTFORWARD"
0x101018 = "KEY_DISPLAY"

[[protocols]]
name = "sony_RM-ADP090_2"
protocol = "sony"
variant = "sony15"
[protocols.scancodes]
0x500015 = "KEY_POWER"
0x500060 = "KEY_SLEEP"
0xd00002 = "KEY_PLAY"
0xd00069 = "KEY_FUNCTION"
0xd0006f = "KEY_SOUND_MODE_DOWN"
0xd00007 = "KEY_HOME"
0xd0006e = "KEY_SOUND_MODE_UP"
0xd00049 = "KEY_MUSIC_EQ"
0xd00001 = "KEY_PAUSE"
0xd00000 = "KEY_STOP"
0x500012 = "KEY_VOLUMEUP"
0x500014 = "KEY_MUTE"
0x500013 = "KEY_VOLUMEDOWN"

[[protocols]]
name = "sony_RM-ADP090_3"
protocol = "sony"
variant = "sony12"
[protocols.scancodes]
0x10015 = "KEY_POWER2"  # TV power button
0x10012 = "KEY_TV_VOL_UP"
0x10013 = "KEY_TV_VOL_DOWN"
0x10025 = "KEY_TV_SOURCE"

(In my case, because the controller used three separate variants of the Sony protocol there needed to be three separate sections within the keymap file.)

  1. Delete the existing table and load the the new table from the keymap file by running a command similar to the following:
    ir-keytable -c -p sony -w /etc/rc_keymaps/Sony_RM-ADP090.toml
    where:
    -c clears the existing table
    -p sony sets the protocol to sony
    -w /etc/rc_keymaps/Sony_RM-ADP090.toml write (add) the keymapping from the file specified

    Review the resulting output – mine was as follows:
root@runeaudio+R e4:~ # ir-keytable -c -p sony -w /etc/rc_keymaps/Sony_RM-ADP090.toml
Read sony_RM-ADP090 table
/etc/rc_keymaps/Sony_RM-ADP090.toml: keycode `KEY_TV_SPEAKER' not recognised, no mapping for scancode 0x04103045
/etc/rc_keymaps/Sony_RM-ADP090.toml: keycode `KEY_RETURN' not recognised, no mapping for scancode 0x0410107d
/etc/rc_keymaps/Sony_RM-ADP090.toml: keycode `KEY_SEN' not recognised, no mapping for scancode 0x04107050
/etc/rc_keymaps/Sony_RM-ADP090.toml: keycode `KEY_DISPLAY' not recognised, no mapping for scancode 0x04101018
/etc/rc_keymaps/Sony_RM-ADP090.toml: keycode `KEY_TV_VOL_UP' not recognised, no mapping for scancode 0x0410012
/etc/rc_keymaps/Sony_RM-ADP090.toml: keycode `KEY_TV_VOL_DOWN' not recognised, no mapping for scancode 0x0410013
/etc/rc_keymaps/Sony_RM-ADP090.toml: keycode `KEY_TV_SOURCE' not recognised, no mapping for scancode 0x0410025
/etc/rc_keymaps/Sony_RM-ADP090.toml: keycode `KEY_FUNCTION' not recognised, no mapping for scancode 0x04d00069
/etc/rc_keymaps/Sony_RM-ADP090.toml: keycode `KEY_SOUND_MODE_DOWN' not recognised, no mapping for scancode 0x04d0006f
/etc/rc_keymaps/Sony_RM-ADP090.toml: keycode `KEY_SOUND_MODE_UP' not recognised, no mapping for scancode 0x04d0006e
/etc/rc_keymaps/Sony_RM-ADP090.toml: keycode `KEY_MUSIC_EQ' not recognised, no mapping for scancode 0x04d00049
Old keytable cleared
Wrote 41 keycode(s) to driver
Protocols changed to sony
root@runeaudio+R e4:~ #

You can see from the output that 41 keycodes were written, but there were also a number of errors listed: the keycodes specified need to match the keycodes already defined within the system. I never found where the list of allowable keycodes is defined or whether it can be added to, but you can find a list of keycodes (as comments) in /usr/include/linux/input-event-codes.h. Of course it doesn’t matter if you get some errors – you only need to recognise the keycodes from the buttons on the controller that you want to use to control RuneAudio. So if, for example, you wanted to use the button labelled ‘FOOTBALL’ on the remote control then you would need to map its scancode to one of the allowable keycodes.

  1. Check the contents of the keytable. If you run
    ir-keytable -r
    it will list the keycodes that are now in the keytable together with their corresponding scancodes:
root@runeaudio+R e4:~ # ir-keytable -r
scancode 0x10015 = KEY_POWER2 (0x164)
scancode 0x101000 = KEY_1 (0x02)
scancode 0x101001 = KEY_2 (0x03)
scancode 0x101002 = KEY_3 (0x04)
scancode 0x101003 = KEY_4 (0x05)
scancode 0x101004 = KEY_5 (0x06)
scancode 0x101005 = KEY_6 (0x07)
scancode 0x101006 = KEY_7 (0x08)
scancode 0x101007 = KEY_8 (0x09)
scancode 0x101008 = KEY_9 (0x0a)
scancode 0x101009 = KEY_0 (0x0b)
scancode 0x101011 = KEY_SUBTITLE (0x172)
scancode 0x101012 = KEY_AUDIO (0x188)
scancode 0x101019 = KEY_MEDIA_TOP_MENU (0x26b)
scancode 0x10101a = KEY_MENU (0x8b)
scancode 0x101030 = KEY_PREVIOUS (0x19c)
scancode 0x101031 = KEY_NEXT (0x197)
scancode 0x101033 = KEY_REWIND (0xa8)
scancode 0x101034 = KEY_FASTFORWARD (0xd0)
scancode 0x10103c = KEY_EJECTCD (0xa1)
scancode 0x101073 = KEY_OPTION (0x165)
scancode 0x101078 = KEY_UP (0x67)
scancode 0x101079 = KEY_DOWN (0x6c)
scancode 0x10107a = KEY_LEFT (0x69)
scancode 0x10107b = KEY_RIGHT (0x6a)
scancode 0x10107c = KEY_OK (0x160)
scancode 0x103004 = KEY_BLUE (0x191)
scancode 0x103005 = KEY_RED (0x18e)
scancode 0x103006 = KEY_GREEN (0x18f)
scancode 0x103007 = KEY_YELLOW (0x190)
scancode 0x103071 = KEY_BLUETOOTH (0xed)
scancode 0x107017 = BTN_TRIGGER_HAPPY10 (0x2c9)
scancode 0x500012 = KEY_VOLUMEUP (0x73)
scancode 0x500013 = KEY_VOLUMEDOWN (0x72)
scancode 0x500014 = KEY_MUTE (0x71)
scancode 0x500015 = KEY_POWER (0x74)
scancode 0x500060 = KEY_SLEEP (0x8e)
scancode 0xd00000 = KEY_STOP (0x80)
scancode 0xd00001 = KEY_PAUSE (0x77)
scancode 0xd00002 = KEY_PLAY (0xcf)
scancode 0xd00007 = KEY_HOME (0x66)
Enabled kernel protocols: lirc sony
root@runeaudio+R e4:~ #

Crucially you need to ensure that the remote control keys that you want to use to control RuneAudio are listed here, and if not you’ll need to update the keymap file.

  1. Test the operation of the keytable – run this command:
    ir-keytable -t
    and press some buttons on the remote control. You should get some output similar to the following:
root@runeaudio+R e4:~ # ir-keytable -t
Testing events. Please, press CTRL-C to abort.
673.780023: lirc protocol(sony20): scancode = 0x10103c
673.780068: event type EV_MSC(0x04): scancode = 0x10103c
673.780068: event type EV_KEY(0x01) key_down: KEY_EJECTCD(0x00a1)
673.780068: event type EV_SYN(0x00).
673.820050: lirc protocol(sony20): scancode = 0x10103c
673.820079: event type EV_MSC(0x04): scancode = 0x10103c
673.820079: event type EV_SYN(0x00).
673.870025: lirc protocol(sony20): scancode = 0x10103c
673.870046: event type EV_MSC(0x04): scancode = 0x10103c
673.870046: event type EV_SYN(0x00).
673.910033: lirc protocol(sony20): scancode = 0x10103c
673.910049: event type EV_MSC(0x04): scancode = 0x10103c
673.910049: event type EV_SYN(0x00).
674.030025: event type EV_KEY(0x01) key_up: KEY_EJECTCD(0x00a1)
674.030025: event type EV_SYN(0x00).
679.450023: lirc protocol(sony20): scancode = 0x101000
679.450058: event type EV_MSC(0x04): scancode = 0x101000
679.450058: event type EV_KEY(0x01) key_down: KEY_1(0x0002)
679.450058: event type EV_SYN(0x00).
679.490024: lirc protocol(sony20): scancode = 0x101000
679.490049: event type EV_MSC(0x04): scancode = 0x101000
679.490049: event type EV_SYN(0x00).
679.540022: lirc protocol(sony20): scancode = 0x101000
679.540037: event type EV_MSC(0x04): scancode = 0x101000
679.540037: event type EV_SYN(0x00).
679.660021: event type EV_KEY(0x01) key_up: KEY_1(0x0002)
679.660021: event type EV_SYN(0x00).
685.550027: lirc protocol(sony15): scancode = 0x500012
685.550055: event type EV_MSC(0x04): scancode = 0x500012
685.550055: event type EV_KEY(0x01) key_down: KEY_VOLUMEUP(0x0073)
685.550055: event type EV_SYN(0x00).
685.600028: lirc protocol(sony15): scancode = 0x500012
685.600054: event type EV_MSC(0x04): scancode = 0x500012
685.600054: event type EV_SYN(0x00).
685.640024: lirc protocol(sony15): scancode = 0x500012
685.640039: event type EV_MSC(0x04): scancode = 0x500012
685.640039: event type EV_SYN(0x00).
685.760026: event type EV_KEY(0x01) key_up: KEY_VOLUMEUP(0x0073)
685.760026: event type EV_SYN(0x00).
696.170030: lirc protocol(sony15): scancode = 0xd00002
696.170073: event type EV_MSC(0x04): scancode = 0xd00002
696.170073: event type EV_KEY(0x01) key_down: KEY_PLAY(0x00cf)
696.170073: event type EV_SYN(0x00).
696.220087: lirc protocol(sony15): scancode = 0xd00002
696.220138: event type EV_MSC(0x04): scancode = 0xd00002
696.220138: event type EV_SYN(0x00).
696.260117: lirc protocol(sony15): scancode = 0xd00002
696.260154: event type EV_MSC(0x04): scancode = 0xd00002
696.260154: event type EV_SYN(0x00).
696.380076: event type EV_KEY(0x01) key_up: KEY_PLAY(0x00cf)
696.380076: event type EV_SYN(0x00).

Crucially you want to see messages like key_down: KEY_EJECTCD and key_down: KEY_PLAY which shows that the scancodes from the controller are being mapped to keycodes within Archlinux.

Optionally you can get debug messages by specifying the verbose option:
ir-keytable -t -v

  1. Edit the file /etc/rc_maps.cfg to ensure that this keymapping is loaded automatically on bootup. There are a lot of comments in the file, and a lot of options selected by default, but I just commented out all the entries and added this line to the file:
 *       *       /etc/rc_keymaps/Sony_RM-ADP090.toml

(This keymapping seems to take effect 30-60 seconds after the system boots up.)

  1. Reboot
    reboot
  1. Test that the keytable is automatically loaded correctly by running this command:
    ir-keytable -t
    and then pressing some buttons on the remote control. Again you want to see messages like key_down: KEY_EJECTCD and key_down: KEY_PLAY.
  1. Certain keycodes control Archlinux/MPD behaviour by default: for example, KEY_PLAY automatically causes MPD to toggle play/pause (equivalent of mpc toggle), and KEY_POWER causes the system to power off. The automatic key bindings that I have found are as follows:

    KEY_LEFT – previous track
    KEY_UP – increase mpc volume
    KEY_RIGHT – next track
    KEY_DOWN – decrease mpc volume
    KEY_POWER – powers down the system
    KEY_PLAY – toggle play/pause
    KEY_MUTE – mute the output
    KEY_VOLUMEUP – increase mpc volume
    KEY_VOLUMEDOWN – decrease mpc volume

    This means that supposing you want the red button on your control to power off the pi and the scancode generated by the red button on the remote control is 0x103005, then you can cause this to happen by putting the following entry in the keymap file:
    0x103005 = "KEY_POWER" # code for red button

    Conversely if, for example, you want to ensure that no button on the remote control will cause the pi to power down then don’t map any scancode to the KEY_POWER keycode.

    It is possible to map more than one scancode to a particular keycode. For example when I decided that I wanted to the following operations to be performed:
    – Left arrow and up arrow: previous track
    – OK button: toggle play/pause
    – Right arrow and down arrow: next track
    my keymap file just needed to contain the following:

    [[protocols]]
    name = "sony_RM-ADP090"
    protocol = "sony"
    variant = "sony20"
    [protocols.scancodes]
    0x101078 = "KEY_LEFT" # KEY_UP button -> Previous track
    0x10107a = "KEY_LEFT" # KEY_LEFT button -> Previous track
    0x10107c = "KEY_PLAY" # KEY_OK button -> Play/pause
    0x10107b = "KEY_RIGHT" # KEY_RIGHT button -> Next track
    0x101079 = "KEY_RIGHT" # KEY_DOWN button -> Next track

    If you can meet your requirements by using the automatic key bindings to mpc commands then this is all you need to do!
  1. If you want to perform some of the MPD operations not covered by the default key bindings listed above (for example, you wanted a button on the remote control to cause an mpc stop or an mpc repeat on command) then you can do this by installing Triggerhappy. This is described at https://github.com/wertarbyte/triggerhappy as ‘a hotkey daemon developed with small and embedded systems in mind, e.g. linux based routers. It attaches to the input device files and interprets the event data received and executes scripts configured in its configuration.’

    (One idea I had is to use Triggerhappy to trigger a script that would power down the pi if, for example, a certain set of buttons were pressed within a short period of time, as it would be useful to be able to use the remote control to shut down the pi, but I’d like to to avoid powering it down accidentally. However I haven’t gone any further with that idea.)

    The Archlinux repository does not appear to have a version of Triggerhappy which works on armv7h architecture, so I found the most reliable method was to fire up a Raspbian/Raspberry Pi OS system, install Triggerhappy, save the relevant files and copy them across to the RuneAudio system. (If you’re interested I have written more about the other options that I tried at the foot of this article.)

    On a Raspbian system, install Triggerhappy by running the following commands:
    sudo apt-get update
    sudo apt-get install triggerhappy
    Then copy the files listed below onto a local PC, or a memory stick/thumbdrive/USB flash drive.
FilenamePermissions/ownershipDirectory on RaspbianDirectory on RuneAudio
triggerhappy.service-rw-r--r-- 1 root root/lib/systemd/system/usr/lib/systemd/system
triggerhappy.socket-rw-r--r-- 1 root root/lib/systemd/system/usr/lib/systemd/system
triggerhappy.conf.examples-rw-r--r-- 1 root root/usr/share/doc/triggerhappy/etc/triggerhappy/triggers.d/
thd-rwxr-xr-x 1 root root/usr/sbin//usr/bin

On the RuneAudio system create a directory, say, /tmp/triggerhappyTempSave, and copy the saved Triggerhappy files to that directory.

Then run the following commands:

Set the permissions:
chmod 644 /tmp/triggerhappyTempSave/*
chmod 755 /tmp/triggerhappyTempSave/thd

Create the required directory:
mkdir -p /etc/triggerhappy/triggers.d/

Move the files to their correct directories:
mv /tmp/triggerhappyTempSave/triggerhappy.service /usr/lib/systemd/system/
mv /tmp/triggerhappyTempSave/triggerhappy.socket /usr/lib/systemd/system/
mv /tmp/triggerhappyTempSave/triggerhappy.conf.examples /etc/triggerhappy/triggers.d/
mv /tmp/triggerhappyTempSave/thd /usr/bin

  1. Run Triggerhappy interactively by running the following command:
    thd -d /dev/input/event*

    Then press some keys on the remote control. You should see some output similar to the following:
EV_KEY  KEY_1   1       /dev/input/event0
# KEY_1 1       command
EV_KEY  KEY_1   0       /dev/input/event0
# KEY_1 0       command
EV_KEY  KEY_2   1       /dev/input/event0
# KEY_2 1       command
EV_KEY  KEY_2   0       /dev/input/event0
# KEY_2 0       command
EV_KEY  KEY_3   1       /dev/input/event0
# KEY_3 1       command
EV_KEY  KEY_3   0       /dev/input/event0
# KEY_3 0       command
EV_KEY  KEY_RED 1       /dev/input/event0
# KEY_RED       1       command
EV_KEY  KEY_RED 0       /dev/input/event0
# KEY_RED       0       command
EV_KEY  KEY_GREEN       1       /dev/input/event0
# KEY_GREEN     1       command
EV_KEY  KEY_GREEN       0       /dev/input/event0
# KEY_GREEN     0       command
EV_KEY  KEY_YELLOW      1       /dev/input/event0
# KEY_YELLOW    1       command
EV_KEY  KEY_YELLOW      0       /dev/input/event0
# KEY_YELLOW    0       command
EV_KEY  KEY_BLUE        1       /dev/input/event0
# KEY_BLUE      1       command
EV_KEY  KEY_BLUE        0       /dev/input/event0
# KEY_BLUE      0       command
  1. Create a trigger definitions file, such as /etc/triggerhappy/triggers.d/triggerhappy.conf
    This specifies what actions should be performed when a given key is pressed.
    The file can have any name, but it needs to be in /etc/triggerhappy/triggers.d/
    You will find examples in /etc/triggerhappy/triggers.d/triggerhappy.conf.examples.
    More information about the syntax of the configuration file can be found at http://manpages.ubuntu.com/manpages/bionic/man1/thd.1.html

    Here is an example of the contents:
    KEY_RED 1 /usr/bin/mpc stop
    KEY_GREEN 1 /usr/bin/mpc repeat on

    Run this interactively and display the output:
    thd --dump --triggers /etc/triggerhappy/triggers.d /dev/input/event*
    (This will look for trigger definitions in any file in the /etc/triggerhappy/triggers.d directory.)

    Then press the red key – you should see something similar to the following:
    EV_KEY KEY_RED 1 /dev/input/event0
    KEY_RED 1 command
    Executing trigger action: /usr/bin/mpc stop
    volume:100% repeat: off random: off single: off consume: off
    EV_KEY KEY_RED 0 /dev/input/event0
    KEY_RED 0 command
  1. You can list all the key events that Triggerhappy will react to by running this command:
    thd --listevents

    Note that this also includes additional events of the form BTN_TRIGGER_HAPPYnn so if, for example, you wanted to perform an action when the button labelled ‘FOOTBALL’ on the remote control is pressed you could add something similar to the following to the keymap file in /etc/rc_keymaps:
    0x107017 = "BTN_TRIGGER_HAPPY10" # Button labelled 'FOOTBALL'
    and then add an entry for BTN_TRIGGER_HAPPY10 in /etc/triggerhappy/triggers.d/triggerhappy.conf.
  1. Enable the triggerhappy service and start it:
    systemctl enable triggerhappy
    systemctl start triggerhappy
    systemctl status triggerhappy

    This should look similar to the following:

root@runeaudio+R e4:~ # systemctl enable triggerhappy
root@runeaudio+R e4:~ # systemctl start triggerhappy
root@runeaudio+R e4:~ # systemctl status triggerhappy
* triggerhappy.service - triggerhappy global hotkey daemon
     Loaded: loaded (/usr/lib/systemd/system/triggerhappy.service; enabled; vendor preset: disabled)
     Active: active (running) since Fri 2020-08-07 15:59:15 BST; 6s ago
   Main PID: 2247 (thd)
      Tasks: 1 (limit: 2140)
     CGroup: /system.slice/triggerhappy.service
             `-2247 /usr/sbin/thd --triggers /etc/triggerhappy/triggers.d/ --socket /run/thd.socket --user nobody --deviceg>

Aug 07 15:59:15 runeaudio systemd[1]: Starting triggerhappy global hotkey daemon...
Aug 07 15:59:15 runeaudio systemd[1]: Started triggerhappy global hotkey daemon.
lines 1-10/10 (END)...skipping...
* triggerhappy.service - triggerhappy global hotkey daemon
     Loaded: loaded (/usr/lib/systemd/system/triggerhappy.service; enabled; vendor preset: disabled)
     Active: active (running) since Fri 2020-08-07 15:59:15 BST; 6s ago
   Main PID: 2247 (thd)
      Tasks: 1 (limit: 2140)
     CGroup: /system.slice/triggerhappy.service
             `-2247 /usr/sbin/thd --triggers /etc/triggerhappy/triggers.d/ --socket /run/thd.socket --user nobody --deviceg>

Aug 07 15:59:15 runeaudio systemd[1]: Starting triggerhappy global hotkey daemon...
Aug 07 15:59:15 runeaudio systemd[1]: Started triggerhappy global hotkey daemon.

And that’s it all done!

Further information

Here are some articles that I found useful when setting up my system:

Further notes on installing Triggerhappy on RuneAudio

If you run:
pacman -S Triggerhappy
then you get:
error: target not found: Triggerhappy

Although Triggerhappy exists in the Archlinux repository, when I tried running makepkg on it I got an error indicating that armv7h architecture isn’t supported.

Nishil Kohli has described how to compile Triggerhappy for Archlinux at https://nishil.in/blog/Turn-on-off-appliances-using-a-TV-remote-and-Raspbery-Pi/ . (In fact he is using RuneAudio.) I followed a process similar what he described to compile Triggerhappy, but I needed to use a different approach to set it up to run as a service. This is the process that I tried:


cd ~
mkdir triggerhappywork
cd triggerhappywork
pacman -Sy                    # update the repos
pacman -S guile make gcc git  # install dependencies and build tools
git clone https://github.com/wertarbyte/triggerhappy
cd triggerhappy
make
make install
copy /root/triggerhappywork/triggerhappy/systemd/triggerhappy.s* /usr/lib/systemd/system/

This all worked fine with RuneAudio+R e3, and it would work interactively with RuneAudio+R e4, but when I tried to start the service on e4 it did nothing until it eventually timed out and failed – so that’s why I adopted the process that I described above.

Written by Vaughan

Leave a Reply

Your email address will not be published. Required fields are marked *