XBMC Community Forum  

Go Back   XBMC Community Forum > Development > XBMC Development

XBMC Development Developers forums for XBMC related development. Programmers/Coders only!
No end-user support, no bug reports, and no feature/function requests here!
Please, add platform prefix for suggestions that are not platform-independent!:
Thread prefixes; "[LINUX]", "[LIVE]", "[MAC]", "[WINDOWS]", and "[XBOX]"

Reply
 
Thread Tools Search this Thread Display Modes
Old 2004-02-21, 20:58   #1
IndieRockSteve
Senior Member
 
Join Date: Oct 2003
Posts: 195
IndieRockSteve is on a distinguished road
Default

i've made a couple changes to the script, this is my first time using python, so i didn't delve far in, but what i did was cause the numbers placed at the beginning of the filenames to show a leading zero to keep them listed in order on the screen and i also had it place the bitrate right after the count number so it was easy to see what bitrate the stream was at.

if i feel like teaching myself enough about python i'll set it up so the output file name follows a user-definable string. i'll also see if i can do some better parsing to get the station name out of the retreived field and seperate it from the description, but this is obviously a more difficult algorithm to implement, so it will prbly take me some time.

anyway, here's what i changed so someone can change the cvs copy if they want...

line 138 becomes:
filename = '%sk ' % bitrate + strip(filename, 0, xfs_file_length - 4 - 3 - 5 - 1) + '.pls'

and line 237 becomes:
filename = '%02d ' + get_filename(plsfilecontent, station.get_bitrate())

so now it looks like:
01 128k somafm....
IndieRockSteve is offline   Reply With Quote
Old 2004-02-21, 21:04   #2
IndieRockSteve
Senior Member
 
Join Date: Oct 2003
Posts: 195
IndieRockSteve is on a distinguished road
Default

ok, i've decided to get it to sort by bitrate too...
i'm working on that right now and will post the change to get that to work...
IndieRockSteve is offline   Reply With Quote
Old 2004-02-21, 21:51   #3
IndieRockSteve
Senior Member
 
Join Date: Oct 2003
Posts: 195
IndieRockSteve is on a distinguished road
Default

hehe, ok, i have it sorting by bitrate now, wasn't that hard...
but, in doing so i discovered a parseing flaw in the script that prevented stations that don't have a "now playing" line from being grabbed, so i fixed the function responsible for this and now it seems to work...

here's the function i changed:
Quote:
# gets the stations out of the html page by looking for a 'filename.pls' string.

def get_stations(htmlcontent):
stations = []
for line in htmlcontent:
if line.find('filename.pls') != -1:
if line.find('now playing') !=-1:
line_count = 7
else:
line_count = 6
#always seven lines later its the html content with the bitrate
bitrate = get_bitrate(htmlcontent[htmlcontent.index(line) + line_count])
if min_bitrate <= bitrate <= max_bitrate:
stations.append(plsdescriptor(line, bitrate))
if len(stations) == max_number_of_stations:
break
return stations
so this will make sure all the stations get added.

and line 79 becomes:
shoutcast_genre_path = 'http://www.shoutcast.com/directory/?...y=bitrate'

this will sort the list with highest bitrate first.
IndieRockSteve is offline   Reply With Quote
Old 2004-02-21, 22:04   #4
IndieRockSteve
Senior Member
 
Join Date: Oct 2003
Posts: 195
IndieRockSteve is on a distinguished road
Default

anyone know why the dialog.yesno doesn't autosize correctly?
the dialog.create seems to autosize correctly

thanks!
IndieRockSteve is offline   Reply With Quote
Old 2004-02-23, 06:49   #5
Zinger
Junior Member
 
Join Date: Feb 2004
Posts: 25
Zinger is on a distinguished road
Default

i found this issue also. * i rewrote with regex. *no more counting lines. *grouping makes it easy to pull out the info from the html line without needing external functions to split strings.

Quote:
title = re.compile('target="_scurl" href=.*>(.*)</a>')
bitrate = re.compile('>(\d+)<')
rn_number = re.compile('rn=(\d+)&file=filename.pls')

for line in htmlcontent:
# search for rn number of shoutcast playlist file
m = rn_number.search(line)
if m:
rn_number = m.group(1)
if line.find('/tr>') != -1 and rn_number != 0:
genres[genre].append([rn_number,bitrate,title])
rn_number = 0 * *
if rn_number != 0: *
m = title.search(line)
if m:
title = m.group(1)
m = bitrate.search(line)
if m:
bitrate = m.group(1)
Zinger is offline   Reply With Quote
Old 2004-02-24, 17:14   #6
IndieRockSteve
Senior Member
 
Join Date: Oct 2003
Posts: 195
IndieRockSteve is on a distinguished road
Default

zinger, awesome, that was the next peice of code i wanted to rewrite.

i'm gunna merge this with my test tree and test it out.
IndieRockSteve is offline   Reply With Quote
Old 2004-02-25, 23:32   #7
IndieRockSteve
Senior Member
 
