Holiday music streamer

One of the standing traditions in my household is to get thoroughly immersed in Christmas music during the holiday season. For years, this has involved Pandora streams and Raspberry Pis. This year, I built on that tradition with a little help from some Adafruit gadgets:

The speaker bonnet:

Adafruit I2S 3W Stereo Speaker Bonnet for Raspberry Pi - Mini Kit

and a membrane matrix pad

Membrane 3x4 Matrix Keypad + extras - 3x4

This time around, I upgraded the music delivery system from Pandora to a SiriusXM based approach using andrew0’s code on github that creates a SiriusXM server on your RPi. Some tweaks were needed to bring the code up to date and I moved passwords and tokens to a secrets.py file along the lines of this circuitpython tutorial from Adafruit. Then using the matrix pad tutorial I was able to create a script to connect the keypad to different stations, including an on/off button and volume control. Lastly, I 3D printed a wall mount for the pad that allows me to “change” the buttons so that I don’t have to remember which buttons are which.

Don’t talk about my lack of alignment skills.

Now, I’ve got the ability to play Christmas music while I’m baking cookies in the kitchen (I’m up to 8 dozen to date). Here’s the setup (pre 3D printed wall mount.

If you’re interested in reproducing this setup, I start the SiriusXM server using systemctl and then start the code below manually. If I run that code in a GNU Screen, then I can detach the screen and still keep the code running.

import os
import subprocess
import time
import digitalio
import board
import adafruit_matrixkeypad

cols = [digitalio.DigitalInOut(x) for x in (board.D5, board.D6, board.D12)]
rows = [digitalio.DigitalInOut(x) for x in (board.D27, board.D22, board.D23, board.D24)]
keys = ((1,2,3),(4,5,6),(7,8,9),('vup',0,'vdown'))

keypad = adafruit_matrixkeypad.Matrix_Keypad(rows, cols, keys)

check_keypad = True

def SiriusActiveQ():
  '''
  Checks systemd to see if siriusxm is active.  
  systemctl returns 0 if active, or 3 if inactive (presumably other exit codes as well)
  '''
  r = subprocess.call(['systemctl','is-active','siriusxm'])
  return (r == 0)

def killVLC():
  '''
  Ensures that vlc is not running
  '''
  os.system('killall vlc')

def SiriusPlay(channel):
  ''' 
  Plays a channel, does not check if channel is valid
  '''
  killVLC()
  subprocess.Popen(['cvlc','http://127.0.0.1:8888/{}.m3u8'.format(channel)])

def speak(statement):
  os.system('espeak -w /tmp/out.wav -ven+f3 -k5 -s150 -a125 "{}" 2>/dev/null'.format(statement))
  os.system('aplay /temp/out.wav')
  #subprocess.call(['espeak','-s','125','-a','150',str(statement)])

def constrain(val, min_val, max_val):
  return min(max_val, max(min_val, val))
def setvolume(volume):
  vol = constrain(volume,0,90) # Just making sure
  subprocess.run(['amixer', 'sset','PCM','{}%'.format(vol)])

def process_keypress(key):
  global volume
  if (key=='vup'):
    volume = constrain(volume + 10,0,90)
    setvolume(volume)
  elif (key=='vdown'):
    volume = constrain(volume -10, 0, 90)
    setvolume(volume)
  elif (key==0):
    killVLC()
  elif (key==1):
    SiriusPlay(9342)
  elif (key==2):
    SiriusPlay(9483)
  elif (key==3):
    SiriusPlay(9403)
  elif (key==4):
    SiriusPlay(9343)
  elif (key==5):
    SiriusPlay(9521)
  elif (key==6):
    SiriusPlay(9489)
  elif (key==7):
    SiriusPlay(9344)
  elif (key==8):
    SiriusPlay('nprnow')
  elif (key==9):
    SiriusPlay('symphonyhall')
  else:
    speak('I do not understand.')

print("Setting default volume to 75%")
volume = 75
setvolume(volume)

print("Do something")
while True:
  try:
    if check_keypad:
      keys = keypad.pressed_keys
      if keys:
        check_keypad = False
        process_keypress(keys[0])
        check_keypad = True
      time.sleep(0.1)
  except (KeyboardInterrupt, EOFError, SystemExit):
    break

I’m excited about this platform since it opens up a lot of other streaming services via VLC. I do need to figure out some volume issues, as supposedly I can get much more sound out of the speaker bonnet than I am at the time. For now, I am pretty psyched that this system has introduced me to Dominic the Christmas Donkey.

Leave a Reply

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

This site uses Akismet to reduce spam. Learn how your comment data is processed.