[tuxdroid-svn] r529 - api/python/trunk
Status: Beta
Brought to you by:
ks156
From: remi <c2m...@c2...> - 2007-09-19 08:09:52
|
Author: remi Date: 2007-09-19 10:09:47 +0200 (Wed, 19 Sep 2007) New Revision: 529 Modified: api/python/trunk/tuxapi_class.py Log: UPD: TTS speak system UPD: Socket send Modified: api/python/trunk/tuxapi_class.py =================================================================== --- api/python/trunk/tuxapi_class.py 2007-09-18 15:00:17 UTC (rev 528) +++ api/python/trunk/tuxapi_class.py 2007-09-19 08:09:47 UTC (rev 529) @@ -68,7 +68,7 @@ Call the destroying function at the end of your script for closing the api correctly. >>> tux.destroy() - + "tts" class is compatible with "tuxttsd" v 0.3.0 or more recent """ #-------------------------------------------------------------------------- @@ -81,6 +81,7 @@ Example: >>> tux=TUXTCPCommunicator() """ + self.sock = None self.main_thread_list=[] self.exit_flag=False self.tcp_mutex=threading.Lock() @@ -136,6 +137,15 @@ print "Tux object has been destroyed" #-------------------------------------------------------------------------- + # Send a frame to tuxd + #-------------------------------------------------------------------------- + def _sock_send_frame(self, frame): + try: + self.sock.send(frame) + except: + pass + + #-------------------------------------------------------------------------- # SYSTEM function #-------------------------------------------------------------------------- def _loop_tux_tcp_msg(self): @@ -238,7 +248,7 @@ lock[1].acquire() lock[1].notify() lock[1].release() - self.lock_list.pop(i) + self.lock_list = [] self.lock_list_mutex.release() #-------------------------------------------------------------------------- @@ -441,7 +451,7 @@ if ord(data[5])==0: if self.event.on_spin_stop!=None: self.event.on_spin_stop() - #on status + #on status if self.event.on_status!=None: self.event.on_status(data) @@ -510,7 +520,7 @@ return False # Fill up the end of the frame with 0 data.extend([0] * (TCPIP_FRAME_LENGTH - len(data))) - self.parent.sock.send("".join( [chr(x) for x in data] )) + self.parent._sock_send_frame("".join( [chr(x) for x in data] )) return self.parent.status.rsp_status(connection_command, timeout=5) #-------------------------------------------------------------------------- @@ -554,7 +564,7 @@ assert 0 < id < 0xFFFF id_msb = id >> 8 id_lsb = id & 0xFF - ack_frame = self.tux_connection(TUX_CONNECTION_CONNECT, + ack_frame = self.tux_connection(TUX_CONNECTION_CONNECT, [id_msb, id_lsb]) if not ack_frame or ord(ack_frame[5]) != TUX_CONNECTION_ACK: return False @@ -589,7 +599,7 @@ Get the ID of tux currently connected Returns: - "id" as uint16 (0 < id < 65536) if the command has been sent + "id" as uint16 (0 < id < 65536) if the command has been sent successfully, "False" otherwise. """ @@ -614,7 +624,7 @@ to issue this command multiple times until you don't get any new ID. Returns: - "id" as uint16 (0 < id < 65536) if the command has been sent + "id" as uint16 (0 < id < 65536) if the command has been sent successfully, "False" otherwise. """ @@ -646,7 +656,7 @@ assert 0 < id < 0xFFFF id_msb = id >> 8 id_lsb = id % 256 - ack_frame = self.tux_connection(TUX_CONNECTION_CHANGE_ID, + ack_frame = self.tux_connection(TUX_CONNECTION_CHANGE_ID, [id_msb, id_lsb]) if not ack_frame or ord(ack_frame[5]) != TUX_CONNECTION_ACK: return False @@ -713,7 +723,7 @@ "True" if the command has been sent successfully, "False" otherwise. """ - ack_frame = self.tux_connection(TUX_CONNECTION_WIRELESS_CHANNEL, + ack_frame = self.tux_connection(TUX_CONNECTION_WIRELESS_CHANNEL, [channel]) if not ack_frame or ord(ack_frame[5]) != TUX_CONNECTION_ACK: return False @@ -1596,7 +1606,7 @@ return 2 data=(DEST_TUX,SD_DEFAULT,DATA_TP_CMD,SUBDATA_TP_STRUCT, \ fct,cmd,param1,param2,param3,0,0,0,0,0,0,0) - self.parent.sock.send("".join( [chr(x) for x in data] )) + self.parent._sock_send_frame("".join( [chr(x) for x in data] )) if self.no_ack: return 2 else: @@ -1624,7 +1634,7 @@ return 2 data=(DEST_TUX,SD_DEFAULT,DATA_TP_CMD,SUBDATA_TP_RAW, \ cmd,param1,param2,param3,0,0,0,0,0,0,0,0) - self.parent.sock.send("".join( [chr(x) for x in data] )) + self.parent._sock_send_frame("".join( [chr(x) for x in data] )) if self.no_ack: return 2 else: @@ -2597,7 +2607,7 @@ return 0 data=(DEST_TUX,SD_DEFAULT,DATA_TP_REQ,SUBDATA_TP_STATUS,DATA_STATUS, \ 0,0,0,0,0,0,0,0,0,0,0) - self.parent.sock.send("".join( [chr(x) for x in data] )) + self.parent._sock_send_frame("".join( [chr(x) for x in data] )) return self.rsp_status(DATA_STATUS) #-------------------------------------------------------------------------- @@ -3487,7 +3497,7 @@ return 2 data=(DEST_SUB_DAEMON,SD_DEFAULT,DATA_TP_CMD,SUBDATA_TP_STRUCT,cmd, param1,param2,param3,0,0,0,0,0,0,0,0) - self.parent.sock.send("".join( [chr(x) for x in data] )) + self.parent._sock_send_frame("".join( [chr(x) for x in data] )) return 0 #-------------------------------------------------------------------------- @@ -3501,7 +3511,7 @@ return 2 data=(DEST_SUB_DAEMON,SD_DEFAULT,DATA_TP_REQ, \ SUBDATA_TP_INFO,req,param1,param2,param3,0,0,0,0,0,0,0,0) - self.parent.sock.send("".join( [chr(x) for x in data] )) + self.parent._sock_send_frame("".join( [chr(x) for x in data] )) return self.rsp_info(req) #-------------------------------------------------------------------------- @@ -3571,7 +3581,7 @@ ord(name[2]),ord(name[3]),ord(name[4]),ord(name[5]), ord(name[6]),ord(name[7]),ord(name[8]),ord(name[9]), ord(name[10])) - self.parent.sock.send("".join( [chr(x) for x in data] )) + self.parent._sock_send_frame("".join( [chr(x) for x in data] )) self.parent.my_name=name self.last_ack=self.cmd_ack() @@ -3724,7 +3734,7 @@ return (0,0,0,0,0) data=(DEST_TUX,SD_DEFAULT,DATA_TP_REQ,SUBDATA_TP_INFO, \ TUX_REQ_INFO_VERSION,cpu_index,0,0,0,0,0,0,0,0,0,0) - self.parent.sock.send("".join( [chr(x) for x in data] )) + self.parent._sock_send_frame("".join( [chr(x) for x in data] )) frame = self.parent.status.rsp_status(TUX_REQ_INFO_VERSION) if len(frame) > 0: ver_major=ord(frame[5]) @@ -3958,10 +3968,10 @@ Constructor of this class """ self.parent=parent - self.con_thread_list=[] + self.con_thread_list = [] self.connected=False - self.tcp_mutex=threading.Lock() - self.tts_mutex=threading.Lock() + self.tcp_mutex = threading.Lock() + self.tts_mutex = threading.Lock() self.tcp_data_list = [] self.print_status = False self.on_sound_on = None @@ -3977,6 +3987,77 @@ self.ac_address='localhost' self.authorized_voices_list = [] self.voice_loaded = False + self.speaking_stack = [] + self.speaking_stack_mutex = threading.Lock() + + def speaking_stack_add(self, speaking_conf): + self.speaking_stack_mutex.acquire() + self.speaking_stack.append(speaking_conf) + self.speaking_stack_mutex.release() + + def speaking_stack_get_size(self): + self.speaking_stack_mutex.acquire() + val = len(self.speaking_stack) + self.speaking_stack_mutex.release() + return val + + def speaking_stack_loop(self): + while self.connected: + if self.speaking_stack_get_size() > 0: + if not self.tts_mutex.locked(): + self.speaking_stack_mutex.acquire() + curr_speaking_conf = self.speaking_stack.pop(0) + self.speaking_stack_mutex.release() + self.my_pitch = curr_speaking_conf[1][1] + self.my_voice = curr_speaking_conf[1][0] + if curr_speaking_conf[2] == True: + self.__speak_free(curr_speaking_conf[0]) + else: + self.__speak(curr_speaking_conf[0]) + curr_speaking_conf[3].acquire() + curr_speaking_conf[3].notify() + curr_speaking_conf[3].release() + time.sleep(0.1) + self.speaking_stack_mutex.acquire() + for curr_speaking_conf in self.speaking_stack: + curr_speaking_conf[3].acquire() + curr_speaking_conf[3].notify() + curr_speaking_conf[3].release() + self.speaking_stack_mutex.release() + + def speak(self, text): + if not self.connected: + return + speaking_conf = [] + speaking_conf.append(text) + voice_conf = [] + voice_conf.append(self.my_voice) + voice_conf.append(self.my_pitch) + speaking_conf.append(voice_conf) + speaking_conf.append(False) + my_lock = threading.Condition(threading.Lock()) + speaking_conf.append(my_lock) + self.speaking_stack_add(speaking_conf) + my_lock.acquire() + my_lock.wait() + my_lock.release() + + def speak_free(self, text): + if not self.connected: + return + speaking_conf = [] + speaking_conf.append(text) + voice_conf = [] + voice_conf.append(self.my_voice) + voice_conf.append(self.my_pitch) + speaking_conf.append(voice_conf) + speaking_conf.append(True) + my_lock = threading.Condition(threading.Lock()) + speaking_conf.append(my_lock) + self.speaking_stack_add(speaking_conf) + my_lock.acquire() + my_lock.wait() + my_lock.release() #-------------------------------------------------------------------------- # Allow to connect the api to tuxttsd automatically @@ -4086,10 +4167,17 @@ t.setName('tts._loop_tux_data_dispatching') t.start() self.con_thread_list.append(t) + t=threading.Thread(target=self._loop_tcp_tts_msg) t.setName('tts._loop_tcp_tts_msg') t.start() self.con_thread_list.append(t) + + t=threading.Thread(target=self.speaking_stack_loop) + t.setName('tts.speaking_stack_loop') + t.start() + self.con_thread_list.append(t) + self.get_sound_state() return True @@ -4114,6 +4202,15 @@ self.sock.close() #-------------------------------------------------------------------------- + # Send a frame to tuxttsd + #-------------------------------------------------------------------------- + def _sock_send_frame(self, frame): + try: + self.sock.send(frame) + except: + pass + + #-------------------------------------------------------------------------- # SYSTEM function #-------------------------------------------------------------------------- def _loop_tcp_tts_msg(self): @@ -4212,7 +4309,7 @@ print "WARNING : Resource text to speech Acapela not found" return data=(cmd_type,cmd,param1,param2,param3,param4) - self.sock.send("".join( [chr(x) for x in data] )) + self._sock_send_frame("".join( [chr(x) for x in data] )) #-------------------------------------------------------------------------- # Reinit sound to tux sound card device @@ -4242,24 +4339,13 @@ Select a speaker voice Parameters: - "speaker" as integer : speaker id (SPK_FR_MALE|SPK_FR_FEMALE| - SPK_US_MALE|SPK_US_FEMALE| - SPK_B_FEMALE|SPK_D_MALE| - SPK_D_FEMALE|SPK_GB_MALE| - SPK_GB_FEMALE|SPK_AR_FEMALE| - SPK_DK_FEMALE|SPK_E_FEMALE| - SPK_I_FEMALE|SPK_NL_FEMALE| - SPK_N_FEMALE|SPK_P_FEMALE| - SPK_S_MALE|SPK_S_FEMALE) + "speaker" as integer : speaker id (SPK_FR_MALE|SPK_FR_FEMALE| + SPK_US_MALE|SPK_US_FEMALE) "pitch" as integer : raised pitch in % (100..330) Example: >>> tux.tts.select_voice(SPK_FR_MALE,100) """ - if speaker not in SPK_VOICE_LIST: - if self.parent.print_warnings: - print " Invalid speaker" - return if (pitch<100) or (pitch>330): if self.parent.print_warnings: print " Pitch not in range (100 - 330)" @@ -4367,7 +4453,7 @@ #-------------------------------------------------------------------------- # Speak a text with the acapela text to speech engine #-------------------------------------------------------------------------- - def speak(self,text): + def __speak(self,text): """ Speak a text with the acapela text to speech engine @@ -4393,26 +4479,35 @@ (text_length & 0x0000FF00) >> 8, (text_length & 0x000000FF), \ self.my_voice, self.my_pitch) self.voice_loaded = False - self.sock.send(text_to_send) + self._sock_send_frame(text_to_send) counter = 0 while ((self.voice_loaded == False) and (counter < 300)): counter = counter + 1 self.parent.sys.wait(0.1) + if self.speaking_stack_get_size() > 0: + break if counter == 300: self.stop() print "TTS Speak : Voice not loaded" + self.tts_mutex.release() return False self.parent.cmd.audio_channel_tts() counter = 0 while ((self.sound_on == False) and (counter < 100)): counter = counter + 1 self.parent.sys.wait(0.1) + if self.speaking_stack_get_size() > 0: + break if counter == 100: self.stop() + self.parent.cmd.audio_channel_general() print "TTS Speak : Timeout 10 sec" + self.tts_mutex.release() return False while self.sound_on == True: self.parent.sys.wait(0.1) + if self.speaking_stack_get_size() > 0: + break self.parent.cmd.audio_channel_general() self.tts_mutex.release() return True @@ -4420,7 +4515,7 @@ #-------------------------------------------------------------------------- # Speak a text with the acapela text to speech engine in free mode #-------------------------------------------------------------------------- - def speak_free(self,text): + def __speak_free(self,text): """ Speak a text with the acapela text to speech engine in free mode @@ -4430,7 +4525,7 @@ Example: >>> tux.tts.speak_free('My name is tux! tux droid !') """ - t=threading.Thread(target=self.speak,args=(text,)) + t=threading.Thread(target=self.__speak, args=(text,)) t.setName('tts.speak_free') t.start() self.parent.daemon.free_thread_list.append(t) |