Join Date: Oct 2003
Posts: 195
IndieRockSteve is on a distinguished road
Default

zinger, i get a line error about
"for line in htmlcontent"
as invalid syntax

any ideas? maybe i did something wrong in pasting it?
IndieRockSteve is offline   Reply With Quote
Old 2004-02-26, 03:06   #8
Zinger
Junior Member
 
Join Date: Feb 2004
Posts: 25
Zinger is on a distinguished road
Default

sorry, thats from a script i'm working on. not for shoutcast.py. i never fixed shoutcast_update after finding the issue. here is my modified version though. it adds the ability to specify bitrate min/max and channel number by genre. also creates pls with only one stream so xbmc will just play the stream instead of opening pls first.

Quote:
#shoutcast .pls updater for xbmc. use at your own risk!
#edit config part in script, copy script to $home\script\ directory,
#start and enjoy.
#keep in mind, that updating too frequently or with too many
#genres and/or stations will "bann" you from shoutcast for ~24h.
#feel free to edit, bugfix, enhance and so on... :-)
#initial version by nei

# known issues:
# -none for the moment;-)


####################### config ########################

#directory where you want to store your radio stations
shoutcast_dir = 'e:\\music\\radio\\'

#genres [number of channels, minimum bitrate,maximum bitrate], leave [] empty for defaults.
genres = {'topten':[20,128,256], 'alternative':[20,128,256], 'metal':[],'rock':[],'rnb':[5,128,256],'hip hop':[4,128,256], 'comedy':[2,1,256], '70s':[10,96,256], '80s':[]}

#minimum bitrates for stations (0 -> all)
min_bitrate = 128

#maximum bitrate for stations (999 -> all)
max_bitrate = 256

#(0 or 1) to enable or disable the bitrate in the filename
show_bitrate_in_filename = 1

#number of stations to retrieve.
max_number_of_stations = 10


################################################## #####


#do not edit from here on (if you don't know what you're doing, of course;-)
import xbmc, xbmcgui
import urllib2, os, sys, traceback
from os import makedirs
from os.path import normpath,dirname,exists,abspath,join

xfs_file_length = 42

shoutcast_genre_path = 'http://www.shoutcast.com/directory/?sgenre=%s&numresult=100'

#chars accepted for filenames on xfs
legal_chars = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvw xyz1234567890!#$%&'()-@[]^_`{}~."

#class for storing pls stuff.
class plsdescriptor:
#converts the line with the filename.pls in an url
def (self, fileline, bitrate):
startindex = fileline.find('/sbin')
endindex = fileline.find('filename.pls') + 12
self.fileurl = 'http://www.shoutcast.com' + strip(fileline, startindex, endindex)
self.bitrate = bitrate

#returns the url to be used for getting the pls file content.
def get_fileurl(self):
return self.fileurl

#returns the bitrate for this plsdescriptor.
def get_bitrate(self):
return self.bitrate


# removes all chars at the end, that are loner than length.
# stupid to implement this myself, but couldn't find an
# approriate function for it...
def strip(stringtostrip, startindex, endindex):
if endindex >= len(stringtostrip):
endindex = len(stringtostrip) - 1
strippedstring = ''
i = startindex
while i <= endindex:
strippedstring = strippedstring + stringtostrip[i]
i += 1
return strippedstring.rstrip() #remove newline character (and any ending whitespaces)


#substitutes all illegal chars for xfs with ' '
def subst_illegal_chars(stringtocheck):
for char in stringtocheck:
if legal_chars.find(char) == -1:
stringtocheck = stringtocheck.replace(char, ' ')
return stringtocheck


# gets the filename out of the first title in the pls file.
# removes the (#2 - 187/750) and strips it to characters.
def get_filename(plsfilecontent, bitrate):
filename = ''
for line in plsfilecontent:
if line.startswith('title1='):
filename = line
break
if filename == '': #happens, if there were too many requests
raise exception('too many requests, try again tomorrow...')
splittedname = filename.split(') ', 1)
filename = splittedname[1]
if show_bitrate_in_filename == 1:
# -4 -> ".pls", -3 -> i.e.: "19 ", -5 -> 999k -1 -> index
filename = strip(filename, 0, xfs_file_length - 4 - 3 - 5 - 1) + ' %sk.pls' % bitrate
else:
# -4 -> ".pls", -3 -> i.e.: "19 ", -1 -> index
filename = strip(filename, 0, xfs_file_length - 4 - 3 - 1) + '.pls'
filename = subst_illegal_chars(filename)
return filename

#converts non http chars to them.
#enhance if necessary.
def get_genre_url(genre):
genreurl = genre.replace(' ', '\%20')
genreurl = genreurl.replace('&', '\%26')
return genreurl


#creates missing directories for the given path
def make_path(path):
dpath = normpath(dirname(path))
if not exists(dpath): makedirs(dpath)
return normpath(abspath(path))


# saves the content under the given path. (i.e. f:\music\shoutcast\blabla.pls)
def save_file(dir, filename, content):
dir = make_path(dir)

