xboxscene.org forums

Author Topic: Help With Ooba Multi Browser Script  (Read 674 times)

Phunck

  • Archived User
  • Newbie
  • *
  • Posts: 3
Help With Ooba Multi Browser Script
« on: April 07, 2005, 04:49:00 AM »

I'm having trouble with seemingly random chrashes of this script i'm making... The weird thing is that these chrases only occurs when i'm running the script on the xbox not when i'm running it on the emulator by alexpoet.

Another thing i'm trying is to use a ControlTextBox for displaying progess information (see the OpenUrl function). But it does not work ... It seems to me that the gui is not being updated while the script is running. Is there anyway of forcing a redraw of the screen?




OOBA.PY:
Note if you try out the code you'll need to copy lyricspanel.png to the same folder as this script and create a cache subfolder also. Note this is my first python script ever so excuse any weirdness, but feel free to give advice :-).
CODE

# ScriptName   : ooba.py   (Browse using RegExp's, couldn't think of a good name)
# Version   : 0.1 beta
# Author   : Van der Phunck aka Aslak Grinsted. [email protected] <- not cmo but com
# Desc  : flexible browser for streams,images and rawtext.
#
# Based on many scripts but primarily GameSpotPlus & XBMCLyrics.
#
#
# My ambition with this script is that you can give it a list of urls and tell it
# what it should do with "that kind of url".
#
# E.g. mp3,pls&avi files should be played, jpg should be shown and
# http://www.bbc.co.uk/radio/aod/index_choose.shtml should result in a sub menu.
#
#
#
#
#
#
# Version 0.1 beta
# Initial Release


import urllib, re, random, os.path, time, stat, string
import xbmc, xbmcgui
import htmlentitydefs,socket,Image,ImageFile



ACTION_MOVE_LEFT   =  1   
ACTION_MOVE_RIGHT   =  2
ACTION_MOVE_UP  =  3
ACTION_MOVE_DOWN   =  4
ACTION_PAGE_UP  =  5
ACTION_PAGE_DOWN   =  6
ACTION_SELECT_ITEM   =  7
ACTION_HIGHLIGHT_ITEM   =  8
ACTION_PARENT_DIR   =  9
ACTION_PREVIOUS_MENU   = 10
ACTION_SHOW_INFO   = 11
ACTION_PAUSE  = 12
ACTION_STOP  = 13
ACTION_NEXT_ITEM   = 14
ACTION_PREV_ITEM   = 15



ScriptPath  = os.getcwd()
if ScriptPath[-1]==';': ScriptPath=ScriptPath[0:-1]
if ScriptPath[-1]!='\\': ScriptPath=ScriptPath+'\\'

timeout=10.0 #socket timeout
   
try: Emulating = xbmcgui.Emulating #Thanks alot to alexpoet for the xbmc.py,xmbcgui.py emulator. Very useful!
except: Emulating = False

#######################
#   FUNCTIONS     #
#######################

entpat=re.compile("&#?([\w\d]+);", re.IGNORECASE)

#----------viewstates-------------
MENUSTATE=1
IMAGESTATE=2
TEXTSTATE=3

def HTMLDecode(name): #make titles look nicer in menu
   nameout=''
   name=string.replace(name,'&nbsp;',' ') #nbsp looks ugly
   lastidx=0
   for match in entpat.finditer(name):
  try:
     ent=unichr(int(match.group(1)))
  except:
     try:
    ent=unichr(htmlentitydefs.name2codepoint[match.group(1)])
     except: ent='?'
  nameout=nameout+name[lastidx:match.start()]+ent.encode('iso-8859-1')
  lastidx=match.end()
   nameout=nameout+name[lastidx:]
   return nameout

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

def Play(url):
   lowurl=string.lower(url)
   if string.find(lowurl, '.asx')!=-1 or string.find(lowurl, 'www.dr.dk')!= -1:
  data=OpenUrl(url)
  rg = re.compile("]*href=[\"']([^\"'<>]*)", re.IGNORECASE)
  result = rg.findall(data)
  n = len(result)
  if n>0: url=result[0]
   elif string.find(lowurl, '.rpm')==-1:
  data=OpenUrl(url)
  url=data
   print("Playing:"+url)
   xbmc.Player().play(url)

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


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


urlContext=['no context yet!'] #<- this is the url relative urls are evaluated against....
#it is in a list so that i can write to it. Stupid scope rules in python.. global did not help?

urlSplitter=re.compile('^([^/]*?//[^/]*)/[^#\?]*/?')

def GetFullUrl(url): #set urlContext before calling if it is a relative url
   if string.find(url,'://')==-1: #then use urlContext
  m=urlSplitter.match(urlContext[0])
  if url[0]=='/':
     url=m.group(1)+url
  else:
     url=m.group(0)+url
   return url

