Table of contents
I'm using a headless Raspberry Pi as audio player. It is connected to my ancient ;-) Denon amplifier via analog cinch cables.
The operating system on the Raspberry Pi is a stock Raspberry Pi OS Buster. Up to 2018 I used to use a specialized operating system image (Volumio) for that but no longer.
Under the hood there is the MPD (Music Player Daemon) working.
There are a lot of MPD client programs out there, I like ncmpcpp (CLI) and Cantata (GUI) the most these days.
Searching the web I didn't find a client matching my ideas.
So I created one by myself - and rcmpd was born.
I used bash as programming language to make it as easy as possible for others to understand and modify rcmpd by themselves.
Of course there are the usual, obvious commands:
And a not so obvious:
do something with the current songs title/artist
But there is more! Please read on.
There are some informations spoken and it's possible to get some commands "echoed" in words.
Additionally there are the following playlist features:
All of the above functions are reachable with a single button press.
To extend the possibilities I implemented compound keys.
If a playlist has more than ten entries (reachable via buttons 1-9,0) it's possible to select higher ones with compound keys.
E.g. entry 27 could be started with:
OK 2 7 OK
You can load more playlists directly by combining the letters A, B, C, D with the digits to playlists like "A7", "AC1" or "B126".
The list of defined/available playlists and the contents of the current one could be printed on a printer with:
OK MENU EPG OK
More about printing see below.
To make the direct loading of playlists work, the playlists in question have to be prepared a bit:
Using a MPD client on my PC I'm predefining MPD playlists which I would like to manage with the RC with a special naming convention.
Example:
A ~ Various Artists - The ultimate songs B B1 -- Angel Hearts - The first album C24 ~ Alltime favourites Runaways - Hot! The lonely boys - Chicago
All the playlists starting with
can now be loaded with the RC! (The first four in the example above.)
So the above example playlists can be loaded by:
A B OK B 1 OK OK C 2 4 OK
Using a compound key with Power and then one or more digits, a sleep timer with the given time in minutes is started.
For example set a sleep timer of 30 minutes:
OK POWER 3 0 OK
Additionally to the Vol+/- in steps of 5% the volume can be set to 100% by:
OK VOL+ VOL+ OK
to 50% by either of:
OK VOL+ VOL- OK OK VOL- VOL+ OK
and to 0% by:
OK VOL- VOL- OK
If there are external programs/scripts existing named like rcmpd.A (B,C,D,0-9) they can be called by:
OK MENU A OK
A short reference of the possible keys can be printed on a printer with:
OK MENU MENU OK
This is the same list that is shown if rcmpd is called without any parameters.
To increase the WAF (Woman Acceptance Factor) I added those infos in German as well now.
Add a line like the following to your ~/.bashrc file:
export RCMPD_LANGUAGE=DE
To activate it just logoff and login again or type the above in your current shell session.
The optional printing features are implemented by producing Postscript output which is converted to PDF and sent to the printer.
The most current output file is stored in /tmp/rcmpd-printout.pdf (configured as variable PRINTOUT in the script).
So it's possible to use the file for other purposes as well.
Here are two example prints, the short manual and playlist infos.
(Click to see larger picture.)
This topic is showing the assignments I configured for my own IR Remote Controls.
That is a simple text description here, not the configuration itself! More about the real configuration follows.
Both can be used in parallel of course.
Power shutdown / cancel delayed shutdown / set sleep timer Mute mute / unmute Menu toggle audible command descriptions on/off / call external scripts / print keys TV speak info: current time EPG speak info: collection (available playlists) / print playlists Vol+ Vol- increase/decrease volume (in 5% steps) Ch+ Ch- next/previous playlist Pinnacle speak info: volume and state of "repeat" A B C load playlist "A", "B", "C" D speak info: playlist Back speak info: channel/album Loop toggle "repeat" Fullscreen speak info: current track/song Pause toggle pause/play Play Stop start, stop playback / stop currently spoken text Rew FFwd seek 30 seconds back/forward Skip+ Skip- next/previous track (within playlist) Record save current song info (title/artist) in '/home/pi/rcmpd.record' 1-9, 0 1st .. 10th track (within playlist) OK start/stop multiple-key commands (build from A,B,C,D,0-9, POWER, MENU, EPG, VOL)
with only these commands:
KEY_POWER shutdown in 1 minute / cancel shutdown / set sleep timer KEY_VOLUMEUP KEY_VOLUMEDOWN increase/decrease volume (in 5% steps) KEY_CHANNELUP=KEY_NEXT next/previous track (within playlist) KEY_CHANNELDOWN=KEY_PREVIOUS KEY_SEARCH=KEY_SCREEN speak info: current track/song KEY_MUTE=KEY_PAUSE toggle pause/play KEY_MODE=KEY_STOP stop
So I created a new repo on Github: https://github.com/gchriz/rcmpd/.
Issues and comments can be posted there.
Here I would like to describe how the parts are playing together. Additional infos are shown in the installation section.
First there is the software LIRC. It
In LIRC's configuration file(s) lircd.conf and/or preferred lircd.conf.d/*.conf there are the used remote control(s) defined.
Shortened example:
begin remote name Pinnacle_RC1144201 ... begin codes power 0x6E2D menu 0x6EE7 mute 0x6E1E stop 0x6E2B play 0x6ED1 pause 0x6E2C ...
You can see the name of the RC and some of the known buttons.
LIRC provides - beneath others - a simple program irexec.
irexec is able to communicate with the above running lircd and gets infos about a pressed button.
To know what to do with that button info it has a configuration file too: .lircrc.
That configuration file maps button-presses to actions, for example starting a program.
In my case I map all buttons to rcmpd - with an appropriate parameter to distinguish them.
Shortened example:
begin prog = irexec remote = Pinnacle_RC1144201 button = power config = /home/pi/bin/rcmpd power repeat = 0 end begin prog = irexec remote = Pinnacle_RC1144201 button = pause config = /home/pi/bin/rcmpd pause repeat = 0 end
You can see the matching name of the RC(!) and the matching buttons as well.
So on every button press rcmpd gets called with the appropriate function as parameter.
That file can be crafted manually or automaticall, described a bit later.
To get this working irexec needs to run in background and wait for button infos.
Finally within rcmpd there is a table or block for every used remote control.
This is your individual setup - part 1
Example:
#********************************************************************* # You need to define the choosen keys of your remote controls here! # # Used for the creation of .lircrc (and as reference for humans...) # # Need to match the remote's names and the button names from the files # /etc/lirc/lircd.conf and/or /etc/lirc/lircd.conf.d/*.conf! # Edit the current ones below, add or replace with your own RC(s). #********************************************************************* define_remotes() { REMOTES=( [Pinnacle_RC1144201]=" mute power menu tv epg a b c d vol+ vol- pinnacle ch+ ch- ok back loop fullscreen pause play stop ffwd rew skip+ skip- rec 1 2 3 4 5 6 7 8 9 0 cancel " # The definition below uses an "aliasing" feature: # If an RC sends a button X but you want rcmpd to behave like button Y # then write X=Y [DENON_RC_126]=" KEY_POWER KEY_VOLUMEDOWN KEY_VOLUMEUP KEY_CHANNELUP=KEY_NEXT KEY_CHANNELDOWN=KEY_PREVIOUS KEY_SEARCH=KEY_SCREEN KEY_MUTE=KEY_PAUSE KEY_MODE=KEY_STOP " ) }
Later on in rcmpd there is function button_menu()
That is your individual setup - part 2 - if really needed
There are the mappings from "button" to internal function where the commands are executed then:
#------------------------------------------------------------- # The assignments of RC buttons to commands in this program. # Here you can do your "setup". #------------------------------------------------------------- MUTE|KEY_MUTE) cmd_mute ;; VOL+|KEY_VOLUMEUP) cmd_volume_up ;; VOL-|KEY_VOLUMEDOWN) cmd_volume_down ;; PLAY|KEY_PLAY) cmd_play ;; STOP|KEY_STOP) cmd_stop ;; PAUSE|KEY_PAUSE) cmd_pause ;; LOOP|KEY_MEDIA_REPEAT) cmd_toggle_repeat ;; SKIP+|KEY_NEXT) cmd_next_track ;; SKIP-|KEY_PREVIOUS) cmd_previous_track ;; 0|1|2|3|4|5|6|7|8|9) cmd_digit $btn ;; KEY_0|KEY_1|KEY_2|KEY_3|KEY_4|KEY_5|KEY_6|KEY_7|KEY_8|KEY_9) cmd_digit $btn ;; CH+|KEY_CHANNELUP) cmd_next_playlist ;; CH-|KEY_CHANNELDOWN) cmd_previous_playlist ;; A|B|C|KEY_A|KEY_B|KEY_C) cmd_ABC $btn ;; REC|RECORD|KEY_RECORD) cmd_record ;; MENU|KEY_MENU) cmd_toggle_speech ;; EPG|KEY_EPG) cmd_info_collection ;; # of playlists D|KEY_D) cmd_info_playlist ;; # current playlist BACK|KEY_BACK) cmd_info_station ;; # respective "album" FULLSCREEN|KEY_SCREEN) cmd_info_track ;; PINNACLE) cmd_info_state ;; TV|KEY_TV) cmd_info_time ;; POWER|KEY_POWER) cmd_poweroff ;; #-------------------------------------------------------------
a computer running an operating system hosting MPD, LIRC and Bash - that is usually some flavour of UNIX/Linux
an infrared receiver connected to that computer
- via GPIO: in my case it's an IR detector (e.g. Vishay TSOP31238, less than 2,- €)
- or via USB (not in this description here, but probably working the same way)
an IR remote control - supported by LIRC
and optionally a printer
mpd configured and running
mpc standard CLI client for sending commands to mpd
lircd running and configured (more details in the LIRC section below):
* /etc/lirc/lirc_options.conf driver and device configuration. * /etc/lirc/lircd.conf main config file. Just includes further *.conf files * /etc/lirc/lircd.conf.d/*.conf defined remote control(s) (downloaded from http://lirc.sourceforge.net/remotes/ or recorded with irrecord -l) * ~/.lircrc user's command assignments
several standard Linux tools (grep, awk, sed, sort, tr, cut, ...)
optional (for Text To Speech): espeak
optional (for printing): Cups (with lp), Ghostscript (with gs and ps2pdf), paps
Note
Optional patch for paps
The original paps package (creating Postscript for printing) in version 0.6.8-6 doesn't have a --title option for filling the header on the printed document with own text.
It shows the filename - or the string "stdin" - instead.
Since I really wanted to be able to place variable text in the header I created a patch for that. It's described at https://www.ziemski.net/paps
But of course rcmpd is working with the unpatched paps as well - just without the individual header.
Save rcmpd into a directory available via $PATH (e.g. in ~/bin).
Make it executable, e.g. with chmod u+x rcmpd
execute rcmpd --checkinstall to do a base installation check
Install-and-configure-LIRC-for-your-RC (see below)
in file rcmpd itself
Create an appropriate ~/.lircrc file for handling the RC commands
rcmpd --createlircrc
(Re)start irexec to let it know about the new ~/.lircrc: rcmpd --restartirexec
Test it in your shell by rcmpd <command> with <command> being any of the defined commands above.
If all works fine you should make irexec autostart.
That may be done via an entry in /etc/rc.local like this:
su - pi -c "/usr/bin/irexec --daemon /home/pi/.lircrc"
Or if playback should start immediately:
su - pi -c "/usr/bin/irexec --daemon /home/pi/.lircrc ; mpc play"
You should use a "normal" user (here: pi) for that.
rcmpd is easy to call.
The first iexample is the normal operation format and the others are for installation/configuration purposes:
rcmpd <command> ... manages a command, e.g. from an infrared RC buttonpress rcmpd --checkinstall checks some aspects of the install (prerequisites) rcmpd --createlircrc creates /home/pi/.lircrc if not existing rcmpd --restartirexec restarts irexec after changes on .lircrc rcmpd --showsonginfos shows the "recorded" infos in '/home/pi/rcmpd.record' rcmpd --listplaylists lists all playlists and the contents of current one rcmpd without any parameters this usage info and a short summary of keys is shown
If the infrared receiver is connected to the Raspberry Pi via GPIO pins (and not via USB) the Raspberry Pi needs to know the choosen GPIO.
That can be done in /boot/config.txt:
# Uncomment this to enable infrared communication. dtoverlay=gpio-ir,gpio_pin=17
Next the software part:
Install the lirc package:
sudo apt install lirc
The above installation of lirc creates some configuration files in /etc/lirc/.
At least on Raspberry Pi's it's a good idea to change driver and device in lirc_options.conf:
Orignal: driver = devinput device = auto New: driver = default device = /dev/lirc0
Since we don't use the devinput driver the matching config file in /etc/lirc/lircd.conf.d/ should be disabled by renaming it:
cd /etc/lirc/lircd.conf.d sudo mv devinput.lircd.conf devinput.lircd.conf.dist
Now check if there is already a LIRC configuration file for your RC, for example here: http://lirc.sourceforge.net/remotes
and put it as a nicely named *.conf file into the directory:
/etc/lirc/lircd.conf.d/
sudo irrecord --list-namespace sudo irrecord -d /dev/lirc0 /etc/lirc/lircd.conf.d/this_special_remote.conf
Finally (re)start lirc:
sudo systemctl restart lircd
and test your RC:
irw
==> press some keys on the RC and watch your shell window ... Stop irw with <Ctrl-C>
If there are technical problems you might want to use the following command for further testing:
mode2 -d /dev/lirc0