file = open(dir + '\\' + filename, 'w')
file.write("[playlist]\n")
file.write("numberofentries=1\n")
for line in content:
if line.startswith('file1=') or line.startswith('title1=') or line.startswith('length1=') or line.startswith('version='):
file.write(line)
file.close


#just strips the line at the right indices. line will always look something like this:
# <td nowrap align="center" bgcolor="#001e5a"><font face="arial, helvetica" size="2" color="#ffffff">128</font></td>
#returns an int reprecenting the bitrate or -1, if conversion failed
def get_bitrate(bitrateline):
bitratestring = strip(bitrateline, 105, len(bitrateline) - 14)
bitrate = -1
try:
bitrate = int(bitratestring)
except:
print "parsing of bitrate failed: \n" + bitrateline
return bitrate


# gets the stations out of the html page by looking for a 'filename.pls' string.
def get_stations(htmlcontent, genre):
stations = []
for line in htmlcontent:
if line.find('filename.pls') != -1:
#always seven lines later its the html content with the bitrate
bitrate = get_bitrate(htmlcontent[htmlcontent.index(line) + 7])
if genres[genre][1] <= bitrate <= genres[genre][2]:
stations.append(plsdescriptor(line, bitrate))
if len(stations) == genres[genre][0]:
break
return stations

#delete directory
def clean_dir(dirname):
for root, dirs, files in os.walk(dirname):
for name in files:
os.remove(join(root, name))

#dialog asking user if he wants to start the update
def start_update():
dialog = xbmcgui.dialog()
title = "shoutcast update"
question = "do you want to update %s?" % shoutcast_dir
config1 = "number of genres to update: %s" % len(genres)
selected = dialog.yesno(title, question, config1)
return selected

##### main() #####
if start_update():
try:
dialog = xbmcgui.dialogprogress()
genreindex = 1
for genre in genres.keys():
if len(genres[genre]) == 0:
genres[genre]=[max_number_of_stations,min_bitrate, max_bitrate]
genrestatus = 'updating ' + genre + ' (%s/%s) numer of stations:%s\nmin bitrate:%s max bitrate:%s' % (genreindex, len(genres),genres[genre][0],genres[genre][1],genr es[genre][2])
dialog.create('shoutcast update', genrestatus + "\ngetting station list...")
clean_dir(shoutcast_dir + subst_illegal_chars(genre))
genrepage = urllib2.urlopen(shoutcast_genre_path % get_genre_url(genre))
stations = get_stations(genrepage.readlines(),genre)
genrepage.close()
dialog.close()
dialog.create('shoutcast update', genrestatus + "\nprocessing stations...")
numberofstations = len(stations)
stationindex = 1
for station in stations:
if dialog.iscanceled():
break
dialog.update((stationindex * 100)/ numberofstations)
plsfile = urllib2.urlopen(station.get_fileurl())
plsfilecontent = plsfile.readlines()
plsfile.close()
directory = shoutcast_dir + subst_illegal_chars(genre) + '\\'
filename = '%s ' + get_filename(plsfilecontent, station.get_bitrate())
save_file(directory, filename % stationindex, plsfilecontent)
stationindex += 1
if dialog.iscanceled():
break
dialog.close()
genreindex += 1
if dialog.iscanceled():
dialog.close()
except:
dialog.close()
dialog = xbmcgui.dialog()
traceback.print_exc()
dialog.ok("unexpected error", "%s\npress white button after closing the dialog for more info." % sys.exc_info()[0])
Zinger is offline   Reply With Quote
Old 2004-02-26, 03:17   #9
Zinger
Junior Member
 
Join Date: Feb 2004
Posts: 25
Zinger is on a distinguished road
Default

you should be able to use the code. with some changes. it pulls the title from the page not the pls and only grabs the rn number to build the link to the pls file. i've been working on a live player (does not download anything to hd) and provides all genre/station stuff in gui dialogs. but maybe you can port it into the updater script. good luck.
Zinger is offline   Reply With Quote
Old 2004-02-26, 20:36   #10
IndieRockSteve
Senior Member
 
Join Date: Oct 2003
Posts: 195
IndieRockSteve is on a distinguished road
Default

ah, ok, so i have to add the other info.

so should i continue working on this if your writing a cooler version?
IndieRockSteve is offline   Reply With Quote
Reply

Bookmarks


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
update jmejiaa XBMC for Xbox Specific Support 2 2005-11-16 04:58
Shoutcast playlist script update BelleDesirePC Plugin/Script (Python) Help and Support 5 2005-03-08 19:48
Shoutcast playlist script update BelleDesirePC Plugin/Script (Python) Development 1 2005-03-05 12:47
shoutcast update python script... IndieRockSteve XBMC for Xbox Specific Support 0 2004-02-16 19:57
Auto Update/Script Update TheKillar XBMC Feature Suggestions 1 1970-01-01 02:00


All times are GMT +2. The time now is 12:19.


Protected by Akismet, We recommend WordPress blogs
Copyright © 2008, XBMC Project