Saturday, November 16, 2013

Converting Raspberry PI to Music Center with Remote

Hooking New Stuff to Legacy Hardware 

Long time ago I bought Onkyo TX-SV535 receiver/amplifier with a couple of decent speakers. I occasionally used it to listen radio or CD's spinning on another Onkyo device -  DX-C320.

I've realized lately that I could have much more fun with all that legacy hardware when got my first Raspberry PI device.

Installing Music Player Daemon (MPD) and Music Player Client (MPC) was not a problem. I've even managed to built MPD from sources to make sure that I can easily integrate it with Spotify, SoundCloud, last.fm and virtually any existing audio format.

It all worked well, but it was irritating a bit that I needed to use a native Onkyo's remote control for the receiver and MPC running on my mobile device or on a desktop to control Raspberry's MPD.

Then I came across the Adafruit's IR chip and realized that this is what I needed. Hooking up the chip to Raspberry's GPIO was easy - I used female to female connectors, drilled a hole in a Raspberry's clear case, used a bit of heat shrink tubing to make sure that the IR receiver can be fixed on the top of the case.

This is how everything looks together:


Raspberry's audio output is connected directly to Onkyo's Phono input, which has a preamp that does an excellent work of boosting the audio signal and eliminates a necessity of having a sound card on Raspberry. Even when I listen an Internet radio station, it sounds rich and groovy.  

Making IR receiver to understand Onkyo's remote was a little bit harder, but eventually I've made it working.

Tuning IR to Onkyo's Remote

The first step was to install LIRC tools that have not been installed on my Raspberry OS by default:

   sudo apt-get install lirc

You'll also need to make sure that lirc_rpi driver is loaded before you can do anything:

   sudo modprobe lirc_rpi
 
To make the module loaded at boot time add it to /etc/modules.
The next step is to record codes generated by remote's buttons that you want to use. Stop lircd daemon if it's running and use  irrecord command line utility to record the codes:
 
  sudo /etc/init.d/lircd stop
  irrecord -d /dev/lirc0 ./lircd.conf 
 
Follow instructions provided by irrecord and chose the buttons that you need.

This is how my lircd.conf file looks like:

