Here is my awful but roughly functional code that pulls from MPD and writes to the screen, and also handles power functions on my system. Comment these out or your pi will shutdown as soon as you run the program. You will need to put any old TTF font in /home/pi/display (which is where I run this script from on boot, via rc.local
I have wired my screen as per learn.adafruit.com/user-space-s … 2-8/wiring But I am using GPIO 12 for the backlight switch instead.
import Image
import ImageDraw
import ImageFont
import time
import subprocess
import os
import glob
import socket
import Adafruit_ILI9341 as TFT
import Adafruit_GPIO as GPIO
import Adafruit_GPIO.SPI as SPI
import gc
import mpd
client = mpd.MPDClient(use_unicode=True)
client.timeout = 10
client.connect("localhost", 6600)
#setup to monitor pin for shutdown on power stich off
gpio = GPIO.get_platform_gpio()
gpio.setup(20, GPIO.IN, pull_up_down=GPIO.PUD_DOWN) # monitor power switch
gpio.setup(21, GPIO.OUT) # Take control of Keep Alive signal to relay board
gpio.setup(16, GPIO.OUT) # Takecontrol of Power LED
gpio.setup(12, GPIO.OUT) # Take control of LCD Backlight
gpio.output(21, True) # Turn on Keep Alive
gpio.output(16, True) # Turn on Power LED
gpio.output(12, True) # Turn on LCD backlight
# Raspberry Pi pin configuration for screen
DC = 18
RST = 23
SPI_PORT = 0
SPI_DEVICE = 0
# Create TFT LCD display class.
disp = TFT.ILI9341(DC, rst=RST, spi=SPI.SpiDev(SPI_PORT, SPI_DEVICE, max_speed_hz=64000000))
# Initialize display.
disp.begin()
# Clear the Display
disp.clear((0, 0, 0)) #DON'T DO THIS OFTEN, IT LEAKS MEMORY IF REPEATED FREQUENTLY
# Get a PIL Draw object to start drawing on the display buffer.
draw = disp.draw()
# load a TTF font
# I chose fixed width for now, to make it easier to center things
font = ImageFont.truetype('/home/pi/display/unispace.ttf', 20)
smallfont = ImageFont.truetype('/home/pi/display/unispace.ttf', 14)
bigfont = ImageFont.truetype('/home/pi/display/unispace.ttf', 60)
orig_time = time.time() # Initialise timer for track timer
# Try to connect to gmail, then note which IP address resolves to the internet to identify the correct
# network interface to print on the screen in idle mode
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(("gmail.com",80))
ipaddress=(s.getsockname()[0])
s.close()
# Return CPU temperature as a character string
def getCPUtemperature():
res = os.popen('vcgencmd measure_temp').readline()
return(res.replace("temp=","").replace("'C\n",""))
#The screen is usually setup portrait, so ghere i used some adafruit code to draw text at 90 degrees:
def draw_rotated_text(image, text, position, angle, font, fill=(255,255,255)):
# Get rendered font width and height.
draw = ImageDraw.Draw(image)
width, height = draw.textsize(text, font=font)
# Create a new image with transparent background to store the text.
textimage = Image.new('RGBA', (width, height), (0,0,0,0))
# Render the text.
textdraw = ImageDraw.Draw(textimage)
textdraw.text((0,0), text, font=font, fill=fill)
# Rotate the text image.
rotated = textimage.rotate(angle, expand=1)
# Paste the text into the image, using it as a mask for transparency.
image.paste(rotated, position)
#Initial MPC queries. !!!"Always use try/except !!!!! otherwise the program crashes out when one is blank!
try:
artist = client.currentsong()['artist']
except:
artist = "No Artist"
try:
title = client.currentsong()['title']
except:
title = "No Title"
try:
album = client.currentsong()['album']
except:
album = "No Album"
start_time = time.time()
# initial setup of variables and lines
oldtitle = title
artist2 = artist[28:56].center(27)
artist = artist[0:28].center(27)
title2 = title[28:56].center(27)
title = title[0:28].center(27)
album2 = album[28:56].center(34)
album = album[0:28].center(34)
#inital draw of screen
disp.clear((0, 0, 0))
draw_rotated_text(disp.buffer, artist, (20, 0), 90, font, fill=(255,255,255))
draw_rotated_text(disp.buffer, artist2, (40, 0), 90, font, fill=(255,255,255))
draw_rotated_text(disp.buffer, title, (70, 0), 90, font, fill=(255,255,255))
draw_rotated_text(disp.buffer, title2, (90, 0), 90, font, fill=(255,255,255))
draw_rotated_text(disp.buffer, album, (150, 0), 90, smallfont, fill=(255,255,255))
draw_rotated_text(disp.buffer, album2, (180, 0), 90,smallfont, fill=(255,255,255))
oldstate="Random nonzero"
while(True):
if ( gpio.input(20) == False ): ##I have this pin wired to the power switch on the front of the case. If the input goes low, the pi shuts down! Remove this if you don't want it to happen
print "shit down"
disp.clear((0, 0, 0))
draw_rotated_text(disp.buffer, "Shutdown", (70, 10), 90, bigfont, fill=(255,255,255))
disp.display()
time.sleep(5)
os.system('sudo shutdown -h now')
try:
oldstate=state
state = client.status()['state']
except:
state = "fail"
if (state != oldstate): disp.clear((0, 0, 0))
## only clear when we have to, disp.clear has a memory leak!!!
if (state != "play") and (state != "pause"): # If device idle, show current time/date, IP and CPU temp
draw_rotated_text(disp.buffer, ipaddress, (20, 10), 90, smallfont, fill=(255,255,255))
draw_rotated_text(disp.buffer, getCPUtemperature(), (20, 280), 90, smallfont, fill=(255,255,255))
localtime = time.asctime( time.localtime(time.time()) )
draw_rotated_text(disp.buffer, localtime[0:10], (70, 10), 90, font, fill=(255,255,255))
draw_rotated_text(disp.buffer, localtime[11:19], (90, 10), 90, bigfont, fill=(255,255,255))
disp.display()
time.sleep(0.1) # YOu can remove this to make display update quicker, but it becomes even more of a CPU hog
oldtitle = "Random Nonsense placeholder"
print state # just for debugging
else: # If Playing or Paused
print state ## just for debugging
draw_time = time.time() ## also debug
try:
newtitle = client.currentsong()['title']
except:
newtitle = "failed to get title"
if (newtitle == oldtitle): # Mark time on track change
seconds = time.time() - start_time
m, s = divmod(seconds, 60)
h, m = divmod(m, 60)
draw_rotated_text(disp.buffer,"%d:%02d:%02d" % (h, m, s) , (195, 5), 90, font, fill=(255,255,255))
else:
start_time = time.time()
try: # ALWAYS TRY /EXCEPT ON MPC CALLS
artist = client.currentsong()['artist']
except:
artist = "No Artist"
try:
title = client.currentsong()['title']
except:
title = "No Title"
try:
album = client.currentsong()['album']
except:
album = "No Album"
#Format display strings
oldtitle = title
artist2 = artist[28:56].center(27)
artist = artist[0:28].center(27)
title2 = title[28:56].center(27)
title = title[0:28].center(27)
album2 = album[28:56].center(34)
album = album[0:28].center(34)
disp.clear((0, 0, 0))
draw_rotated_text(disp.buffer, artist, (20, 0), 90, font, fill=(255,255,255))
draw_rotated_text(disp.buffer, artist2, (40, 0), 90, font, fill=(255,255,255))
draw_rotated_text(disp.buffer, title, (70, 0), 90, font, fill=(255,255,255))
draw_rotated_text(disp.buffer, title2, (90, 0), 90, font, fill=(255,255,255))
draw_rotated_text(disp.buffer, album, (150, 0), 90, smallfont, fill=(255,255,255))
draw_rotated_text(disp.buffer, album2, (180, 0), 90,smallfont, fill=(255,255,255))
disp.display()
time.sleep(0.1) # Can reduce this delay for snappyer display, but it will hog much more CPU for little benefit.