[tuxdroid-svn] r643 - api/python/trunk
Status: Beta
Brought to you by:
ks156
From: remi <c2m...@c2...> - 2007-10-26 10:05:07
|
Author: remi Date: 2007-10-26 12:05:00 +0200 (Fri, 26 Oct 2007) New Revision: 643 Modified: api/python/trunk/tuxapi_class.py api/python/trunk/tuxapi_const.py Log: ADD: Micro class, EventControl class UP: Documentation, status on tuxapi_const Modified: api/python/trunk/tuxapi_class.py =================================================================== --- api/python/trunk/tuxapi_class.py 2007-10-24 11:26:09 UTC (rev 642) +++ api/python/trunk/tuxapi_class.py 2007-10-26 10:05:00 UTC (rev 643) @@ -30,6 +30,8 @@ import threading import string import signal +import subprocess +import math from tuxapi_const import * from copy import deepcopy @@ -41,6 +43,77 @@ TCPIP_FRAME_LENGTH = 16 #============================================================================== +# EventControl - class +#============================================================================== +class EventControl(object): + + def __init__(self): + self.__funct_ptr_list = [] + self.__fifo_list = [] + self.__list_mutex = threading.Lock() + self.__threads_list = [] + + def destroy(self): + for my_thread in self.__threads_list: + if my_thread.isAlive(): + my_thread.join() + + def connect(self, funct_ptr): + self.__list_mutex.acquire() + idx = len(self.__funct_ptr_list) + self.__funct_ptr_list.append(funct_ptr) + self.__list_mutex.release() + return idx + + def push(self): + self.__list_mutex.acquire() + self.__fifo_list.append(self.__funct_ptr_list) + self.__list_mutex.release() + self.clear() + + def pop(self): + if len(self.__fifo_list) > 0: + self.__list_mutex.acquire() + self.__funct_ptr_list = self.__fifo_list.pop() + self.__list_mutex.release() + + def clear(self): + self.__list_mutex.acquire() + self.__funct_ptr_list = [] + self.__list_mutex.release() + + def disconnect(self, idx): + self.__list_mutex.acquire() + self.__funct_ptr_list[idx] = None + self.__list_mutex.release() + + def __run(self, funct_ptr, idx, fargs): + try: + funct_ptr(*fargs) + except: + self.__list_mutex.acquire() + self.__funct_ptr_list[idx] == None + self.__list_mutex.release() + + def notify(self, *fargs): + self.__list_mutex.acquire() + if len(self.__funct_ptr_list) == 0: + self.__list_mutex.release() + return + try: + funct_ptr_list = self.__funct_ptr_list + except: + self.__list_mutex.release() + return + self.__list_mutex.release() + for idx, funct_ptr in enumerate(funct_ptr_list): + if funct_ptr != None: + t=threading.Thread(target=self.__run, args=(funct_ptr, idx, fargs)) + t.setName('EventControl') + t.start() + self.__threads_list.append(t) + +#============================================================================== # TUXTCPCommunicator class #============================================================================== class TUXTCPCommunicator(object): @@ -53,6 +126,7 @@ "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 + "micro" as class : Class which manages the microphone functions "misc" as class : Class which manages the miscellaneous functions "monitoring" as class : Class which manages the monitoring @@ -111,6 +185,10 @@ self.misc=TUXmisc(self) self.monitoring = TUXmonitoring(self) self.wav = TUXwav(self) + self.micro = TUXmicro(self) + + self.head_switch = TuxSwitch(self, STATUS_HEAD_PUSH_SWITCH) + self.connected=False #deprecated t=threading.Thread(target=self.daemon._loop_auto_connect) t.setName('daemon._loop_auto_connect') @@ -130,8 +208,10 @@ self.tts.auto_connect(False) self.daemon.disconnect() self.tts.disconnect() + self.tts.destroy() self.daemon._tcp_threads_join() self.tts._tcp_threads_join() + self.micro.destroy() self.exit_flag=True for main_thread in self.main_thread_list: if self.print_debug_thread: @@ -461,6 +541,8 @@ self.event.on_status(data) #on monitoring self.monitoring.check_events(data) + + self.head_switch._notify(ord(data[4]), ord(data[5])) #-------------------------------------------------------------------------- @@ -1014,7 +1096,8 @@ 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 + STATUS_SOUND_COUNT, STATUS_PONG, + STATUS_BATTERY, STATUS_MICRO_ENERGY, ) Functions list: @@ -4154,15 +4237,6 @@ tux.tts.pause tux.tts.play tux.tts.select_voice - tux.tts.select_voice_fr_female - tux.tts.select_voice_fr_female_tuxed - tux.tts.select_voice_fr_male - tux.tts.select_voice_fr_male_tuxed - tux.tts.select_voice_us_female - tux.tts.select_voice_us_female_tuxed - tux.tts.select_voice_us_male - tux.tts.select_voice_us_male_tuxed - tux.tts.send_command_to_tts tux.tts.speak tux.tts.speak_free tux.tts.stop @@ -4186,7 +4260,7 @@ self.on_connected = None self.on_disconnected = None self.on_voice_list = None - self.on_wav_raw = None + self.on_wav_raw = EventControl() self.__last_wav_raw = [0] * 1024; self.sound_on=False self.my_pitch=100 @@ -4199,6 +4273,9 @@ self.speaking_stack = [] self.speaking_stack_mutex = threading.Lock() + def destroy(self): + self.on_wav_raw.destroy() + def speaking_stack_add(self, speaking_conf): self.speaking_stack_mutex.acquire() self.speaking_stack.append(speaking_conf) @@ -4584,7 +4661,7 @@ 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,)) + self.on_wav_raw.notify(tmp_raw) #-------------------------------------------------------------------------- # Send command to tuxttsd @@ -5093,8 +5170,128 @@ >>> tux.wav._continue() """ self.parent.tts.play() + +#============================================================================== +# TUXTCPCommunicator - micro - class +#============================================================================== +class TUXmicro(object): + """ + Class which manages the microphone functions. + + Global variables of this class: + "on_buffer" as EventControl : Event on new buffer from micro + Example of associating a function to 'on_buffer' event: + + >>> def new_buffer(values): + >>> ... print values + >>> ... + >>> tux.micro.on_buffer.connect(new_buffer) + >>> tux.micro.on() + + Functions list for the users: + tux.micro.on + tux.micro.off + """ + def __init__(self,parent): + self.parent = parent + self.__state = False + self.__process = None + self.__process_mutex = threading.Lock() + self.on_buffer = EventControl() + + def destroy(self): + self.off() + self.on_buffer.destroy() + + def on(self): + """ + Function to turn on the micro capture. + + Example: + >>> tux.micro.on() + """ + if self.__state: + return + def get_micro_data(): + device = self.parent.hw.alsa_device + cmd = ["arecord", "-D", device, "-t", "raw"] + self.__process = subprocess.Popen(cmd, stdout = subprocess.PIPE,\ + stderr = subprocess.PIPE) + self.__state = True + while self.__process.poll() == None: + self.__process_mutex.acquire() + buff = self.__process.stdout.read(800) + self.__on_new_buffer(buff) + self.__process_mutex.release() + time.sleep(0.01) + self.__state = False + + thread.start_new_thread(get_micro_data, ()) + + def off(self): + """ + Function to turn off the micro capture. + + Example: + >>> tux.micro.off() + """ + if not self.__state: + return + self.__process_mutex.acquire() + os.kill(self.__process.pid, signal.SIGKILL) + os.waitpid(-1, os.WNOHANG) + self.__process_mutex.release() + + def __on_new_buffer(self, buffer): + i_buffer = [] + for c in buffer: + i_buffer.append(ord(c)) + if self.__state: + self.__send_energy_monitoring(i_buffer) + self.on_buffer.notify(i_buffer) + + def __send_energy_monitoring(self, buffer): + def log_value(value): + return int(math.log(value) / math.log(255) * 255) + + try: + e_total = 0 + for val in buffer: + e_total += abs(val - 127) + e_total /= 200 + if e_total > 255: + e_total = 255 + e_total = log_value(e_total) + + e_table = [] + for i in range(4): + e_m = 0 + i_b = i * 200 + i_e = i_b + 200 + for j in range(i_b, i_e): + e_m += abs(buffer[j] - 127) + e_m /= 50 + if e_m > 255: + e_m = 255 + e_m = log_value(e_m) + e_table.append(e_m) + except: + return + + tmp_tcp_data = [chr(0)] * 16 + tmp_tcp_data[0] = chr(SOURCE_TUX) + tmp_tcp_data[1] = chr(0) + tmp_tcp_data[2] = chr(DATA_TP_RSP) + tmp_tcp_data[3] = chr(SUBDATA_TP_STATUS) + tmp_tcp_data[4] = chr(STATUS_MICRO_ENERGY) + tmp_tcp_data[5] = chr(e_total) + tmp_tcp_data[6] = chr(e_table[0]) + tmp_tcp_data[7] = chr(e_table[1]) + tmp_tcp_data[8] = chr(e_table[2]) + tmp_tcp_data[9] = chr(e_table[3]) + self.parent.misc.simulate_tcpip_frame(tmp_tcp_data) #============================================================================== # TUXTCPCommunicator - misc - class @@ -5108,10 +5305,9 @@ tux.misc.build_documentation tux.misc.print_api_version tux.misc.simulate_remote_key + tux.misc.simulate_tcpip_frame """ - #-------------------------------------------------------------------------- - # Constructor of class - #-------------------------------------------------------------------------- + def __init__(self,parent): """ Constructor of this class @@ -5125,9 +5321,6 @@ self.h_funct_b='<b><u><i><font size="2">' self.h_funct_e='</font></i></u></b>' - #-------------------------------------------------------------------------- - # Print the docstring of a element of tux api - #-------------------------------------------------------------------------- def doc(self,element): """ Print the docstring of an element of tux api @@ -5145,9 +5338,6 @@ print element.__doc__ print c_header - #-------------------------------------------------------------------------- - # Not a user function - #-------------------------------------------------------------------------- def parse_class(self,class_num,class_obj,class_name,class_str,indent): """ Not a user function @@ -5194,9 +5384,6 @@ getattr(class_obj,line).__doc__,indent+' ') return my_doc - #-------------------------------------------------------------------------- - # Not a user function - #-------------------------------------------------------------------------- def parse_function(self,funct_num,funct_name,funct_str,indent): """ Not a user function @@ -5214,9 +5401,6 @@ my_doc=my_doc+indent+line[4:]+'<br>' return my_doc - #-------------------------------------------------------------------------- - # Build the documentation of this api - #-------------------------------------------------------------------------- def build_documentation(self,doc_path): """ Build the documentation of this api @@ -5252,9 +5436,6 @@ f.write(documentation) f.close() - #-------------------------------------------------------------------------- - # To print the version of the API - #-------------------------------------------------------------------------- def print_api_version(self): """ To print the version of the API @@ -5265,12 +5446,28 @@ print "---------------------------------------------------------------" print "TUXDROID PYTHON API %s"%(api_version) print "---------------------------------------------------------------" + + def simulate_tcpip_frame(self, frame): + """ + To simulate the receiving of a frame - #-------------------------------------------------------------------------- - # To simulate the receiving of a remote key - #-------------------------------------------------------------------------- - def simulate_remote_key(self,key): + Parameters: + "frame" as list of 16 char : fake frame + + Example: + >>> tux.misc.simulate_tcpip_frame(<list of 16 chars>) """ + self.parent.tcp_data_fifo_lock_mutex.acquire() + self.parent.tcp_data_fifo_lock.append(frame) + self.parent.tcp_data_fifo_lock_mutex.release() + self.parent.tcp_data_fifo_event_mutex.acquire() + self.parent.tcp_data_fifo_event.append(frame) + self.parent.tcp_data_fifo_event_mutex.release() + if not self.parent.daemon.connected: + self.parent._dispatch_data_main(frame) + + def simulate_remote_key(self, key): + """ To simulate the receiving of a remote key Parameters: @@ -5279,14 +5476,48 @@ Example: >>> tux.misc.simulate_remote_key(K_OK) """ - tmp_tcp_data = (chr(SOURCE_TUX),chr(0),chr(DATA_TP_RSP), \ - chr(SUBDATA_TP_STATUS),chr(DATAS_STATUS_IR_CODE), \ - chr(key),chr(0),chr(0),chr(0),chr(0),chr(0),chr(0), \ - chr(0),chr(0),chr(0),chr(0)) + tmp_tcp_data = [chr(0)] * 16 + tmp_tcp_data[0] = chr(SOURCE_TUX) + tmp_tcp_data[1] = chr(0) + tmp_tcp_data[2] = chr(DATA_TP_RSP) + tmp_tcp_data[3] = chr(SUBDATA_TP_STATUS) + tmp_tcp_data[4] = chr(DATAS_STATUS_IR_CODE) + tmp_tcp_data[5] = chr(key) + self.simulate_tcpip_frame(tmp_tcp_data) + +#============================================================================== +# TUXTCPCommunicator - switch - class +#============================================================================== +class TuxSwitch(object): - self.parent.tcp_data_fifo_lock_mutex.acquire() - self.parent.tcp_data_fifo_lock.append(tmp_tcp_data) - self.parent.tcp_data_fifo_lock_mutex.release() - self.parent.tcp_data_fifo_event_mutex.acquire() - self.parent.tcp_data_fifo_event.append(tmp_tcp_data) - self.parent.tcp_data_fifo_event_mutex.release() + def __init__(self, parent, status): + self.parent = parent + self.__status = status + self.on_press = EventControl() + self.on_release = EventControl() + + def _store_events(self): + self.on_press.push() + self.on_release.push() + + def _restore_events(self): + self.on_press.pop() + self.on_release.pop() + + def _clear_events(self): + self.on_press.clear() + self.on_release.clear() + + def _notify(self, status, value): + if status == self.__status: + if value == 0: + self.on_release.notify() + else: + self.on_press.notify() + + def simulate(self, value): + self._notify(self.__status, value) + + def get_status(self): + return self.parent.status.get_one_status(self.__status) + Modified: api/python/trunk/tuxapi_const.py =================================================================== --- api/python/trunk/tuxapi_const.py 2007-10-24 11:26:09 UTC (rev 642) +++ api/python/trunk/tuxapi_const.py 2007-10-26 10:05:00 UTC (rev 643) @@ -157,6 +157,7 @@ DATAS_STATUS_SOUND_COUNT = 0x23 DATAS_STATUS_PONG = 0x24 DATAS_STATUS_BATTERY = 0x25 +DATAS_STATUS_MICRO_ENERGY = 0xF0 DATAS_STATUS_AUDIO = 0x26 STATUS_WINGS_MOTOR_BACKWARD = 0x01 @@ -195,6 +196,9 @@ STATUS_IR_CODE = 0x22 STATUS_SOUND_COUNT = 0x23 STATUS_PONG = 0x24 +STATUS_BATTERY = 0x25 +STATUS_AUDIO = 0x26 +STATUS_MICRO_ENERGY = 0xF0 # Tux connection commands TUX_CONNECTION_DISCONNECT = 1 |