#!/usr/bin/python
# -*- coding: utf-8 -*-

import time
from bisect import bisect_left
from mpd import MPDClient
import smbus
import RPi.GPIO as GPIO


def readDial():
	""" Ask the AS5601 where the dial is currently set. """
	""" Returns a value 0 - 4096. Some cannot be reached due to mechanical limitations. """
	# 0x36 is address of AD5601.
	# 0x0c and 0x0d are register addresses in AD5601 (See Datasheet).
	#                           High 4 Bits                               Low 8 Bits
	dial = i2cBus.read_byte_data(0x36, 0x0c) * 256 + i2cBus.read_byte_data(0x36, 0x0d)
	return dial


def readBand():
	""" Read GPIO to see where bandswitch is. """
	""" Does whatever monkeying is required to make bands make sense. """
	band = 0
	if (GPIO.input(23) == False):
		band = 1
	elif (GPIO.input(18) == False):
		band = 4
	elif (GPIO.input(24) == False):
		band = 2
	elif (GPIO.input(25) == False):
		band = 3
	return band 


def lightBand(band):
	""" Light the appropiate GPIO to illuminate chosen band """
	if (band == 4):
		GPIO.output(4, GPIO.LOW)
		GPIO.output(17, GPIO.LOW)
		GPIO.output(27, GPIO.LOW)
		GPIO.output(22, GPIO.HIGH)
	elif (band == 3):
		GPIO.output(4, GPIO.LOW)
		GPIO.output(17, GPIO.LOW)
		GPIO.output(27, GPIO.HIGH)
		GPIO.output(22, GPIO.LOW)
	elif (band == 2):
		GPIO.output(4, GPIO.LOW)
		GPIO.output(17, GPIO.HIGH)
		GPIO.output(27, GPIO.LOW)
		GPIO.output(22, GPIO.LOW)
	elif (band == 1):
		GPIO.output(4, GPIO.HIGH)
		GPIO.output(17, GPIO.LOW)
		GPIO.output(27, GPIO.LOW)
		GPIO.output(22, GPIO.LOW)
	return


def getStation(tune):
	""" Returns the nearest station index to a given tune position. """
	""" Also returns distance to that station. """
	pos = bisect_left(stationIndex, tune)
	if pos == 0:
		station = pos
	elif pos == len(stationIndex):
		station = pos - 1
	else:
		before = stationIndex[pos - 1]
		after = stationIndex[pos]
		if after - tune < tune - before:
			station = pos
		else:
			station = pos - 1
	distance = abs(tune - stationIndex[station])
	return (station, distance)


