[tuxdroid-svn] r618 - api/python/trunk
Status: Beta
Brought to you by:
ks156
From: remi <c2m...@c2...> - 2007-10-16 15:16:13
|
Author: remi Date: 2007-10-16 16:57:07 +0200 (Tue, 16 Oct 2007) New Revision: 618 Modified: api/python/trunk/tuxapi_class.py api/python/trunk/tuxapi_const.py Log: ADD: Wav system, monitoring UP: Documentation Modified: api/python/trunk/tuxapi_class.py =================================================================== --- api/python/trunk/tuxapi_class.py 2007-10-16 13:00:24 UTC (rev 617) +++ api/python/trunk/tuxapi_class.py 2007-10-16 14:57:07 UTC (rev 618) @@ -31,6 +31,7 @@ import string import signal from tuxapi_const import * +from copy import deepcopy #============================================================================== # Constants @@ -48,16 +49,18 @@ Sub class of this class: "cmd" as class : Class which manages the tux commands + "connect" as class : Class which manages connection functions "daemon" as class : Class which manages the daemon commands "event" as class : Class which manages the events "hw" as class : Class which manages the tux hardware "misc" as class : Class which manages the miscellaneous functions + "monitoring" as class : Class which manages the monitoring "status" as class : Class which manages the request of a status - "connect" as class : Class which manages connection functions "sys" as class : Class which manages the system functions "tts" as class : Class which manages the text to speech + "wav" as class : Class which manages the wav functions Global variables of this class: "my_name" as string : Name of the api instance @@ -107,6 +110,7 @@ self.tts=TUXtts(self) self.misc=TUXmisc(self) self.monitoring = TUXmonitoring(self) + self.wav = TUXwav(self) self.connected=False #deprecated t=threading.Thread(target=self.daemon._loop_auto_connect) t.setName('daemon._loop_auto_connect') @@ -989,6 +993,34 @@ # TUXTCPCommunicator - monitoring - class #============================================================================== class TUXmonitoring(object): + """ + Class which manages the monitoring + + Status constants list: + (STATUS_WINGS_MOTOR_BACKWARD, STATUS_SPIN_MOTOR_BACKWARD, + STATUS_SPIN_MOTOR_FORWARD, STATUS_MOUTH_OPEN_POSITION, + STATUS_MOUTH_CLOSED_POSITION, STATUS_HEAD_PUSH_POSITION, + STATUS_CHARGER_INHIBIT_SIGNAL, STATUS_WINGS_POSITION_SWITCH, + STATUS_MOTOR_FOR_WINGS, STATUS_LEFT_BLUE_LED, + STATUS_I2C_SDA_LINE, STATUS_I2C_SCL_LINE , + STATUS_HEAD_MOTOR_FOR_MOUTH, STATUS_HEAD_MOTOR_FOR_EYES, + STATUS_IR_RECEIVER_SIGNAL, STATUS_SPIN_POSITION_SWITCH, + STATUS_WINGS_MOTOR_FORWARD, STATUS_IR_LED, + STATUS_EYES_OPEN_POSITION_SWITCH, STATUS_EYES_CLOSED_POSITION_SWITCH, + STATUS_LEFT_WING_PUSH, STATUS_RIGHT_WING_PUSH, + STATUS_POWER_PLUG_SWITCH, STATUS_HEAD_PUSH_SWITCH, + STATUS_CHARGER_LED, STATUS_MUTE_STATUS, + STATUS_LIGHT_LEVEL, STATUS_EYES_POSITION_COUNTER, + STATUS_MOUTH_POSITION_COUNTER, STATUS_WINGS_POSITION_COUNTER, + STATUS_SPIN_POSITION_COUNTER, STATUS_RIGHT_BLUE_LED, + STATUS_RF_CONNECTED, STATUS_IR_CODE, + STATUS_SOUND_COUNT, STATUS_PONG + ) + + Functions list: + tux.monitoring.insert + tux.monitoring.remove + """ def __init__(self, parent): self.parent = parent @@ -996,14 +1028,38 @@ self._event_list = [] def insert(self, status, function): + """ + Insert a monitoring event. + + Parameters: + "status" as integer : Status index + (See status contants list) + "function" as pointer of function : Function to bind + + Returns: + The index of your event in the monitoring manager. + You must save this index if you want removing your event. + + Exemple: + >>> monitor_idx = tux.monitoring.insert(STATUS_LIGHT_LEVEL, my_function) + """ self._event_mutex.acquire() self._event_list.append([status, function]) self._event_mutex.release() return len(self._event_list) - 1 def remove(self, event_id): + """ + Remove a monitoring event. + + Parameters: + "event_id" as integer : Index of the event. + + Exemple: + >>> tux.monitoring.remove(monitor_idx) + """ self._event_mutex.acquire() - self._event_list.pop(event_id) + self._event_list[event_id][1] = None self._event_mutex.release() def check_events(self, frame): @@ -1018,13 +1074,14 @@ self.remove(idx) for i, event in enumerate(events): - if event[0] == ord(frame[4]): - frame = frame[5:] - ord_frame = [] - for val in frame: - ord_frame.append(ord(val)) - args = tuple(ord_frame) - thread.start_new_thread(__load_funct_async, (i, event[1], args)) + if event[1] != None: + if event[0] == ord(frame[4]): + frame = frame[5:] + ord_frame = [] + for val in frame: + ord_frame.append(ord(val)) + args = tuple(ord_frame) + thread.start_new_thread(__load_funct_async, (i, event[1], args)) #============================================================================== @@ -2852,7 +2909,7 @@ Example: >>>var = tux.status.charger_state() """ - return self.get_one_status(DATAS_STATUS_CHARGER_INHIBIT_SIGNAL) + return self.get_one_status(DATAS_STATUS_CHARGER_LED_STATUS) #-------------------------------------------------------------------------- # Get the last state of wings position switch status @@ -4099,6 +4156,8 @@ self.on_connected = None self.on_disconnected = None self.on_voice_list = None + self.on_wav_raw = None + self.__last_wav_raw = [0] * 1024; self.sound_on=False self.my_pitch=100 self.my_voice=SPK_US_MALE @@ -4128,12 +4187,22 @@ 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: + if curr_speaking_conf[2] == 'speak_free': + self.my_pitch = curr_speaking_conf[1][1] + self.my_voice = curr_speaking_conf[1][0] self.__speak_free(curr_speaking_conf[0]) - else: + elif curr_speaking_conf[2] == 'speak': + self.my_pitch = curr_speaking_conf[1][1] + self.my_voice = curr_speaking_conf[1][0] self.__speak(curr_speaking_conf[0]) + elif curr_speaking_conf[2] == 'wav_free': + self.parent.wav._set_begin_end( curr_speaking_conf[1][0], + curr_speaking_conf[1][1]) + self.__wav_free(curr_speaking_conf[0]) + elif curr_speaking_conf[2] == 'wav': + self.parent.wav._set_begin_end( curr_speaking_conf[1][0], + curr_speaking_conf[1][1]) + self.__wav(curr_speaking_conf[0]) curr_speaking_conf[3].acquire() curr_speaking_conf[3].notify() curr_speaking_conf[3].release() @@ -4146,6 +4215,15 @@ self.speaking_stack_mutex.release() def speak(self, text): + """ + Speak a text with the acapela text to speech engine + + Parameters: + "text" as string : text to read + + Example: + >>> tux.tts.speak('My name is tux! tux droid !') + """ if not self.connected: return speaking_conf = [] @@ -4154,7 +4232,7 @@ voice_conf.append(self.my_voice) voice_conf.append(self.my_pitch) speaking_conf.append(voice_conf) - speaking_conf.append(False) + speaking_conf.append('speak') my_lock = threading.Condition(threading.Lock()) speaking_conf.append(my_lock) self.speaking_stack_add(speaking_conf) @@ -4163,6 +4241,15 @@ my_lock.release() def speak_free(self, text): + """ + Speak a text with the acapela text to speech engine in free mode + + Parameters: + "text" as string : text to read + + Example: + >>> tux.tts.speak_free('My name is tux! tux droid !') + """ if not self.connected: return speaking_conf = [] @@ -4171,13 +4258,51 @@ voice_conf.append(self.my_voice) voice_conf.append(self.my_pitch) speaking_conf.append(voice_conf) - speaking_conf.append(True) + speaking_conf.append('speak_free') 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 _wav(self, wav_path, begin, end): + if not os.path.isfile(wav_path): + return + if not self.connected: + return + speaking_conf = [] + speaking_conf.append(wav_path) + voice_conf = [] + voice_conf.append(begin) + voice_conf.append(end) + speaking_conf.append(voice_conf) + speaking_conf.append('wav') + 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 _wav_free(self, wav_path, begin, end): + if not os.path.isfile(wav_path): + return + if not self.connected: + return + speaking_conf = [] + speaking_conf.append(wav_path) + voice_conf = [] + voice_conf.append(begin) + voice_conf.append(end) + speaking_conf.append(voice_conf) + speaking_conf.append('wav_free') + 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 @@ -4339,7 +4464,7 @@ """ while self.connected: try: - tcp_data=self.sock.recv(32) + tcp_data=self.sock.recv(256) except socket.timeout: time.sleep(0.01) continue @@ -4348,7 +4473,7 @@ self.connected=False time.sleep(0.01) continue - if len(tcp_data) < 32: + if len(tcp_data) < 256: time.sleep(0.01) continue if self.print_status: @@ -4357,7 +4482,7 @@ self.tcp_mutex.acquire() self.tcp_data_list.append(tcp_data) self.tcp_mutex.release() - time.sleep(0.01) + time.sleep(0.002) #-------------------------------------------------------------------------- # SYSTEM function @@ -4373,11 +4498,11 @@ data = self.tcp_data_list.pop(0) else: self.tcp_mutex.release() - time.sleep(0.003) + time.sleep(0.002) continue self.tcp_mutex.release() self._dispatch_data_main(data) - time.sleep(0.003) + time.sleep(0.002) #-------------------------------------------------------------------------- # Dispatch data from tcp server @@ -4416,6 +4541,20 @@ # A voice has been loaded if ord(data[1])==CMD_INFO_VOICE_OK: self.voice_loaded = True + # WAV INFO + if ord(data[0]) == WAV_INFO: + idx = ord(data[1]) + if idx < 4: + spectre_idx = idx * 254 + for i in range(254): + self.__last_wav_raw[spectre_idx + i] = ord(data[i + 2]) + else: + spectre_idx = idx * 254 + for i in range(8): + self.__last_wav_raw[spectre_idx + i] = ord(data[i + 2]) + if self.on_wav_raw != None: + tmp_raw = deepcopy(self.__last_wav_raw) + thread.start_new_thread(self.on_wav_raw, (tmp_raw,)) #-------------------------------------------------------------------------- # Send command to tuxttsd @@ -4631,25 +4770,75 @@ self.parent.cmd.audio_channel_general() self.tts_mutex.release() return True - + #-------------------------------------------------------------------------- - # Speak a text with the acapela text to speech engine in free mode + # Play a wav with tuxttsd #-------------------------------------------------------------------------- - def __speak_free(self,text): + def __wav(self, wav_path): """ - Speak a text with the acapela text to speech engine in free mode + Speak a text with the acapela text to speech engine Parameters: "text" as string : text to read Example: - >>> tux.tts.speak_free('My name is tux! tux droid !') + >>> tux.tts.speak('My name is tux! tux droid !') """ + self.tts_mutex.acquire() + if not self.connected: + if self.parent.print_warnings: + print "WARNING : Resource text to speech Acapela not found" + self.tts_mutex.release() + return False + if self.sound_on == True: + self.stop() + u = unicode(wav_path, "utf-8") + text_to_send = u.encode('latin-1','replace') + text_length = len(text_to_send) + self.send_command_to_tts(CMD_TYPE_WAV, CMD_WAV_INSERT_PLAY, \ + (text_length & 0x0000FF00) >> 8, (text_length & 0x000000FF), \ + 0, 0) + self._sock_send_frame(text_to_send) + 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 "WAV play : 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 + + #-------------------------------------------------------------------------- + # Speak a text with the acapela text to speech engine in free mode + #-------------------------------------------------------------------------- + def __speak_free(self,text): t=threading.Thread(target=self.__speak, args=(text,)) t.setName('tts.speak_free') t.start() self.parent.daemon.free_thread_list.append(t) return True + + #-------------------------------------------------------------------------- + # Play a wav with tuxttsd in free mode + #-------------------------------------------------------------------------- + def __wav_free(self, wav_path): + t=threading.Thread(target=self.__wav, args=(wav_path,)) + t.setName('tts.wav_free') + t.start() + self.parent.daemon.free_thread_list.append(t) + return True #-------------------------------------------------------------------------- # Play the sound if it's in "pause" state @@ -4745,7 +4934,138 @@ >>> tux.tts.kill_daemon() """ self.send_command_to_tts(CMD_TYPE_DAEMON,CMD_DAEMON_KILL,0,0,0,0) + +#============================================================================== +# TUXTCPCommunicator - wav - class +#============================================================================== +class TUXwav(object): + """ + Class which manages the wav functions. + Functions list for the users: + tux.wav.play + tux.wav.play_free + tux.wav.pause + tux.wav.stop + tux.wav._continue + tux.wav.get_duration + """ + + #-------------------------------------------------------------------------- + # Constructor of class + #-------------------------------------------------------------------------- + def __init__(self,parent): + self.parent = parent + self.__wav_path = "" + self.__wav_length = 0 + + def __load(self, wav_path): + if os.path.isfile(wav_path): + try: + size = os.stat(wav_path)[6] - 44 + self.__wav_length = (float)(size) / 8000 + self.__wav_path = wav_path + except: + return False + return True + else: + return False + + def _set_begin_end(self, begin = 0., end = 0.): + begin_100m = (int)(round(begin * 10)) + end_100m = (int)(round(end * 10)) + begin_lower = begin_100m & 0x000000FF + begin_upper = (begin_100m & 0x0000FF00) >> 8 + end_lower = end_100m & 0x000000FF + end_upper = (end_100m & 0x0000FF00) >> 8 + self.parent.tts.send_command_to_tts( + CMD_TYPE_WAV, + CMD_WAV_BEGIN_END, + begin_lower, + begin_upper, + end_lower, + end_upper) + + def get_duration(self, wav_path): + """ + Get the duration of a wave file. + + Parameters: + "wav_path" as string : Path of the wave file + + Returns: + The time duration in seconds as float. + + Exemple: + >>> print tux.wav.get_duration('/home/tux/test.wav') + """ + if self.__load(wav_path): + self.__wav_path = "" + return self.__wav_length + else: + return 0. + + def play(self, wav_path, begin = 0., end = 0.): + """ + Play a wave file with tuxttsd daemon. + + Parameters: + "wav_path" as string : Path of the wave file + "begin" as float : Starting index in seconds(Optional) + "end" as float : Ending index in seconds(Optional) + + Exemple: + >>> tux.wav.play('/home/tux/test.wav') + >>> tux.wav.play('/home/tux/test.wav', 0., 5.5) + """ + if self.__load(wav_path): + self.parent.tts._wav(self.__wav_path, begin, end) + + def play_free(self, wav_path, begin = 0., end = 0.): + """ + Play a wave file with tuxttsd daemon in free mode. + + Parameters: + "wav_path" as string : Path of the wave file + "begin" as float : Starting index in seconds(Optional) + "end" as float : Ending index in seconds(Optional) + + Exemple: + >>> tux.wav.play_free('/home/tux/test.wav') + >>> tux.wav.play_free('/home/tux/test.wav', 0., 5.5) + """ + if self.__load(wav_path): + self.parent.tts._wav_free(self.__wav_path, begin, end) + + def stop(self): + """ + Stop the current played wave file. + + Exemple: + >>> tux.wav.stop() + """ + self.parent.tts.stop() + + def pause(self): + """ + Pause the current played wave file. + + Exemple: + >>> tux.wav.pause() + """ + self.parent.tts.pause() + + def _continue(self): + """ + Continue the playing of a paused wave file. + + Exemple: + >>> tux.wav._continue() + """ + self.parent.tts.play() + + + #============================================================================== # TUXTCPCommunicator - misc - class #============================================================================== @@ -4807,7 +5127,7 @@ c_header='' my_doc='' for i in range(80-len(indent)): c_header=c_header+'-' - my_doc='%s%s) Class : %s (%s)<br>'%(my_doc,class_num, \ + my_doc='%s%s) Object : %s (%s)<br>'%(my_doc,class_num, \ class_name,str(type(class_obj))[8:-2]) self.header_doc=self.header_doc+indent+'<a href="#%s">'%(class_num) \ +my_doc+'</a>' @@ -4855,7 +5175,7 @@ c_header='' my_doc='' for i in range(80-len(indent)): c_header=c_header+'-' - my_doc='%s%s)\tFunction : %s<br>'%(my_doc,funct_num,funct_name) + my_doc='%s%s)\tMethode : %s<br>'%(my_doc,funct_num,funct_name) self.header_doc=self.header_doc+indent+'<a href="#%s">'%(funct_num) \ +my_doc+'</a>' my_doc=indent+'<a name=%s></a>'%(funct_num)+self.h_funct_b+ \ Modified: api/python/trunk/tuxapi_const.py =================================================================== --- api/python/trunk/tuxapi_const.py 2007-10-16 13:00:24 UTC (rev 617) +++ api/python/trunk/tuxapi_const.py 2007-10-16 14:57:07 UTC (rev 618) @@ -158,6 +158,43 @@ DATAS_STATUS_PONG = 0x24 DATAS_STATUS_BATTERY = 0x25 +STATUS_WINGS_MOTOR_BACKWARD = 0x01 +STATUS_SPIN_MOTOR_BACKWARD = 0x02 +STATUS_SPIN_MOTOR_FORWARD = 0x03 +STATUS_MOUTH_OPEN_POSITION = 0x04 +STATUS_MOUTH_CLOSED_POSITION = 0x05 +STATUS_HEAD_PUSH_POSITION = 0x06 +STATUS_CHARGER_INHIBIT_SIGNAL = 0x07 +STATUS_WINGS_POSITION_SWITCH = 0x08 +STATUS_MOTOR_FOR_WINGS = 0x09 +STATUS_LEFT_BLUE_LED = 0x0A +STATUS_I2C_SDA_LINE = 0x0B +STATUS_I2C_SCL_LINE = 0x0C +STATUS_HEAD_MOTOR_FOR_MOUTH = 0x0D +STATUS_HEAD_MOTOR_FOR_EYES = 0x0E +STATUS_IR_RECEIVER_SIGNAL = 0x0F +STATUS_SPIN_POSITION_SWITCH = 0x10 +STATUS_WINGS_MOTOR_FORWARD = 0x11 +STATUS_IR_LED = 0x12 +STATUS_EYES_OPEN_POSITION_SWITCH = 0x13 +STATUS_EYES_CLOSED_POSITION_SWITCH = 0x14 +STATUS_LEFT_WING_PUSH = 0x15 +STATUS_RIGHT_WING_PUSH = 0x16 +STATUS_POWER_PLUG_SWITCH = 0x17 +STATUS_HEAD_PUSH_SWITCH = 0x18 +STATUS_CHARGER_LED = 0x19 +STATUS_MUTE_STATUS = 0x1A +STATUS_LIGHT_LEVEL = 0x1B +STATUS_EYES_POSITION_COUNTER = 0x1C +STATUS_MOUTH_POSITION_COUNTER = 0x1D +STATUS_WINGS_POSITION_COUNTER = 0x1E +STATUS_SPIN_POSITION_COUNTER = 0x1F +STATUS_RIGHT_BLUE_LED = 0x20 +STATUS_RF_CONNECTED = 0x21 +STATUS_IR_CODE = 0x22 +STATUS_SOUND_COUNT = 0x23 +STATUS_PONG = 0x24 + # Tux connection commands TUX_CONNECTION_DISCONNECT = 1 TUX_CONNECTION_CONNECT = 2 @@ -276,9 +313,13 @@ CMD_TYPE_TTS = 0x02 CMD_TYPE_DAEMON = 0x03 CMD_TYPE_INFO = 0x04 +CMD_TYPE_WAV = 0x05 # Sound conf commands CMD_SOUNDCONF_REINIT = 0X01 CMD_SOUNDCONF_STOP = 0X02 +# WAV commands +CMD_WAV_INSERT_PLAY = 0x01 +CMD_WAV_BEGIN_END = 0x02 # TTS commands CMD_TTS_CHOOSE_VOICE = 0x01 CMD_TTS_INSERT_PLAY_SPEECH = 0x02 @@ -370,6 +411,7 @@ RET_ACK = 0x01 TTS_INFO = 0x02 DAEMON_INFO = 0x03 +WAV_INFO = 0x04 # ACK return ACK_OK = 0x01 ACK_UNKNOW_CMD_TYPE = 0x02 |