import gtk import gtk.glade import os import tempfile import subprocess import gobject import math import dbus import hashlib import net.Lliurex.Amic.Render import net.Lliurex.Amic.Grid import net.Lliurex.Amic.JoyManager import net.Lliurex.Amic.Configuration import net.Lliurex.Amic.Resources rsrc_path=net.Lliurex.Amic.Resources.get_rsrc() class Player: def __init__(self,grid_name,theme="Default"): self.log("Init") self.theme=theme self.scan_time=0 self.joy_buttons=None self.joy_axes=None self.usable_axes=[] self.audios={} self.speech_hash={} self.isJoystick=False bus=dbus.SessionBus() self.audio_server=bus.get_object("net.Lliurex.Media.AudioServer","/net/Lliurex/Media/AudioServer") self.resources=net.Lliurex.Amic.Resources.Resources() self.log("Loading ui") uitree=gtk.glade.XML(rsrc_path+"/ui.glade") self.winmain=uitree.get_widget("winmain") self.drawingarea=uitree.get_widget("drawingarea") self.log("Connecting events") self.winmain.connect("destroy",self.OnDestroy) self.winmain.connect("key-press-event",self.OnKey) self.drawingarea.add_events(gtk.gdk.BUTTON_PRESS_MASK) self.drawingarea.connect("button-press-event",self.OnClick) self.drawingarea.set_extension_events(gtk.gdk.EXTENSION_EVENTS_ALL) self.log("Displaying") self.winmain.show_all() self.winmain.fullscreen() self.log("Running render") self.render=net.Lliurex.Amic.Render.Render(self.drawingarea) # ToDo: # remove hardcoded path, using settings instead self.log("Loading menu grid") grid=net.Lliurex.Amic.Grid.Grid() grid.load("/var/lib/lliurex-amic/xml/grids/Menus.AmicMenu/Parlador.grid",self.theme) self.render.SetMenu(grid) self.log("Loading grid") grid=net.Lliurex.Amic.Grid.Grid() grid.load(grid_name,self.theme) self.render.LoadGrid(grid) self.render.ConnectTouch(self.OnTouch) self.render.scan_mode=net.Lliurex.Amic.Render.Render.SCAN_V self.log("Configuring input devices") self.conf= net.Lliurex.Amic.Configuration.Configuration() self.log("Configuring joysticks...") self.usable_axes=self.conf.axes.split(',') self.log("Configured axes: "+str(self.usable_axes)) for n in range(0,len(self.usable_axes)): try: self.usable_axes[n]=int(self.usable_axes[n]) except ValueError: pass except TypeError: pass self.joystick=net.Lliurex.Amic.JoyManager.Joy() for joy in self.joystick.get_joy_list(): id,name,axes,buttons=joy self.log("Joystick:"+name) if name==self.conf.joy_name: self.log("Found joystick!") self.joystick.init_joy(id) self.isJoystick=True #If desired joystick has been found, just turn it on. Otherwise joystick managment is disabled break self.log("Configuring mices...") for mouse in gtk.gdk.devices_list(): mouse.set_mode(gtk.gdk.MODE_SCREEN) if mouse.name==self.conf.mouse: self.log("Found mouse!! ("+mouse.name+")") self.render.mouse_device=mouse.name gobject.timeout_add(50,self.OnTick) def log(self,txt): print("[Player]:%s" % (txt)) #Event hooks def OnTick(self): self.scan_time+=50 if self.scan_time>(self.conf.scanperiod*1000): self.scan_time=0 #print "SCAN !!!" self.render.PushScan() if not self.joystick==None and self.isJoystick: axes=self.joystick.get_all_axes() if self.joy_axes==None: for n in range(0,len(axes)): if n in self.usable_axes: ax=math.fabs(axes[n]) if ax>self.conf.threshold: self.render.PushInput() self.log("Joystick input ax="+str(ax)) break else: for n in range(0,len(axes)): if n in self.usable_axes: ax=math.fabs(axes[n]) bx=math.fabs(self.joy_axes[n]) if ax>self.conf.threshold and not bx>self.conf.threshold: self.log("Joystick input ax="+str(ax)+",bx="+str(bx)) self.render.PushInput() break self.joy_axes=axes #Check if joystick button detection is enabled if self.conf.buttons: buttons=self.joystick.get_all_buttons() if self.joy_buttons==None: for n in range(0,len(buttons)): if buttons[n]: self.render.PushInput() break else: for n in range(0,len(buttons)): if buttons[n] and not self.joy_buttons[n]: self.render.PushInput() break self.joy_buttons=buttons return True def OnDestroy(self,data): self.log("disconnecting from lliurex audio server") self.audio_server.Disconnect() gtk.main_quit() def OnKey(self,widget,event): if event.keyval==gtk.keysyms.Escape: self.log("disconnecting from lliurex audio server") self.audio_server.Disconnect() self.log("Quit requested") gtk.main_quit() def OnClick(self,widget,event): pass #print "Click!!: " + str(event) def OnTouch(self,pictogram): action_name,action_data=pictogram.action self.log("Action event:"+action_name) self.log("Action data:"+str(action_data)) if action_name=="menuaction": if action_data[0]=="readstack": self.log("reading stack") audio_stack=None id=0 for pict in self.render.pictogram_stack: self.log("Pictogram "+str(pict.name)) self.log("data :") print pict.action[1][0] if pict.action[0]=="sound": wav_path=str(self.resources.get_audios())+"/"+str(pict.action[1][0]) if audio_stack==None: audio_stack=wav_path else: audio_stack=audio_stack+","+wav_path if pict.action[0]=="speech": self.text2wave("WAVE"+str(id),pict.action[1][0]) if audio_stack==None: audio_stack="/tmp/WAVE"+str(id)+".wav" else: audio_stack=audio_stack+",/tmp/WAVE"+str(id)+".wav" id=id+1 self.log("Generated playlist:"+audio_stack) #self.audio_server.PlayList("/tmp/",audio_stack) self.audio_server.PlayFiles(audio_stack) self.render.pictogram_stack=[] if action_data[0]=="readlast": self.log("reading last") pict_count = len(self.render.pictogram_stack) if pict_count>0: pict = self.render.pictogram_stack[pict_count-1] if pict.action[0]=="speech": hash=hashlib.sha224(pict.action[1][0]).hexdigest() print hash if hash in self.speech_hash: self.audio_server.Play(self.speech_hash[hash]) else: wav_path="/tmp/"+hash+".wav" self.text2wave(hash,pict.action[1][0]) self.speech_hash[hash]=self.audio_server.LoadMedia(wav_path) self.audio_server.Play(self.speech_hash[hash]) if action_data[0]=="erase": self.log("erase stack") self.render.pictogram_stack=[] if action_data[0]=="eraseword": self.log("erase last") self.render.pictogram_stack.pop() if action_name=="speech": self.render.pictogram_stack.append(pictogram) if action_name=="sound": self.render.pictogram_stack.append(pictogram) if action_name=="child": #grid=net.Lliurex.Amic.Grid.Grid() #grid.load(rsrc_path+"/"+action_data[0]) #self.render.LoadGrid(grid) print action_data found=False proj=str(action_data[0]) proj=proj.replace("/",".AmicProject/") file=self.resources.get_grids()+"/"+proj+".grid" self.log("Looking up " + file+ "...") for g in self.render.grids: self.log("* " + g.filename+ "...") if g.filename==file: self.log("Matching grid name " + g.filename) g.parent=self.render.grid self.render.SetGrid(g) found=True break if not found: #file=net.Lliurex.Amic.Grid.scan_grids(net.Lliurex.Amic.Resources.get_grids(),action_data[0]) if os.path.exists(file): found=True self.log("Grid found, loading...") grid=net.Lliurex.Amic.Grid.Grid() grid.load(file,self.theme) self.render.LoadGrid(grid) grid.parent=self.render.grid self.render.SetGrid(grid) else: self.log("File not found:" + file) if not found: self.log("Grid not found!!!") if action_name=="parent": if not self.render.grid.parent==None: self.render.SetGrid(self.render.grid.parent) def text2wave(self,id,text): p = subprocess.Popen(["text2wave","-o","/tmp/"+str(id)+".wav"],stdin=subprocess.PIPE) p.stdin.write("\""+text.encode("iso-8859-1")+"\"") p.stdin.close() p.wait()