Using an iMon Front Panel with MPD

The Soundgraph iMon panel has buttons for play, next, volume, etc and a 16 character by two line VFD.

Display

Install Components for the Display

To make use of the display with MPD as part of a music playing appliance we need to install LCDproc which is a daemon for driving displays:

sudo apt-get install LCDproc

We will also be using several python packages to drive information from MPD to LCDproc. Install the python-mpd package:

sudo apt-get install python-mpd

Install the lcdproc and mpdlcd packages from PIP

sudo pip install lcdproc mpdlcd

Configure the Display

By default LCDproc loads a configuration from /etc/LCDd.conf. Create a configuration file:

sudo nano /etc/LCDd.conf

and make it something like the following:

# LCDd.conf -- configuration file for the LCDproc server daemon LCDd
#
# This file contains the configuration for the LCDd server.
#
# The format is ini-file-like. It is divided into sections that start at
# markers that look like [section]. Comments are all line-based comments,
# and are lines that start with '#' or ';'.
#
# The server has a 'central' section named [server]. For the menu there is
# a section called [menu]. Further each driver has a section which
# defines how the driver acts.
#
# The drivers are activated by specifying them in a driver= line in the
# server section, like:
#
# Driver=curses
#
# This tells LCDd to use the curses driver.
# The first driver that is loaded and is capable of output defines the
# size of the display. The default driver to use is curses.

[server]

# Soundgraph/Silverstone VFD
Driver=imon
DriverPath=/usr/lib/arm-linux-gnueabihf/lcdproc/

# Tells the driver to bind to the given interface
# Bind=127.0.0.1

# Listen on this specified port; defaults to 13666.
# Port=13666

# If yes, the the serverscreen will be rotated as a usual info screen. If no,
# it will be a background screen, only visible when no other screens are
# active. The special value 'blank' is similar to no, but only a blank screen
# is displayed. [default: on; legal: on, off, blank]
ServerScreen=no

# Hello message: each entry represents a display line; default: builtin
Hello=" Welcome to     "
Hello=" MoodeAudio     "

# GoodBye message: each entry represents a display line; default: builtin GoodBye="Goodbye       "
GoodBye=""

ReportToSyslog=yes


[imon]

# Character map to to map ISO-8859-1 to the displays character set.
# [default: none; legal: none, hd44780_euro, upd16314, hd44780_koi8_r,
# hd44780_cp1251, hd44780_8859_5 ] (upd16314, hd44780_koi8_r,
# hd44780_cp1251, hd44780_8859_5 are possible if compiled with additional
# charmaps)
CharMap=none

# select the device to use
Device=/dev/lcd0

# display dimensions
Size=16x2

You will need to restart LCDproc when making changes. This can be done using:

sudo service LCDd restart

mpdlcd also uses a configuration file which by default is /etc/mpdlcd.conf. Create a configuration file:

sudo nano /etc/mpdlcd.conf

and enter the following:

[display]

# MPD data refresh rate
refresh = 0.5

# LCDd screen name for MPDlcd
lcdproc_screen = MPD

# When to enable backlight:
# - always: always on (default)
# - never: never on
# - play: when playing
# - playpause: when playing or in pause
backlight_on = play

# Settings for changing the screen priority when music is playing or not
priority_playing = foreground
priority_not_playing = background


[patterns]

# List your patterns here
# You can use line continuations to simulate line breaks.

pattern1 = {state} {song format="%(artist)s - %(title)s"} {elapsed}

pattern2 = {song format="%(artist)s",speed=4} {elapsed}
{song format="%(title)s",speed=2} {state}

pattern3 = {song format="%(artist)s",speed=4}
{song format="%(album)s - %(title)s",speed=2}
{state} {elapsed} / {total}

pattern4 = {song format="%(artist)s",speed=4}
{song format="%(album)s",speed=4}
{song format="%(title)s",speed=2}
{elapsed} {state} {remaining}


[connections]

# MPD server
mpd = localhost:6600

# LCDd server
lcdproc = localhost:13666


[logging]

# Log level - debug, info, warning, error
loglevel = info

# Enable syslog
syslog = 1

# Log to the 'daemon' facility
syslog_facility = daemon


# vim:set ft=dosini et ts=4:

Lastly to make mpdlcd start automatically whenever the system restarts we need to create an init script for it:

sudo nano /etc/init.d/mpdlcd

and enter the following:

#!/bin/sh -
#
# mpdlcd initscript for mpdlcd
# by Stefaan Verfaillie
#
### BEGIN INIT INFO
# Provides: mpdlcd
# Required-Start: $syslog $LCDd $mpd
# Required-Stop: $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: MPD client for lcdproc
# Description: Display MPD status
### END INIT INFO
#
#
#