def OpenUrl(url): #set urlContext before calling if it is a relative url
   #progress = xbmcgui.DialogProgress()
   #progress.create("Reading URL", url)
   win.ShowText("Reading URL\n"+url)
   
   url = GetFullUrl(url)

   if Emulating: print("Opening URL:"+url)
   
   try:
  oldtimeout=socket.getdefaulttimeout()
  socket.setdefaulttimeout(timeout)

  f = urllib.urlopen(url)
  urlContext[0]=f.geturl() #get the new url context
  data = f.read()
  f.close()
  
  socket.setdefaulttimeout(oldtimeout)

   except:
  win.set_viewstate(MENUSTATE)
  raise
  
   #progress.close()
   win.set_viewstate(MENUSTATE)

   
   return data

extre=re.compile('\W?(jpg|jpeg|gif|png)\W?',re.IGNORECASE) #be very liberal with where extension is ... you never know with urls.
def getExtension(url):
   result=extre.findall(url)
   if len(result)>0:
  result=string.lower(result[-1]) #prioritize the last match
  if result=='jpeg': result='jpg'
  return result
   else:
  return ''


def message(line1,line2='',line3=''):
   dialog = xbmcgui.Dialog()
   dialog.ok("Info", line1,line2,line3)
   


########################     ACTIONS

class ActionBase:
   def open(self,url):
  pass
  return None
  
class SubMenuAction(ActionBase):
   def __init__(self,repattern,titleidx,urlidx,linkprefix):
  self.urlidx=urlidx
  self.titleidx=titleidx
  self.repattern=repattern
  self.linkprefix=linkprefix
   
   def open(self,url):
  #TODO: get url contents, parse and return submenu
  submenu=Menu()
  data=OpenUrl(url)
  submenu.set_url(urlContext[0])
  x = re.compile(self.repattern, re.DOTALL|re.IGNORECASE)
  result = x.findall(data)
  n = len(result)
  if n==0:
     win.ShowText('No links in url: '+url+'\n\n'+str(data))
     message('no links?')
     return None
  i = 0
  for i in range(0,n):
     try:
    iurl=self.linkprefix % result[self.urlidx]
    ititle=HTMLDecode(result[self.titleidx])
    item=MenuItem(ititle, iurl)
    submenu.append(item)
     except:
    #ignore all errors in parsing a page.... TODO:log something.
    pass
  return submenu

class PlayAction(ActionBase):
   def open(self,url):
  url=GetFullUrl(url)
  Play(url)
  return None #no sub menu

class ViewImageAction(ActionBase):
   def open(self,url):
  url=GetFullUrl(url)
  print('Opening image:'+url)
  win.ShowImage(url)
  return None #no sub menu

class ViewTextAction(ActionBase):
   def open(self,url):
  url=GetFullUrl(url)
  print('Opening text:'+url)
  data=OpenUrl(url)
  win.ShowText(data)
  return None #no sub menu
  
class ActionList: #ties regexp patterns to desired actions....
   def __init__(self):
  self.items=[]
  self.index=0
  
   def append(self,urlpattern,action):
  self.items.append([re.compile(urlpattern),action])
   
   def open(self,url):
  for i in range(0,len(self.items)):
     item=self.items
     if not(item[0].search(url) is None):
    return item[1].open(url)
  message('No actions found for url:',url)
  print('No actions found for url:'+url)
  return None

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

class MenuItem: #for the mainmenu
   def __init__(self, title, url):
  self.url=url
  self.title=title
  
   def get_url(self): return self.url
   def get_title(self): return self.title

class Menu:
   def __init__(self,title="",url=""):
  self.items=[]
  self.index=0
  self.title=title
  self.url=url
   
   def get_title(self): return self.title
   def set_title(self,title): self.title=title
   def get_url(self): return self.url #used as the urlContext for menuitems
   def set_url(self,url): self.url=url
   
   def append(self,item):
  self.items.append(item)
   
   def pop(self):
  return self.items.pop()
   
   def count(self):
  return len(self.items)
   
   def __iter__(self):
  return self
   def next(self):
  if self.index >= len(self.items):
     raise StopIteration
  self.index = self.index + 1
  return self.items[self.index-1]

   def item(self,idx):
  return self.items[idx]


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

class MainWin(xbmcgui.WindowDialog):
   def __init__(self):

  self.viewstate=MENUSTATE
    
  if Emulating: xbmcgui.Window.__init__(self)  #for emulator to work

  self.menustack=[]
  self.menustack.append(mainmenu)
  
  
  #---------- SetUpControls ------------
  self.player = xbmc.Player()
    
  #PAL/NTSC Support - thanks to solexalex:
  w=self.getWidth()
  h=self.getHeight()
  #Ratio - using PAL for reference:
  self.xratio=float(w/720.0)
  self.yratio=float(h/576.0)

  self.panel = xbmcgui.ControlImage(int(self.xratio*140),int(self.yratio*25),int(self.xratio*580),int(self.yratio*500), ScriptPath+'lyricspanel.png')

  self.addControl(self.panel)
   
  self.title = xbmcgui.ControlFadeLabel(int(self.xratio*270),int(self.yratio*95),int(self.xratio*255),int(self.yratio*25), 'font14','0xFFFFFFFF')
  self.addControl(self.title)

  self.list = xbmcgui.ControlList(int(self.xratio*190),int(self.yratio*130),int(self.xratio*430),int(self.yratio*345))
  self.addControl(self.list)
  
  self.textbox = xbmcgui.ControlTextBox(int(self.xratio*190),int(self.yratio*130),int(self.xratio*430),int(self.yratio*345), 'font14', '0xFFFFFFFF')

  self.image = None
  self.updateMenu()        
  
   def get_viewstate(self):
  return self.viewstate
  
   def set_viewstate(self,state):
