Here is some modifications to code. I have implemented settings-option and modified player to use Nokia Shoutcast Internet radio -client. That player needs to be installed to the memorycard according to this code. If it's not, there should be some modifications on code.
Code is optimized to Nokia N70.
<code>
# lastfm.py: last.fm client for s60
# (c) Richard Cooke - M3 Solutions 2007
# Thanks to Vidar Madsen at Last.fm proxy for some portions of code
import urllib, md5
import e32, appuifw
from appuifw import *
import e32
import time
import thread
import graphics
from graphics import *
import socket
baseurl = "http://ws.audioscrobbler.com/radio/"
username = ""
password = ""
sessionString =""
streamPlaying = 0
metaPeriod = 5 # Period between reading metadata (attempts to read it at end of track)
running=1
# define your redraw function (that redraws the picture on and on)
# in this case we redraw the image named img using the blit function
def handle_redraw(rect):
canvas.blit(screen)
# function to format md5 hashed password string
def hexify(s):
result = ""
for c in s:
result = result + ("%02x" % ord(c))
return result
def exit_key_handler():
app_lock.signal()
def formatStr(inputStr): # Replace spaces with its controlcode
return inputStr.replace(" ","%20")
if (i == track):
# Check whether track changed
if (valueString == lastFMMetaData[i]):
metaPeriod = 5 # Check for trackchange in another 5 seconds
return # If not then return
if (i == trackduration):
metaPeriod = int(valueString)
# form handshake url and connect to it
url = baseurl+"handshake.php?version=1.0.1&platform=linux&username="+username+"&passwordmd5="+passwordmd5
urldata = urllib.urlopen(url)
# get string containing session identifier
sessionString = urldata.readline()[0:40]
# get stream url
streamUrl = urldata.readline()[11:]
Thanks for your input. Shoutcast has already been implemented in the version that is currently on CVS but I think the addtion of a settings file is useful and I will add it to the next build.
On the subject of shoutcast, has anyone ahd any success in getting this working with Nokia's new shiny Internet radio player rather than the old sourceforge one. I must admit I have not. It is a shame that Nokia has removed this project from the public domain.
I plan to package pys60, the internet radio player and blastfm into a single .sis shortly which should make life easier for everyone of a less technical bent.
If there proves to be sufficient demand I amy even port the application to C++ with the open source player as a basis.
Richard
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hi!
Here is some modifications to code. I have implemented settings-option and modified player to use Nokia Shoutcast Internet radio -client. That player needs to be installed to the memorycard according to this code. If it's not, there should be some modifications on code.
Code is optimized to Nokia N70.
<code>
# lastfm.py: last.fm client for s60
# (c) Richard Cooke - M3 Solutions 2007
# Thanks to Vidar Madsen at Last.fm proxy for some portions of code
import urllib, md5
import e32, appuifw
from appuifw import *
import e32
import time
import thread
import graphics
from graphics import *
import socket
baseurl = "http://ws.audioscrobbler.com/radio/"
username = ""
password = ""
sessionString =""
streamPlaying = 0
metaPeriod = 5 # Period between reading metadata (attempts to read it at end of track)
running=1
streaming=0
discovery=1
station=2
station_url=3
stationfeed=4
stationfeed_url=5
artist=6
artist_url=7
track=8
track_url=9
album=10
album_url=11
albumcover_small=12
albumcover_medium=13
albumcover_large=14
trackduration=15
trackprogress=16
radiomode=17
recordtoprofile=18
# create an exit handler
def quit():
global running
running=0
appuifw.app.set_exit()
#set settings
def settings():
global username, password
data1,data2 = appuifw.multi_query(u"Username:",u"Password")
username = data1
password = data2
file = open("E:\\Data\\lastfm.cfg", "w")
file.write(username + "\n" + password)
file.close()
# define your redraw function (that redraws the picture on and on)
# in this case we redraw the image named img using the blit function
def handle_redraw(rect):
canvas.blit(screen)
# function to format md5 hashed password string
def hexify(s):
result = ""
for c in s:
result = result + ("%02x" % ord(c))
return result
def exit_key_handler():
app_lock.signal()
def formatStr(inputStr): # Replace spaces with its controlcode
return inputStr.replace(" ","%20")
def mnuLove():
urllib.urlopen(baseurl+"control.php?"+sessionString+"&command=love&debug=0")
def mnuBan():
global schedtime
urllib.urlopen(baseurl+"control.php?"+sessionString+"&command=ban&debug=0")
schedtime = time.time() # Schedule trackchange
def mnuSkip():
global schedtime
urllib.urlopen(baseurl+"control.php?"+sessionString+"&command=skip&debug=0")
schedtime = time.time() # Schedule track change
def tuneRec():
global username
tuneRadio("lastfm://user/" + username + "/recommended/100")
def tunePer():
global username
tuneRadio("lastfm://user/" + username + "/personal")
def tuneLov():
tuneRadio("lastfm://user/"+ username + "/loved")
def tuneNei():
tuneRadio("lastfm://user/" + username + "/neighbours")
def tuneSim():
tuneRadio("lastfm://artist/"+formatStr(appuifw.query(u"Play Music Like:", "text"))+"/similarartists")
def tuneTag():
tuneRadio("lastfm://globaltags/"+formatStr(appuifw.query(u"Enter Tag:", u"text")))
def tuneRadio(url):
global schedtime
response=urllib.urlopen(baseurl+"adjust.php?"+sessionString+"&url="+url+"&debug=0")
schedtime = time.time() # Schedule track change
def getMetaData():
global streamPlaying, metaPeriod, albumcover, lastFMMetaData
metadata = urllib.urlopen(metaurl)
output = metadata.readline()
i=0
while (output != ""):
indexofequals = output.find("=")+1
valueString = output[indexofequals:]
if (i == track):
# Check whether track changed
if (valueString == lastFMMetaData[i]):
metaPeriod = 5 # Check for trackchange in another 5 seconds
return # If not then return
if (i == trackduration):
metaPeriod = int(valueString)
if (i == albumcover_large):
try:
urllib.urlretrieve(valueString, "C:\\Data\\temp.gif")
except:
appuifw.note(u"Error fetching image", "info")
lastFMMetaData[i] = valueString
try:
output = metadata.readline()
except:
appuifw.note(u"some metadata error")
i=i+1
if (i == 1):
streamPlaying = 0
metaPeriod = 5
else:
streamPlaying = 1
metadata.close()
#reads settings-file if exist
try:
try:
f = open("E:\\Data\\lastfm.cfg", "r")
except:
print u"error opening file"
try:
username = f.readline().rstrip()
password = f.readline()
except:
print u"error reading file"
try:
f.close()
except:
print u"error while closing file"
except:
appuifw.note(u"Set username and password from settings first", "info")
settings()
# set the screen size to large
appuifw.app.screen='large'
# define an initial image (white)
img=Image.new((160,160))
screen = Image.new((240,320))
# calculate md5 hashed password string
passwordmd5=hexify(md5.md5(password).digest())
print passwordmd5
# form handshake url and connect to it
url = baseurl+"handshake.php?version=1.0.1&platform=linux&username="+username+"&passwordmd5="+passwordmd5
urldata = urllib.urlopen(url)
# get string containing session identifier
sessionString = urldata.readline()[0:40]
# get stream url
streamUrl = urldata.readline()[11:]
metaurl = baseurl+"np.php?"+sessionString+"&debug=0"
urldata.close()
# write mp3 playlist to file
try:
m3ufile = open("E:\\Shoutcast\\lastfm.pls", "w")
m3ufile.write(u"[playlist] \nNumberOfEntries=1\nFile1=")
m3ufile.write(streamUrl)
m3ufile.write(u"\nTitle1=Last.fm-radio\n")
m3ufile.close()
except:
appuifw.note(u"Cannot write playlist", "note")
#initialise list for metadata
lastFMMetaData = ["","","","","","","","","","","","","","","","","","",""]
# define the canvas, include the redraw callback function
canvas=appuifw.Canvas(event_callback=None, redraw_callback=handle_redraw)
# set the app.body to canvas
appuifw.app.body=canvas
appuifw.app.menu = [(u"love", mnuLove),
(u"ban", mnuBan),
(u"skip", mnuSkip),
(u"tune", ((u"My Recommendations", tuneRec),
(u"Personal Radio", tunePer),
(u"Loved Tracks Radio", tuneLov),
(u"Neigbourhood Radio", tuneNei),
(u"Similar Artists Radio", tuneSim),
(u"Tag",tuneTag))),
(u"Settings", settings)]
appuifw.app.exit_key_handler=quit
urllib.urlretrieve("http://static.last.fm/depth/advertising/lastfm/mini_red_rev.gif", "C:\\Data\\logo.gif")
logo = Image.open("C:\\Data\\logo.gif")
schedtime = time.time()
while running:
nowtime = time.time() # Get System time
if nowtime >= schedtime: # Attempt to read metaData when track changes
getMetaData()
schedtime = nowtime + metaPeriod
try:
img = Image.open("C:\\Data\\temp.gif")
except:
appuifw.note(u"Error fetching image", "info")
screen.clear((128,128,128))
screen.blit(logo, target=(0,0))
if streamPlaying:
screen.blit(img, target=(0,0,170,160), scale=1)
# convert artist and trackdata to unicode (catch formatting exceptions)
try:
uartist = unicode(lastFMMetaData[artist][:-1])
except:
uartist = u"error"
try:
utrack = unicode(lastFMMetaData[track][:-1])
except:
utrack = u"error"
screen.text((0,168), uartist)
screen.text((0,184), utrack)
screen.text((85,168), unicode(str(metaPeriod/60)+":" + str(metaPeriod%60)))
try:
appuifw.app.title = unicode(lastFMMetaData[station][:-1])
except:
appuifw.app.title = u"error"
else:
screen.text((0,100), u"Not streaming")
# redraw the screen
handle_redraw(())
time.sleep(1)
# yield needs to be here in order that key pressings can be noticed
e32.ao_yield()
</code>
Thanks for your input. Shoutcast has already been implemented in the version that is currently on CVS but I think the addtion of a settings file is useful and I will add it to the next build.
On the subject of shoutcast, has anyone ahd any success in getting this working with Nokia's new shiny Internet radio player rather than the old sourceforge one. I must admit I have not. It is a shame that Nokia has removed this project from the public domain.
I plan to package pys60, the internet radio player and blastfm into a single .sis shortly which should make life easier for everyone of a less technical bent.
If there proves to be sufficient demand I amy even port the application to C++ with the open source player as a basis.
Richard