LCDPROC_SERVER=${LCDPROC_SERVER:-}
MPD_SERVER=${MPD_SERVER:-}
LOGLEVEL=${LOGLEVEL:-info}
SYSLOG_FACILITY=${SYSLOG_FACILITY:-daemon}

PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
DAEMON=/usr/local/bin/mpdlcd
PIDFILE=/var/run/mpdlcd.pid
NAME="mpdlcd"
DESC="mpdlcd"
DAEMON_OPTS="--lcdproc=\"${LCDPROC_SERVER}\" --mpd=\"${MPD_SERVER}\" --loglevel=\"${LOGLEVEL}\" --syslog"
DAEMON_OPTS="--loglevel=${LOGLEVEL} --syslog"

test -x $DAEMON || (echo "$DAEMON does not exist" && exit 0)

set -e

case "$1" in
start)
echo -n "Starting ${DESC}: "
start-stop-daemon --start --background --quiet --pidfile=$PIDFILE -b --make-pidfile --exec ${DAEMON} -- ${DAEMON_OPTS}
echo "${NAME}."
;; 
stop)
echo -n "Stopping $DESC: "
start-stop-daemon --stop --oknodo --pidfile=${PIDFILE}
echo "$NAME."
;;
restart|force-reload)
echo -n "Restarting $DESC: "
$0 stop
sleep 1
$0 start
;;
*)
N=/etc/init.d/$NAME
# echo "Usage: $N {start|stop|restart|reload|force-reload}" >&2
echo "Usage: $N {start|stop|restart|force-reload}" >&2
exit 1
;;
esac

exit 0

Note the “$LCDd $mpd” on the line “# Required-Start: “. This indicates that this service is dependent on the mpd and LCDproc services.

Make the script executable:

sudo chmod +x /etc/init.d/mpdlcd

Enable the service:

sudo systemctl enable mpdlcd.service

More information about mpdlcd can be found here.

Using the iMon Buttons

Having got the kernel module to correctly detect the iMon buttons, we will use Python to capture button presses and control MPD via the command line client, mpc.

Create our script:

nano mpdkeys.py

and add:

#!/usr/bin/python
from evdev import InputDevice, list_devices
import os
import subprocess 

# set this to the string name of the device
DEVICE_NAME = "iMON Panel, Knob and Mouse(15c2:ffdc)"

# functions to interact with the mpc CLI client     
def MPD_stop():
   subprocess.Popen("mpc stop", shell=True)
def MPD_playpause():
   subprocess.Popen("mpc toggle", shell=True)
def MPD_next():
   subprocess.Popen("mpc next", shell=True)
def MPD_prev():
   subprocess.Popen("mpc prev", shell=True)
def MPD_volumeup():
   subprocess.Popen("mpc volume +5", shell=True)
def MPD_volumedown():
   subprocess.Popen("mpc volume -5", shell=True)
def SYS_halt():
   os.system("halt") 

# function to keycode binding
fun_tbl = {
  128  : MPD_stop,      #  KEY_STOP
  164  : MPD_playpause, #  KEY_PLAYPAUSE
  407  : MPD_next,      #  KEY_NEXT
  412  : MPD_prev,      #  KEY_PREVIOUS
  115  : MPD_volumeup,  #  KEY_VOLUMEUP
  114  : MPD_volumedown,#  KEY_VOLUMEDOWN
  113  : MPD_playpause, #  KEY_MUTE
} 

# listen for events
for dev in [ InputDevice(fn) for fn in list_devices()]:
   print dev.name
   if dev.name == DEVICE_NAME:
      for event in dev.read_loop():
         print event.value
         if event.value == 1:
            try:
               fun_tbl[event.code]()
            except KeyError:
               print "Action for %d code is not defined" % (event.code)

Make it executable:

chmod +x ./mpdkeys.py

Test it:

./mpdkeys.py

Press any key on the iMon panel and the corresponding function should be called. If any button is not mapped then you will see a message in the console.

When it is working correctly copy it to a good place for user created scripts, eg:

sudo cp mpdkeys.py /usr/local/bin

To make the script run automatically when the system boots, edit the rc.local file:

sudo nano /etc/rc.local

and add the following right before the line at the end of the file that contains “exit 0”:

/usr/local/bin/mpdkeys.py > /dev/null 2>&1

References

Using Python with keyboard input: http://morethanuser.blogspot.com/2015/10/python-banana-pi-ir-event-handler.html