#  xbmcgui.lock()
  state2control={MENUSTATE:self.list,IMAGESTATE:self.image,TEXTSTATE:self.textbox}
  control=state2control[state]
  if self.viewstate==state:
     self.setFocus(control)
     return
  try:
     self.removeControl(state2control[self.viewstate])
  except:
     pass
  self.viewstate=state
  self.addControl(control)
  if state==MENUSTATE:
     self.updateMenu()
  self.setFocus(control)
#  xbmcgui.unlock()
  
   def updateMenu(self):
                if not (self.viewstate==MENUSTATE): return
  menu=self.menustack[len(self.menustack)-1]
  self.title.reset()
  self.title.addLabel(menu.get_title())
  self.list.reset()
  for i in range(0,menu.count()):
     item=menu.item(i)
     self.list.addItem(item.get_title())
  self.setFocus(self.list)

   def ShowText(self,txt):
  self.textbox.reset()
  self.textbox.setText(txt)
  self.set_viewstate(TEXTSTATE)

   def ShowImage(self,url):
  ext=getExtension(url);
  localfile=ScriptPath+'cache\\imgtemp.'+ext
  
  oldtimeout=socket.getdefaulttimeout()
  socket.setdefaulttimeout(timeout)
  loc = urllib.URLopener()
  loc.retrieve(url, localfile)
  socket.setdefaulttimeout(oldtimeout)
  #-------------Resize Image-------------   
  im = Image.open(localfile)
  scalex=float(self.getWidth())/float(im.size[0])
  scaley=float(self.getHeight())/float(im.size[1])
  if scalex>scaley: scalex=scaley #keep aspect ratio
  if scaley>scalex: scaley=scalex
  
  PicSize = (int(float(im.size[0])*scalex), int(float(im.size[1])*scaley))
  if scalex<1:
     im.thumbnail(PicSize, Image.ANTIALIAS)
     localfile=ScriptPath+'cache\\imgtemp.png' #best choice for unknown graphics.
     im.save(localfile)
     PicSize=(im.size[0],im.size[1])
  elif scalex<1.1:
     PicSize = (im.size[0], im.size[1]) #dont stretch original size...

  #-------------Display the image--------
  
  self.image = xbmcgui.ControlImage((self.getWidth()-PicSize[0])/2, (self.getHeight()-PicSize[1])/2, PicSize[0], PicSize[1], localfile)   
  
  self.set_viewstate(IMAGESTATE)
  
   

   def onAction(self, action):
  if action == ACTION_PREVIOUS_MENU:
     self.close()
     return
#  try:
  if self.viewstate==MENUSTATE:
     if action == ACTION_SELECT_ITEM:
    menu=self.menustack[len(self.menustack)-1]
    item=menu.item(self.list.getSelectedPosition())
    urlContext[0]=menu.get_url()
    submenu=actions.open(GetFullUrl(item.get_url()))
                         if (not (submenu is None)):
       if submenu.get_title() == '':
      submenu.set_title(item.get_title())
       self.menustack.append(submenu)
       self.updateMenu()
       
     if action == ACTION_PARENT_DIR:
    self.menustack.pop()
    if len(self.menustack)==0:
       self.close()
       return
    self.updateMenu()
     return
    
  if self.viewstate==IMAGESTATE:
     if action == ACTION_PARENT_DIR:
    self.set_viewstate(MENUSTATE)
     return
    
  if self.viewstate==TEXTSTATE:
     if (action == ACTION_PARENT_DIR) or (action == ACTION_SELECT_ITEM):
    self.set_viewstate(MENUSTATE)
     return
    
    
      
#  except:
#     message('Error?')
#     self.close()
   

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





mainmenu=Menu('Choose thy destiny')
actions=ActionList();

actions.append('\.asx$', PlayAction())
actions.append('\.mp3$', PlayAction())
actions.append('\.wmv$', PlayAction())
actions.append('^mms:' , PlayAction())
actions.append('^rtsp:', PlayAction())
actions.append('\.rpm$', PlayAction())
actions.append('\.txt$', ViewTextAction())
actions.append('\W?(jpg|jpeg|gif|png)\W?', ViewImageAction())


mainmenu.items.append(MenuItem('comics.com', 'http://www.comics.com/categories/index.html'))
actions.append('www.comics.com/categories/index.html', \
   SubMenuAction('
Logged

Phunck

  • Archived User
  • Newbie
  • *
  • Posts: 3
Help With Ooba Multi Browser Script
« Reply #1 on: April 07, 2005, 04:51:00 AM »

Sorry about the multi-post but i got an sql error when posting the first time, so i thought it didn't post.
Logged