begin remote

  name  ONKYO-RC-287S
  flags RAW_CODES|CONST_LENGTH
  eps            30
  aeps          100

  gap          108090

      begin raw_codes

          name KEY_POWER
             9017    4480     624     509     579    1663
              581     555     576     529     600    1670
              577     530     600    1667     579    1662
              583    1661     598     537     571    1670
              599    1668     579     531     598    1678
              569    1666     572     562     576     530
              600     536     572    1669     598     536
              581     555     574     531     600     534
              582     554     576    1664     625    1618
              598     536     584    1658     599    1675
              576    1667     571    1672     592    1677
              574

          name KEY_LEFT
             9054    4447     601     533     575    1667
              601     533     625     509     579    1664
              625     509     578    1672     616    1617
              609    1659     579     538     604    1664
              570    1676     622     501     574    1668
              581    1661     607     527     581    1660
              606    1673     565    1667     631    1610
              606     530     577     556     574    1677
              570     556     573     540     605     526
              577     556     573     539     603    1666
              569    1672     626     508     583    1652
              631

          name KEY_RIGHT
             9040    4461     600     534     582    1658
              601     535     572     562     578    1663
              573     562     577    1663     588    1659
              606    1660     576     531     609    1659
              578    1665     591     543     576    1666
              581    1661     608     526     581     553
              576    1666     583    1660     606    1660
              589     525     604     527     580    1667
              600     540     569    1659     608     529
              579     554     575     533     606    1662
              575    1675     572     555     574    1667
              579

          name KEY_PLAY
             9016    4485     628     505     581    1660
              575     559     581     528     609    1657
              583     527     601    1670     579    1666
              570    1665     603     532     575    1665
              604    1667     581     526     601    1666
              582    1661     576     558     580     528
              602     533     574     559     581     527
              602    1667     580     527     603    1667
              580     526     603    1672     581    1673
              563    1666     603    1668     577     526
              601    1673     572     527     602    1665
              581

          name KEY_PAUSE
             9072    4439     569     555     574    1666
              594     541     576     532     606    1664
              574     532     606    1662     576    1677
              570    1663     604     530     579    1661
              607    1663     575     533     605    1672
              565    1671     577     553     575    1668
              579     555     574    1676     571    1663
              606     529     579     554     575    1668
              580     554     608     498     608    1669
              567     534     605     530     579    1661
              606    1662     576     532     616    1653
              574

          name KEY_LEFTALT
             9015    4488     573     561     579    1660
              575     560     579     528     601    1677
              571     527     601    1669     578    1663
              574    1665     603     533     583    1660
              599    1668     579     528     601    1669
              578    1665     574     562     575     530
              599    1668     580     529     599     536
              572    1670     598     536     571    1669
              612     528     598    1649     600     526
              581    1660     607    1672     565     532
              608    1661     576     531     608    1659
              578

          name KEY_RIGHTALT
             9044    4466     594     529     579    1664
              603     529     579     556     573    1669
              579     556     572    1669     587    1656
              609    1667     567     538     600    1670
              566    1676     583     546     572    1668
              577    1665     601     533     573    1669
              600     534     574     561     579     528
              601    1668     577     531     600    1668
              580     528     600     544     564    1668
              598    1670     579    1664     573     561
              578    1672     563     561     579    1664
              572

          name KEY_VOLUMEUP
             9036    4464     597     537     579    1663
              602     532     575     560     578    1662
              573     567     573    1674     569    1663
              599    1668     578     531     605    1665
              571    1671     572     561     576    1667
              579    1662     603     541     566     560
              578    1661     573     563     575     534
              603     530     576     558     580    1673
              561     562     575    1668     577     556
              572    1670     573    1668     597    1673
              573    1669     574     560     577    1663
              582

          name KEY_VOLUMEDOWN
             9032    4470     603     528     579    1666
              605     529     574     559     580    1673
              562     563     576    1615     627    1668
              595    1677     567     533     603    1663
              571    1672     573     575     563    1666
              578    1662     603     533     574    1667
              598    1679     565     534     603     538
              569     559     579     528     598    1670
              574     534     605     529     604     541
              558    1674     572    1669     606    1662
              572    1678     569     562     578    1661
              579

      end raw_codes

end remote
 
Copy this file to /etc/lirc/lircd.conf to make it available for lircd daemon when it starts next time.

You'll also need to change /etc/lirc/hardware.conf to make it working with /dev/lirc0 device. The only two changes that I've made are below:

   #DRIVER="UNCONFIGURED"
   DEVICE="/dev/lirc0"
 
'DRIVER' option was commented out and 'DEVICE' parameter was set to the IR device - /dev/lirc0.

If everything is done correctly, you can start lircd daemon now and check if IR receiver recognizes the configured keys using irw command:

   sudo /etc/init.d/lirc start
   irw 

Press configured buttons on remote sequentially and observe irw's output. If the irw shows all the keys that you've configured, proceed to binding the keys to actions using irexec daemon. You'll need to create a configuration file for irexec called lircrc and copy it it to /etc/lirc/lircrc. My lircrc file is provided below. You can find detailed description of the lircrc's file format here.

begin
   remote = ONKYO-RC-287S 
   prog   = irexec
   button = KEY_POWER
   config = sudo shutdown -h now
end
begin
   remote = ONKYO-RC-287S 
   prog   = irexec
   button = KEY_RIGHT
   config = /usr/bin/mpc next
end
begin
   remote = ONKYO-RC-287S 
   prog   = irexec
   button = KEY_LEFT
   config = /usr/bin/mpc prev
end
begin
   remote = ONKYO-RC-287S 
   prog   = irexec
   button = KEY_PLAY
   config = /usr/bin/mpc toggle
end
begin
   remote = ONKYO-RC-287S 
   prog   = irexec
   button = KEY_PAUSE
   config = /usr/bin/mpc pause
end
begin
   remote = ONKYO-RC-287S 
   prog   = irexec
   button = KEY_LEFTALT
   config = /home/pi/load_playlist.py 0
end
begin
   remote = ONKYO-RC-287S 
   prog   = irexec
   button = KEY_RIGHTALT
   config = /home/pi/load_playlist.py 1
