Tag Archives: squeezebox

Moving RPizeBox to git

500D_1901

Now I have the proof of concept for the RPi, I wanted to improve the code and have long term plans to make it remember tracks we skip, as well as allowing a blacklist!  I wanted to keep some sort of version control, and this is where git comes in.  I have been aware of git for a while but don’t really know much about it.

I now have created my own git hub for RPizeBox at https://github.com/thomaswwp/RPizeBox. I also forked PyLMS (which appears to be abandoned) and will eventually include it in my build as a module, rather than simply importing the code.

I have reduced the code to two scripts, but this looks like it has increased the CPU overhead to about 6%, so I may revert to what I had before.

I have also made a Fritzing diagram of the setup for future reference.

RPizeBox_bb

I also found that the skip forward button was broken on the remote, so just remapped other buttons.

500D_1902

 

RPizeBox Display code

Here is the code for now. It needs pylms downloaded and wiringpi2 to work.  I made some changes to pylms player.py to allow for accented letters in the titles so I just load the code rather than importing it.

#####################################################################
# SqueezeLite LCD Display                                           #
# Thomas W-P - http://thomas.w-p.me.uk                              #
# Needs to be run as sudo                                           #
#                                                                   #
# Known issues:                                                     #
#      Code is a bit crap, but that's life.  It just about works.   #
#                                                                   #
#####################################################################
import wiringpi2 as wp      # to control display
import time, datetime           # for delays and date
import fcntl, socket, struct # to get mac address
import commands           # to get IP address
#import subprocess              # for printing to console
import sys
sys.path.append('/home/pi/PyLMS/')

from pylms.server import Server # to talk to LMS server
from pylms.player import Player # to talk to LMS player


# variables/constants
loggedin = False      # to wait for the server
scrollpos = 0       # for scrolling the title - needs to be remembered...
waitBeforeOffMinutes = 10   # time to wait before switching off in minutes
waitCount = 0               # counter for the suspend mode
elapsed = float(0)          # to hold elapsed time
total = float(0)            # to hold total time
scPort = 9090               # default LMS port for CLI
scUser = ""                 # CLI user
scPassword = ""             # CLI password
whatToShow = 0              # 0 = Artist, 1 = Album, 2 = Position/Length



# to get the mac address
def getHwAddr(ifname):
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    info = fcntl.ioctl(s.fileno(), 0x8927,  struct.pack('256s', ifname[:15]))
    return ''.join(['%02x:' % ord(char) for char in info[18:24]])[:-1]

# to scroll the title
def scrollTitle():
    tracktitle = ""       # string to hold track title
    global scrollpos
    try:
        tracktitle = sl.get_track_title()
        if (len(tracktitle) > 16):
            tracktitle += " --- " + tracktitle[:16]
            for x in range(0,7):
                # exit if not in "Play" mode
                if (sl.get_mode() != 'play'):
                    return
                # we're at the start - pause 
                if (scrollpos == 0):
                    # scroll 
                    wp.lcdPosition(lcd, 0, 0)
                    wp.lcdPuts(lcd,tracktitle[0:16])
                    time.sleep(3)
                if (len(tracktitle) > 16+scrollpos):
                    scrollpos += 1
                    wp.lcdPosition(lcd, 0, 0)
                    wp.lcdPuts(lcd,tracktitle[scrollpos:16+scrollpos])
                    time.sleep(0.4)
                elif (len(tracktitle) == 16+scrollpos): #we've got back to the start
                    scrollpos = 0
        else:   #standard title
            for x in range(0,4):
                if (sl.get_mode() != 'play'):
                    return
                wp.lcdPosition(lcd, 0, 0)
                wp.lcdPuts(lcd,(tracktitle + " "*16)[:16])
                time.sleep(1)

    except:
        wp.lcdPosition(lcd, 0, 0)
        #cmd = [ 'echo', tracktitle ]
        #output = subprocess.Popen( cmd, stdout=subprocess.PIPE ).communicate()[0]
        #print output
        wp.lcdPuts(lcd,"(Title unknown)")
        time.sleep(5)  


# get the IP address
import commands
intf = 'eth0'
intf_ip = commands.getoutput("ip address show dev " + intf).split()
intf_ip = intf_ip[intf_ip.index('inet') + 1].split('/')[0]

# set up the display - 4 bit to save pins - apparently slower but marginal
# https://projects.drogon.net/raspberry-pi/wiringpi/lcd-library/
wp.wiringPiSetup();
lcd = wp.lcdInit (2, 16, 4,  11,10 , 0,1,2,3,0,0,0,0)

# connect to the squeezebox
sc = Server(hostname=intf_ip, port=scPort, username=scUser, password=scPassword)

# initialising
wp.lcdClear(lcd)      # clear the lcd
wp.lcdPosition(lcd, 0, 0) # cursor to start of row


# keep trying to connect until there is a response
while loggedin != True:
    try:
        sc.connect()
        loggedin = sc.logged_in
        #wp.lcdPuts(lcd,str(loggedin))
    except:
        wp.lcdClear(lcd)
        wp.lcdPosition(lcd, 0, 0)
        wp.lcdPuts(lcd,"Music server"[:16])
        wp.lcdPosition(lcd, 0, 1)
        wp.lcdPuts(lcd,"   not ready :("[:16])
        time.sleep(3)

# set up the player
sl = sc.get_player(getHwAddr("eth0")) # http://stackoverflow.com/questions/159137/getting-mac-address

# change the display
while True:

    # show something
    if (sl.get_mode() == 'play'):
        waitCount = 0 
        try:
            wp.lcdPosition(lcd, 0, 1)
            # no switch in python!
            if(whatToShow == 0):
                wp.lcdPuts(lcd,(sl.get_track_artist() + " "*16)[:16])
            elif(whatToShow == 1):
                wp.lcdPuts(lcd,(sl.get_track_album() + " "*16)[:16])
            elif(whatToShow == 2):
                wp.lcdPosition(lcd, 0, 1)  
                elapsed = sl.get_time_elapsed()
                total = sl.get_track_duration()
                progress = int(9 * elapsed / total)#
                wp.lcdPuts(lcd,">" + ">"*(progress+1)+"-"*(8-progress) + " " + str(datetime.timedelta(seconds=int(total)))[-5:])            
            whatToShow += 1
            if (whatToShow == 3):
                whatToShow = 0
        except:
            wp.lcdPuts(lcd,"      ~~~~      "[:16])          
        # title scrolling
        scrollTitle()  


    # deal with pause/stop
    if (sl.get_mode() == 'pause'):
        wp.lcdPosition(lcd, 0, 0)
        wp.lcdPuts(lcd,(sl.get_track_artist() + " "*16)[:16])
        wp.lcdPosition(lcd, 0, 1)  
        wp.lcdPuts(lcd,("     PAUSED" + " "*16)[:16])
        time.sleep(1)
        waitCount += 1
        if (waitCount >= (waitBeforeOffMinutes * 60)): 
            # send "OFF" message to player
            sl.set_power_state(False)

    if (sl.get_mode() == 'stop'):
        waitCount = 0
        wp.lcdPosition(lcd, 0, 1)  
        wp.lcdPuts(lcd,"           " + time.strftime("%H:%M", time.gmtime())[:16])
        wp.lcdPosition(lcd, 0, 0)
        wp.lcdPuts(lcd,(datetime.datetime.now().strftime("%A") + " " + datetime.datetime.now().strftime("%d")+ " " + datetime.datetime.now().strftime("%B")[:3] + " "*16)[:16])
        time.sleep(1)