#! /usr/bin/python
# Copyright 2013 - Emmanuel Cordente
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# See to get a copy of the GNU General
# Public License.
import urllib2
import simplejson
import RPi.GPIO as GPIO
from time import sleep
import threading
import subprocess
import gaugette.rotary_encoder
# Class qui gere toutes les communications avec le serveur squeezebox
class SqueezeBoxServer():
def __init__(self, host="127.0.0.1", port=9000, player_id=""):
self.host = host
self.port = port
self.server_url = "http://%s:%s/jsonrpc.js" % (self.host, self.port)
self.player_id = player_id
self.artists = self.query( "artists", 0, 9999)['artists_loop']
self.radio_count = self.query( "favorites", "items")['count']
self.artist_count = len(self.artists)
def query(self, *args):
params = simplejson.dumps({'id':1, 'method':'slim.request', 'params':[self.player_id, list(args)]})
req = urllib2.Request(self.server_url, params)
response = urllib2.urlopen(req)
response_txt = response.read()
return simplejson.loads(response_txt)['result']
def setVolume(self, volume):
self.query("mixer", "volume", volume)
def getArtists(self):
return self.artists
def getArtistsCount(self):
return self.artist_count
def getRadiosCount(self):
return self.radio_count
def playRadio(self, radio):
return self.query("favorites", "playlist", "play", "item_id:"+str(radio))
def getArtistAlbum(self, artist_id):
return self.query("albums", 0, 99, "tags:al", "artist_id:"+str(artist_id))['albums_loop']
def playAlbum(self, id):
return self.query("playlistcontrol", "cmd:load", "album_id:"+str(id))
def pause(self):
return self.query("pause")
def previousSong(self):
return self.query("playlist", "index", "-1")
def nextSong(self):
return self.query("playlist", "index", "+1")
def getCurrentSongTitle(self):
return self.query("current_title", "?")['_current_title']
def getCurrentRadioTitle(self, radio):
return self.query("favorites", "items", 0, 99)['loop_loop'][radio]['name']
############################
# Class de controle du LCD #
############################
class HD44780(threading.Thread):
######################
# Variable Shared #
######################
_PULSE = 0.00005
_DELAY = 0.00005
######################
# Constructeur #
######################
def __init__(self, pin_rs=26, pin_e=24, pins_db=[22, 18, 16, 12], lcd_width=32):
self.message = ""
self.currentmessage = "azertyuiop"
self.stop = False
self.lcd_width = lcd_width
self.pin_rs = pin_rs
self.pin_e = pin_e
self.pins_db = pins_db
self.updating=False
GPIO.setmode(GPIO.BOARD) # Use RaspPI GPIO numbers
GPIO.setup(self.pin_e, GPIO.OUT)
GPIO.setup(self.pin_rs, GPIO.OUT)
for pin in self.pins_db:
GPIO.setup(pin, GPIO.OUT)
self.Clear()
threading.Thread.__init__(self)
######################
# Demarrage du Thread#
######################
def run(self):
while self.stop == False:
if self.message != self.currentmessage:
self.currentmessage = self.message
self.LcdMessage()
sleep(0.005)
######################
# Arret du Thread #
######################
def Stop(self):
self.stop = True
######################
# Initialisation LCD #
######################
def Clear(self):
""" Blank / Reset LCD """
self.LcdByte(0x33, False) # $33 8-bit mode
self.LcdByte(0x32, False) # $32 8-bit mode
self.LcdByte(0x28, False) # $28 8-bit mode
self.LcdByte(0x0C, False) # $0C 8-bit mode
self.LcdByte(0x06, False) # $06 8-bit mode
self.LcdByte(0x01, False) # $01 8-bit mode
######################
#Execution sur le LCD#
######################
def LcdByte(self, bits, mode):
""" Send byte to data pins """
# bits = data
# mode = True for character
# False for command
GPIO.output(self.pin_rs, mode) # RS
# High bits
for pin in self.pins_db:
GPIO.output(pin, False)
if bits&0x10==0x10:
GPIO.output(self.pins_db[0], True)
if bits&0x20==0x20:
GPIO.output(self.pins_db[1], True)
if bits&0x40==0x40:
GPIO.output(self.pins_db[2], True)
if bits&0x80==0x80:
GPIO.output(self.pins_db[3], True)
# Toggle 'Enable' pin
sleep(HD44780._DELAY)
GPIO.output(self.pin_e, True)
sleep(HD44780._PULSE)
GPIO.output(self.pin_e, False)
sleep(HD44780._DELAY)
# Low bits
for pin in self.pins_db:
GPIO.output(pin, False)
if bits&0x01==0x01:
GPIO.output(self.pins_db[0], True)
if bits&0x02==0x02:
GPIO.output(self.pins_db[1], True)
if bits&0x04==0x04:
GPIO.output(self.pins_db[2], True)
if bits&0x08==0x08:
GPIO.output(self.pins_db[3], True)
# Toggle 'Enable' pin
sleep(HD44780._DELAY)
GPIO.output(self.pin_e, True)
sleep(HD44780._PULSE)
GPIO.output(self.pin_e, False)
sleep(HD44780._DELAY)
######################
#Affichage sur le LCD#
######################
def LcdMessage(self):
""" Send string to LCD. Newline wraps to second line"""
text = self.currentmessage
self.LcdByte(0x80, False)
lines = text.split("\n")
line1=lines[0].ljust(self.lcd_width, " ")
if (len(lines)>1):
line2 = lines[1].ljust(self.lcd_width, " ")
else:
line2= " ".ljust(self.lcd_width, " ")
for c in line1:
self.LcdByte(ord(c),True)
self.LcdByte(0xC0, False) # next line
for c in line2:
self.LcdByte(ord(c),True)
######################
#Definir le message #
######################
def LcdSetMessage(self, text):
self.message = text
class UINavigation(threading.Thread):
def __init__(self):
GPIO.setmode(GPIO.BOARD)
GPIO.setup(11, GPIO.IN)
GPIO.setup(15, GPIO.IN)
A_PIN = 7
B_PIN = 9
self.encoder = gaugette.rotary_encoder.RotaryEncoder.Worker(A_PIN, B_PIN)
self.encoder.start()
self.current_artist=0
self.current_artist_album_count=0
self.current_radio=0
self.current_album=0
self.left=False
self.right=False
self.push=False
self.back=False
self.level="root"
self.cursor=0
self.sbs = SqueezeBoxServer(host="192.168.0.100",port=9000, player_id="80:1f:02:82:3a:50")
self.lcd= HD44780()
self.sbs.setVolume(100)
self.paused = False
threading.Thread.__init__(self)
def affiche(self,texte):
self.lcd.LcdSetMessage(texte)
#print(texte)
def update_screen(self):
if (self.level == "root"):
if (self.cursor==0):
self.affiche('Radio')
if (self.cursor==1):
self.affiche('Artistes')
elif (self.level == "artist"):
self.affiche(self.sbs.getArtists()[self.current_artist]['artist'])
elif (self.level == "radio"):
if (self.paused==False):
self.affiche(self.sbs.getCurrentRadioTitle(self.current_radio))
else:
self.affiche("Pause - " + self.sbs.getCurrentRadioTitle(self.current_radio))
elif (self.level == "album"):
self.affiche(self.sbs.getArtistAlbum(self.sbs.getArtists()[self.current_artist]['id'])[self.current_album]['album'])
elif (self.level == "song"):
if (self.paused==False):
self.affiche(self.sbs.getArtists()[self.current_artist]['artist']+"\n"+self.sbs.getCurrentSongTitle())
else:
self.affiche("Pause - " + self.sbs.getCurrentSongTitle())
def lbutton(self, fast=False): #Left BUTTON
if (fast):
fast_increment = 20
else:
fast_increment = 0
if(self.level == "root"):
if (self.cursor==1):
self.cursor=0
self.update_screen()
elif (self.cursor==0):
self.cursor=1
self.update_screen()
elif (self.level == "artist"):
self.current_artist-=1+fast_increment
if (self.current_artist<0):
self.current_artist = self.sbs.getArtistsCount()-1
self.update_screen()
elif (self.level == "radio"):
if (self.current_radio>0):
self.current_radio-=1
self.sbs.playRadio(self.current_radio)
self.update_screen()
elif (self.level == "album"):
if (self.current_album>0):
self.current_album-=1
self.update_screen()
elif (self.level == "song"):
self.sbs.previousSong()
self.paused = False
self.update_screen();
def rbutton(self, fast=False): #Right BUTTON
if (fast):
fast_increment = 20
else:
fast_increment = 0
if (self.level == "root"):
if (self.cursor==1):
self.cursor=0
self.update_screen()
elif (self.cursor==0):
self.cursor=1
self.update_screen()
elif (self.level == "artist"):
self.current_artist+=1 + fast_increment
if (self.current_artist>=self.sbs.getArtistsCount()-1):
self.current_artist=0
self.update_screen()
elif (self.level == "radio"):
if (self.current_radio(5/tempo)): #refresh screen every 5 seconds if playing song
self.update_screen()
horloge=0
delta = self.encoder.get_delta()
cumul += delta
if (cumul>=4):
cumul=0
self.rbutton(delta>=6)
if (cumul<=-4):
cumul=0
self.lbutton(delta<=-6)
if(self.push==True):
if(GPIO.input(11)==False):
#print "BUTTON PUSH PRESSED"
self.pbutton()
self.push = GPIO.input(11)
if(self.back==False):
if(GPIO.input(15)==True):
#print "BUTTON BACK PRESSED"
self.bbutton()
self.back = GPIO.input(15)
sleep(tempo)
def Stop(self):
self.lcd.Clear()
self.stop=True
self.lcd.Stop()
if __name__ == '__main__':
# lcd = HD44780()
# lcd.start()
ui = UINavigation()
ui.start()
q = str(raw_input('Press ENTER to quit program\n'))
ui.Stop()