end
begin
   remote = ONKYO-RC-287S 
   prog   = irexec
   button = KEY_VOLUMEUP
   repeat = 1
   config = mpc volume +1
end

begin
   remote = ONKYO-RC-287S 
   prog   = irexec
   button = KEY_VOLUMEDOWN
   repeat = 1
   config = mpc volume -1
end
 
KEY_POWER is used to shutdown Raspberry, for almost all other keys MPC command line utility is used to control MPD. I didn't find a simple way of  loading a next or previous playlist from a server and had to write a small Python script called load_playlist.py to do that:

/home/pi/load_playlist.py
================================================================
 
#!/usr/bin/python

# Load next/previous playlist from MPD server using MPC

import os
import sys
import re

CONFIG_FILE=os.path.expanduser("~/.load_playlist/current")

if len(sys.argv) < 2:
   sys.exit("Usage: %s n [config_file]\n\tn  0 - prev, 1 - next\n\tconfig_file contains current playlist" % sys.argv[0])

cf = CONFIG_FILE
next = True
if len(sys.argv) > 2:
   cf = sys.argv[2]

if sys.argv[1] == '0':
   next = False    

if not os.path.isfile(cf):
   if not os.path.isdir(os.path.dirname(cf)):
      os.system("mkdir -p %s" % os.path.dirname(cf))
   os.system("echo '' >%s" % cf)

if not os.path.isfile(cf):
   sys.exit("Can's create file %s" % cf)   
    
with file(cf) as f:
    s = f.read()

s = re.sub(r'[\n\r]', "", s)
print "S='%s'" % s 

ls = os.popen('mpc lsplaylists').read()
# print ls
lsa = ls.split("\n")
del lsa [-1]
# print lsa 

ind = 0
for i in range(0,len(lsa)-1):
   if (s == lsa[i]):
      if next:
 ind = i+1
      else:
        ind = i-1

if ind < 0:
   ind = len(lsa) - 1

if ind >= len(lsa):
   ind = 0

if ind < 0:
   ind = 0

if ind < len(lsa):
   os.system("mpc clear")
   loaded = os.system("mpc load %s" % lsa[ind])
   if loaded == 0:
      os.system("mpc play")
      os.system("echo %s >%s" % (lsa[ind], cf))




irexec daemon should start automatically when you restart lircd daemon.

That's very much it! Enjoy the quality of your old good HiFi improved by smartness of your PI integrated with IR and WiFi :)

6 comments:

  1. Anybody, could you explain me, why it doesn’t work:
    begin
    prog = irexec
    button = KEY_8
    config = /usr/bin/cvlc http://www.a-1radio.com/listen.pls -I dummy &
    end
    begin
    prog = irexec
    button = KEY_9
    config = /usr/bin/cvlc /home/pi/MUSIC/playlist.xspf --random &
    end

    ReplyDelete
  2. Did you test your keys with irw?

    ReplyDelete
  3. Hi!
    The hardware is working well, also some commands are running perfect, for instance:

    begin
    prog = irexec
    button = KEY_0
    config = sudo reboot
    end

    The only a problem is the VLC doesn't working with IREXEC as I wished.
    AK

    ReplyDelete
  4. Check this one - https://wiki.videolan.org/How_to_Use_Lirc

    It looks like you need to run vlc with rc interface (vlc -rc) to be able to control it through remote.

    I do not use VLC, so if this doesn't work, I don't know what else it could be. It looks like the problem is VLC specific.

    ReplyDelete
  5. Well, it'd be complex!
    That I've found some programs don't work like VLC, for example:
    begin
    button = KEY_7
    prog = irexec
    config = voicecommand -c
    end
    To me it looks like because of LIRC.

    ReplyDelete
  6. LIRC driver works fine, because you're getting keys. The problem most likely is that irexec runs in a different env compare to a normal user. Try to run irexec without -d and see if there are errors. Try to set a full path to voicecommand in 'config'. If a command requires a display you probably need DISPLAY env variable to be set. Permissions might be an issue as well.
    I think, it's the same kind of problem when everything works from a command line, but doesn't work from 'cron'.
    I'm sure, you'll find it :)

    ReplyDelete