# The list of stations and their tuning locations,
# As well as the name and genre of each station (For what? Dunno yet...)
stationList = [
	(103297, "BBC World Service", "News", "http://bbcwssc.ic.llnwd.net/stream/bbcwssc_mp1_ws-einws"),	
	(300495, "Iowa Public Radio", "News", "http://news-stream.iowapublicradio.org/News.mp3"),
	(201692, "Thistle and Shamrock", "Folk", "http://ice2.somafm.com/thistle-128-mp3"),
	(301985, "Trancemission.FM Radio", "New Age", "http://87.230.84.182:9000"),
	(300974, "Akihabara Radio", "J-pop", "http://176.31.241.17:8814/aac"),
	(202700, "181.FM Classical Guitar", "Classical Guitar", "http://75.126.5.188:8020"),
	(402968, "Radio-Dunklemacht", "German Death Metal", "http://84.39.97.114:8000"),
	(401419, "Hmong Radio WIXK 1590 AM", "World Music", "http://162.252.85.85:9000"),
	(101114, "IBIZA LIVE RADIO", "House", "http://198.105.220.12:9623/Live"),
	(200656, "Age of Aquarius", "Hippy-Dippy", "http://174.36.232.227:8106/stream"),
	(102112, "Wicca Radio International", "Wicca", "http://51.255.235.165:5000/stream"),
	(402500, "Christmas Melody", "Christmas", "http://107.182.238.95:9185"),

	(102239, "Noise FM", "Dubstep", "http://noisefm.ru:8000/play"),
	(203296, "Full FM", "2000's", "http://198.255.100.170:8142"),
	(302733, "QMR Hit 00's", "2000's", "http://78.129.146.97:7074/stream"),
	(400477, "1940s Radio", "1940's", "http://149.255.59.164:8080"),
	(100905, "24/7 Dreamboat and Petticoats", "1950's", "http://80.86.84.31:8000"),
	(202913, "ORSRADIO", "1950's, 1960's", "http://158.69.109.57:8132/stream"),
	(303036, "Ultimate Seventies", "1970's", "http://94.23.62.189:5342"),
	(403286, "idobi Radio", "Alternative", "http://209.73.138.21:80"),
	(103238, "Radio Star Hot AC", "1990's", "http://46.105.108.89:8000"),
	(201029, "American Classic Radio", "Old Time Radio", "http://149.255.59.164:8043"),
	(300700, "Art7 Radio", "World Music", "http://198.105.220.12:5715/Live"),
	(401791, "BBC Radio 4", "News Programs", "http://bbcmedia.ic.llnwd.net/stream/bbcmedia_radio4fm_mf_p"),
	(101776, "BBC Scotland", "Gaelic", "http://bbcmedia.ic.llnwd.net/stream/bbcmedia_scotlandfm_mf_p"),
	(203252, "Best of Disney", "Disney", "http://107.182.234.82:8286"),
	(300902, "The 1920s Radio Network", "Old Time Radio", "http://209.9.238.5:8570"),
	(403242, "Jazz 20's & Swinging 30's", "1920's, 1930's", "http://142.4.217.133:9069/stream"),
	(100628, "KCEA 89.1", "Big Band", "http://streaming.rubinbroadcasting.com:80/kcea"),
	(203419, "HPR2", "Classic Country", "http://50.7.77.179:8022"),
	(303113, "HPR1", "Classic Country", "http://188.165.192.5:8374"),
	(401002, "polushon.com", "Modern Jazz", "http://38.107.243.188:8591"),
	(103152, "Radiofil", "Jazz", "http://50.22.223.16:8596"),
	(202114, "Japan-A-Radio", "J-pop", "http://64.62.194.40:9030"),
	(301025, "K-LOVE", "Christian", "http://emf.mp3.miisolutions.net/klDAV/sk038_mweb_low"),
	(402192, "Mais Kizomba", "World", "http://109.71.41.250:8123"),
	(102645, "Healing Music by Dr. J. James", "New Age", "http://94.23.252.14:8047/stream"),
	(200588, "Positively Successful", "New Age", "http://198.178.121.76:8432/stream"),
	(302420, "24-7 Polka Heaven", "Polka", "http://206.190.144.155:8046"),
	(401215, "WRJQ Goodtime Radio", "Polka", "http://70.38.12.44:8144"),
	(102185, "psyradio * fm", "World", "http://81.88.36.42:8040"),
	(202773, "Radio-im-Internet.de", "German", "http://stream.radio-im-internet.de:8080/mp3"),
	(300588, "Radio Mahoor", "World", "http://38.99.146.102:8000/mahoor.mp3"),
	(402442, "ROCK ANTENNE", "Rock", "http://mp3channels.webradio.antenne.de:80/rockantenne"),
	(100944, "Space Travel Radio", "New-Age", "http://136.243.156.30:1701/stream/3/"),
	(202022, "SOLORADIO 90.6FM", "Spanish", "http://204.12.193.98:8293"),
	(302080, "Thayagam tamil oli", "World", "http://46.28.53.118:7045/stream"),
	(401707, "Wiccan Moon Radio", "Wicca", "http://38.107.242.202:8356"),
	(100578, "Zwischen-Welten Radio", "Folk", "http://136.243.21.79:8000/listen/"),
	(201386, "Phoenix Radio", "Pop", "http://80.195.148.109:80"),
	(300812, "Irish Pub Radio", "Folk", "http://178.32.219.72:8326"),
	(401500, "Radio Beograd 1", "World", "http://195.252.107.194:8002"),
	(100823, "FM4", "Alternative", "http://198.50.155.189:8009"),
	(202972, "British Comedy Channel - ROK Classic Radio", "Old Time Radio", "http://77.92.76.190:9155"),
	(301788, "KISS 00's", "2000's", "http://149.56.23.7:20226/stream"),
	(401951, "Italian Graffiati", "Italian, 1960's, 1970's", "http://107.182.238.95:7110"),
	(101687, "192 Radio Nederland", "Netherlands, 1960's", "http://188.213.230.36:8030/stream"),
	(201960, "Harmony Radio www.harmonyradio.be", "Belgium, 1960's", "http://195.154.78.67:8052"),
	(301495, "ABC 60's", "1960's", "http://149.56.23.7:20314/stream"),
	(401295, "Radio1 GOLDEN 60s", "1960's", "http://37.187.57.33:8022/stream"),
	(101505, "90sFM", "World", "http://64.150.176.192:8276"),
	(301561, "Gr8 90's", "World", "http://184.107.202.178:8132"),
	(401119, "America Dance 90s", "1990's", "http://104.166.74.74:8212/MP3"),
	(102881, "WALLYradio", "2000's", "http://37.59.42.207:8469/stream"),
	(201096, "San Francisco's 70's HITS!", "1970's", "http://s6.voscast.com:10922"),
	(301297, "DISCO STUDIO 54 HD RADIO", "1970's, Disco", "http://disco54.radioca.st:80/streams/192kbps?yp=7"),
	(402789, "MagicRadio by PulsRadio", "1980's", "http://193.200.42.211:80/magicradioHD.mp3"),
	(101181, "80s Channel | The Power Of 80s", "1980's", "http://46.105.118.14:15500"),
	(200415, "AAZO Radio Rap", "Rap", "http://77.67.46.74:8000/aazoradio-raphiphop.mp3"),
	(300376, "Reggae141.com", "Reggae", "http://66.85.88.2:7147"),
	(402923, "Radio Rivendell", "Soundtrack", "http://rivendell.byte-storm.com:8000/128kbit.mp3"),
	(102820, "AH.FM - Leading Trance Radio", "Electronic", "http://206.223.161.106:9000"),
	(200961, "A Hop A Skip and A Dubstep Away", "Dubstep", "http://192.240.102.131:7637/stream"),
	(302826, "Plain Talk Radio", "Talk", "http://184.154.202.243:8349/stream"),
	(401644, "RayJess.com", "Latin Jazz", "http://192.95.39.65:5189/stream"),
	(102377, "LaTin Jazz Radio", "Latin Jazz", "http://96.56.32.46:8002"),
	(202326, "idobi Howl", "Metal", "http://69.46.88.27:80"),
	(302536, "Bear Metal Radio", "Metal", "http://62.75.215.7:8048"),
	(401846, "liveireland Live From Dublin, Ireland.", "Folk", "http://66.90.73.250:8080"),
	(100511, "Cyber-FM Country", "Country", "http://98.158.184.87:9416/stream"),
	(200903, "KWHW-FM", "Country", "http://45.40.163.108:80/kwhwfm"),
	(300758, "Venice Classic Radio Italia", "Classical", "http://5.196.98.235:80/stream1"),
	(400405, "Public Domain Classical - Swiss Internet Radio", "Classical", "http://82.197.167.137:80"),
	(100351, "Velvet 96.8", "Blues", "http://s10.voscast.com:9942"),
]
# Index used to look up what station we are tuned to. 
stationIndex = []


try:
	# Sort Radio Stations
	stationList.sort(key=lambda station: station[0])

	# Connect to MPD
	mpc = MPDClient()
	mpc.connect("localhost", 6600)

	# Load playlist into MPD
	# and populate station index.
	mpc.clear()
	for station in stationList:
		(index, name, genre, url) = station
		stationIndex.append(index)
		mpc.add(url)

	# Setup i2c Bus
	# Pi has 2 i2c busses, which is the AS5601 (Dial Reader) on?
	i2cBus = smbus.SMBus(1) 

	# Setup GPIO
	# GPIO is used to read band switch and light band lights.
	GPIO.setmode(GPIO.BCM)
	# Band Lights.
	GPIO.setup( 4, GPIO.OUT)
	GPIO.setup(17, GPIO.OUT)
	GPIO.setup(27, GPIO.OUT)
	GPIO.setup(22, GPIO.OUT)
	# Band Switch.
	GPIO.setup(23, GPIO.IN)
	GPIO.setup(24, GPIO.IN)
	GPIO.setup(25, GPIO.IN)	
	GPIO.setup(18, GPIO.IN)	

	# Set lastBand and lastStation to impossible numbers
	# so the first loop pass is forced to tune the correct station
	lastBand = -1
	lastStation = -1

	while True:
		status = mpc.status()
		if 'error' in status:
			print "Error Tuning: ", status
			lastStation = -1
			time.sleep(.2)

		
		# Read where the bandswitch is currently set.
		band = readBand()
		# If the band changed, make sure to light the appropiate band light.
		if (band != lastBand):
			lightBand(band)
			lastBand = band
	
		# Read where the dial is currently set.
		dial = readDial()
		# Work out where the radio is tuned based on the band and dial settings.
		tune = (band * 100000) + dial
	
		# figure out what station is closest to our tune position.
		(station, distance) = getStation(tune)
		
		# If the station changed, change what MPD is playing.
		if (station != lastStation):
			mpc.setvol(0)
			mpc.play(station)
			lastStation = station
			print (tune, stationList[station][1])
		
		# Set the volume higher the closer we are to exactly tuned in
		if (distance > 100):
			volume = 0
		else:
			volume = 100 - distance
		mpc.setvol(volume)
		
		time.sleep(.05)

finally: 
	GPIO.cleanup()
