[tuxdroid-svn] r874 - in software: . tuxosl tuxosl/trunk
Status: Beta
Brought to you by:
ks156
From: remi <c2m...@c2...> - 2008-01-24 10:54:20
|
Author: remi Date: 2008-01-24 11:54:19 +0100 (Thu, 24 Jan 2008) New Revision: 874 Added: software/tuxosl/ software/tuxosl/branches/ software/tuxosl/tags/ software/tuxosl/trunk/ software/tuxosl/trunk/_TUX_OSL.so software/tuxosl/trunk/service_daemonizer.py software/tuxosl/trunk/tux_osl_api.py software/tuxosl/trunk/tux_osl_const.py software/tuxosl/trunk/tux_osl_daemon.py software/tuxosl/trunk/tux_osl_event_cmd_client.py software/tuxosl/trunk/tux_osl_event_cmd_server.py software/tuxosl/trunk/tux_osl_event_controler.py software/tuxosl/trunk/tux_osl_obj.py software/tuxosl/trunk/tux_osl_service_server.py software/tuxosl/trunk/tux_osl_wrapper.py Log: ADD Added: software/tuxosl/trunk/_TUX_OSL.so =================================================================== (Binary files differ) Property changes on: software/tuxosl/trunk/_TUX_OSL.so ___________________________________________________________________ Name: svn:executable + * Name: svn:mime-type + application/octet-stream Added: software/tuxosl/trunk/service_daemonizer.py =================================================================== --- software/tuxosl/trunk/service_daemonizer.py (rev 0) +++ software/tuxosl/trunk/service_daemonizer.py 2008-01-24 10:54:19 UTC (rev 874) @@ -0,0 +1,123 @@ +import os +import sys +import errno + +class PIDFile(object): + """ + Class to deal with the pidfile. + Their original version come from the sysklogd package, under GPL + Copyright (c) 1995 Martin Schulze <Mar...@Li...> + """ + def __init__(self, name, path = "/var/run"): + self.__PIDFILE = "%s/%s.pid" % (path, name) + + def read(self): + pid = 0 + try: + f = open(self.__PIDFILE, "r") + try: + pid = int(f.readline()) + finally: + f.close() + except: + pass + return pid + + def write(self): + pid = os.getpid() + result = False + try: + f = open(self.__PIDFILE, "w") + try: + f.write("%d\n" % pid) + finally: + f.close() + result = True + except: + print 'can not write file' + return result + + def check(self): + pid = os.getpid() + old_pid = self.read() + if (old_pid == pid) or (old_pid == 0): # pid is different + return False + try: + os.kill(old_pid, 0) + except OSError, why: + if why[0] == errno.ESRCH: + return False + return True + + def remove(self): + try: + os.remove(self.__PIDFILE) + except: + pass + +class ServiceDaemonizer(object): + + def __init__(self, name, log_path, service_funct, redirect_io = True): + log_filename = '%s/%s.log' % (log_path, name) + self.daemonize(redirect_io, '/dev/null', log_filename, log_filename) + self.__pidfile = PIDFile(name, '/tmp') + self.__service_funct = service_funct + + def start(self): + result = True + if not self.__pidfile.check(): + if not self.__pidfile.write(): + result = False + else: + result = False + if result: + self.__service_funct() + return result + + def destroy(self): + pass + #self.__pidfile.remove() + + def daemonize(self, redirect_io, stdin, stdout, stderr): + """ + References: + UNIX Programming FAQ + 1.7 How do I get my program to act like a daemon? + http://www.erlenstar.demon.co.uk/unix/faq_2.html#SEC16 + + Advanced Programming in the Unix Environment + W. Richard Stevens, 1992, Addison-Wesley, ISBN 0-201-56317-7. + """ + # Do first fork. + try: + pid = os.fork() + if pid > 0: + sys.exit(0) # Exit first parent. + except OSError, e: + sys.stderr.write ("fork #1 failed: (%d) %s\n" % (e.errno, e.strerror) ) + sys.exit(1) + + # Decouple from parent environment. + os.chdir("/") + os.umask(0) + os.setsid() + + # Do second fork. + try: + pid = os.fork() + if pid > 0: + sys.exit(0) # Exit second parent. + except OSError, e: + sys.stderr.write ("fork #2 failed: (%d) %s\n" % (e.errno, e.strerror) ) + sys.exit(1) + + # Now I am a daemon! + + # Redirect standard file descriptors. + if redirect_io: + si = file(stdin, 'r') + so = file(stdout, 'w') + se = file(stderr, 'w', 0) + os.dup2(si.fileno(), sys.stdin.fileno()) + os.dup2(so.fileno(), sys.stdout.fileno()) + os.dup2(se.fileno(), sys.stderr.fileno()) Added: software/tuxosl/trunk/tux_osl_api.py =================================================================== --- software/tuxosl/trunk/tux_osl_api.py (rev 0) +++ software/tuxosl/trunk/tux_osl_api.py 2008-01-24 10:54:19 UTC (rev 874) @@ -0,0 +1,254 @@ +#!/usr/bin/python +# -*- coding: latin1 -*- +# ----------------------------------------------------------------------------- +# Tux Droid - OSL - Bin to old API +# Copyright (C) 2007 C2ME Sa <rem...@c2...> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. +# ----------------------------------------------------------------------------- +# $Id: $ +# ----------------------------------------------------------------------------- +import os +import sys +import threading +import time +from tux_osl_obj import TuxOSLObjDistant, TuxOSLObjDirect +from tux_osl_const import * + +class TuxOSLVClass(object): + + def __getattribute__(self, name): + if name == 'authorized_voices_list': + return self._get_authorized_voices_list() + elif name == 'connected': + return self._get_connected() + return object.__getattribute__(self, name) + + def __setattr__(self, name, value): + if name == 'on_sound_on': + if value != None: + self._sound_on_event.connect(value, threaded = False, idx = 2) + elif name == 'on_sound_off': + if value != None: + self._sound_off_event.connect(value, threaded = True, idx = 2) + elif name == 'on_connected': + if value != None: + self._connected_event.connect(value, threaded = False, idx = 2) + elif name == 'on_disconnected': + if value != None: + self._disconnected_event.connect(value, threaded = False, idx = 2) + elif name == 'on_voice_list': + if value != None: + self._voice_list_event.connect(value, threaded = False, idx = 1) + object.__setattr__(self, name, value) + +class TuxOSLAPI(object): + + def __init__(self, parent = None): + self.__osl_obj = TuxOSLObjDistant() + self.__osl_obj.on_sound_on.connect(self._on_general_sound_on, threaded = False) + self.__osl_obj.on_sound_off.connect(self._on_general_sound_off, threaded = False) + self.__osl_obj.on_connected.connect(self._on_general_connected, threaded = False) + self.__osl_obj.on_disconnected.connect(self._on_general_disconnected, threaded = False) + self.__parent = parent + self.__tts_mutex = threading.Lock() + self.__wav_mutex = threading.Lock() + self.tts = TuxOSLVClass() + self.wav = TuxOSLVClass() + self.__decorate_tts_sub_object() + self.__decorate_wav_sub_object() + + def destroy(self): + self.__osl_obj.destroy() + + def connect(self, host = 'localhost', port = 5510): + self.__osl_obj.connect(host) + + def auto_connect(self, value, host = 'localhost', port = 5510): + self.__osl_obj.auto_connect(value, host) + + def disconnect(self): + self.__osl_obj.disconnect() + + def kill_daemon(self): + self.__osl_obj.kill() + + def _get_version(self): + return self.__osl_obj.get_version() + + def __decorate_tts_sub_object(self): + self.tts.print_status = False + self.tts.on_sound_on = None + self.tts._sound_on_event = self.__osl_obj.on_sound_on + self.tts.on_sound_off = None + self.tts._sound_off_event = self.__osl_obj.on_sound_off + self.tts.on_connected = None + self.tts._connected_event = self.__osl_obj.on_connected + self.tts.on_disconnected = None + self.tts._disconnected_event = self.__osl_obj.on_disconnected + self.tts.on_voice_list = None + self.tts._voice_list_event = self.__osl_obj.tts.on_voice_list_changed + self.tts.sound_on = False + self.tts.connected = False + self.tts.authorized_voices_list = [] + self.tts._get_authorized_voices_list = self._tts_get_authorized_voices_list + self.tts._get_connected = self._get_connected + self.tts._locutor = SPK_US_MALE_NAME + self.tts._pitch = 100 + self.tts.speak = self._tts_speak + self.tts.speak_free = self._tts_speak_free + self.tts.pause = self._tts_pause + self.tts.play = self._tts_play + self.tts.stop = self._tts_stop + self.tts.select_voice = self._tts_select_voice + self.tts.connect = self.connect + self.tts.auto_connect = self.auto_connect + self.tts.disconnect = self.disconnect + self.tts.destroy = self.destroy + self.tts.kill_daemon = self.kill_daemon + self.tts.get_version = self._get_version + + def __decorate_wav_sub_object(self): + self.wav.play = self._wav_play + self.wav.play_free = self._wav_play_free + self.wav.pause = self._wav_pause + self.wav._continue = self._wav__continue + self.wav.stop = self._wav_stop + self.wav.get_duration = self._wav_get_duration + self.wav.destroy = self.empty_funct + + def _on_general_sound_on(self, *args): + self.tts.sound_on = True + if self.__parent != None: + self.__parent.cmd.audio_channel_tts() + + def _on_general_sound_off(self, *args): + self.tts.sound_on = False + if self.__parent != None: + self.__parent.cmd.audio_channel_general() + + def _on_general_connected(self, *args): + print "CONNECTED to tux_osl_daemon" + + def _on_general_disconnected(self, *args): + print "DISCONNECTED from tux_osl_daemon" + + def empty_funct(self): + pass + + def _tts_speak(self, text): + self.__tts_mutex.acquire() + result = True + channel = self.__osl_obj.tts.speak(text, self.tts._locutor, self.tts._pitch) + if channel != -1: + self.__osl_obj.current_tts_channel = channel + else: + result = False + self.__tts_mutex.release() + if result: + if self.__osl_obj.tts.get_sound_state() == 1: + self.__osl_obj.tts.on_speak_stop.wait_condition(()) + return result + + def _tts_speak_free(self, text): + self.__tts_mutex.acquire() + result = True + channel = self.__osl_obj.tts.speak(text, self.tts._locutor, self.tts._pitch) + if channel != -1: + self.__osl_obj.current_tts_channel = channel + else: + result = False + self.__tts_mutex.release() + return result + + def __tts_speak_free(self, text): + t = threading.Thread(target = self.__tts_speak_free, args = (text,)) + t.start() + + def _tts_pause(self): + return self.__osl_obj.tts.set_pause(True) + + def _tts_play(self): + return self.__osl_obj.tts.set_pause(False) + + def _tts_stop(self): + return self.__osl_obj.tts.set_stop() + + def _tts_select_voice(self, locutor, pitch): + self.tts._pitch = pitch + if str(type(locutor)) != "<type 'str'>": + locutor = SPK_NAME_LIST[locutor] + if locutor not in SPK_NAME_LIST: + return False + self.tts._locutor = locutor + return True + + def _tts_get_authorized_voices_list(self): + avl = self.__osl_obj.tts.get_authorized_voices_list() + result = [] + for v in avl: + for i, name in enumerate(SPK_NAME_LIST): + if name == v: + result.append(i - 1) + return result + + def _wav_play(self, wav_path, begin = 0.0, end = 9999999.0): + self.__wav_mutex.acquire() + result = True + channel = self.__osl_obj.wav.play(wav_path, begin, end) + if channel != -1: + self.__osl_obj.current_wav_channel = channel + else: + result = False + self.__wav_mutex.release() + if result: + if self.__osl_obj.wav.get_sound_state(channel) == 1: + self.__osl_obj.wav.on_play_stop.wait_condition(()) + return result + + def _wav_play_free(self, wav_path, begin = 0.0, end = 9999999.0): + self.__wav_mutex.acquire() + result = True + channel = self.__osl_obj.wav.play(wav_path, begin, end) + if channel != -1: + self.__osl_obj.current_wav_channel = channel + else: + result = False + self.__wav_mutex.release() + return result + + def _wav_pause(self): + return self.__osl_obj.wav.set_pause(True) + + def _wav__continue(self): + return self.__osl_obj.wav.set_pause(False) + + def _wav_stop(self): + return self.__osl_obj.wav.set_stop() + + def _wav_get_duration(self, wav_path): + wav_length = 0.0 + if os.path.isfile(wav_path): + try: + size = os.stat(wav_path)[6] - 44 + wav_length = (float)(size) / 8000 + except: + pass + return wav_length + + def _get_connected(self): + return self.__osl_obj.get_connect_state() + Added: software/tuxosl/trunk/tux_osl_const.py =================================================================== --- software/tuxosl/trunk/tux_osl_const.py (rev 0) +++ software/tuxosl/trunk/tux_osl_const.py 2008-01-24 10:54:19 UTC (rev 874) @@ -0,0 +1,83 @@ +#!/usr/bin/python +# -*- coding: latin1 -*- +# ----------------------------------------------------------------------------- +# Tux Droid - OSL - Constants +# Copyright (C) 2007 C2ME Sa <rem...@c2...> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. +# ----------------------------------------------------------------------------- +# $Id: $ +# ----------------------------------------------------------------------------- +SPK_NO_VOICE = 0x00 +SPK_NO_VOICE_NAME = "None8k" +SPK_FR_MALE = 0x01 +SPK_FR_MALE_NAME = "Bruno8k" +SPK_FR_FEMALE = 0x02 +SPK_FR_FEMALE_NAME = "Julie8k" +SPK_US_MALE = 0x03 +SPK_US_MALE_NAME = "Ryan8k" +SPK_US_FEMALE = 0x04 +SPK_US_FEMALE_NAME = "Heather8k" +SPK_B_FEMALE = 0x05 +SPK_B_FEMALE_NAME = "Sofie8k" +SPK_D_MALE = 0x06 +SPK_D_MALE_NAME = "Klaus8k" +SPK_D_FEMALE = 0x07 +SPK_D_FEMALE_NAME = "Sarah8k" +SPK_GB_MALE = 0x08 +SPK_GB_MALE_NAME = "Graham8k" +SPK_GB_FEMALE = 0x09 +SPK_GB_FEMALE_NAME = "Lucy8k" +SPK_AR_FEMALE = 0x0A +SPK_AR_FEMALE_NAME = "Salma8k" +SPK_DK_FEMALE = 0x0B +SPK_DK_FEMALE_NAME = "Mette8k" +SPK_E_FEMALE = 0x0C +SPK_E_FEMALE_NAME = "Maria8k" +SPK_I_FEMALE = 0x0D +SPK_I_FEMALE_NAME = "Chiara8k" +SPK_NL_FEMALE = 0x0E +SPK_NL_FEMALE_NAME = "Femke8k" +SPK_N_FEMALE = 0x0F +SPK_N_FEMALE_NAME = "Kari8k" +SPK_P_FEMALE = 0x10 +SPK_P_FEMALE_NAME = "Celia8k" +SPK_S_MALE = 0x11 +SPK_S_MALE_NAME = "Erik8k" +SPK_S_FEMALE = 0x12 +SPK_S_FEMALE_NAME = "Emma8k" + +SPK_NAME_LIST = [ + SPK_NO_VOICE_NAME, + SPK_FR_MALE_NAME, + SPK_FR_FEMALE_NAME, + SPK_US_MALE_NAME, + SPK_US_FEMALE_NAME, + SPK_B_FEMALE_NAME, + SPK_D_MALE_NAME, + SPK_D_FEMALE_NAME, + SPK_GB_MALE_NAME, + SPK_GB_FEMALE_NAME, + SPK_AR_FEMALE_NAME, + SPK_DK_FEMALE_NAME, + SPK_E_FEMALE_NAME, + SPK_I_FEMALE_NAME, + SPK_NL_FEMALE_NAME, + SPK_N_FEMALE_NAME, + SPK_P_FEMALE_NAME, + SPK_S_MALE_NAME, + SPK_S_FEMALE_NAME +] Added: software/tuxosl/trunk/tux_osl_daemon.py =================================================================== --- software/tuxosl/trunk/tux_osl_daemon.py (rev 0) +++ software/tuxosl/trunk/tux_osl_daemon.py 2008-01-24 10:54:19 UTC (rev 874) @@ -0,0 +1,38 @@ +#!/usr/bin/python +# -*- coding: latin1 -*- +# ----------------------------------------------------------------------------- +# Tux Droid - OSL - Daemon +# Copyright (C) 2007 C2ME Sa <rem...@c2...> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. +# ----------------------------------------------------------------------------- +# $Id: $ +# ----------------------------------------------------------------------------- + +import time +from service_daemonizer import ServiceDaemonizer +from tux_osl_service_server import TuxOSLServiceServer + +def start_service(): + osl_ss = TuxOSLServiceServer() + osl_ss.start() + osl_ss.wait_stop() + osl_ss.destroy() + +if __name__ == "__main__": + daemonizer = ServiceDaemonizer("tuxosld", "/tmp", start_service, True) + daemonizer.start() + daemonizer.destroy() Property changes on: software/tuxosl/trunk/tux_osl_daemon.py ___________________________________________________________________ Name: svn:executable + * Added: software/tuxosl/trunk/tux_osl_event_cmd_client.py =================================================================== --- software/tuxosl/trunk/tux_osl_event_cmd_client.py (rev 0) +++ software/tuxosl/trunk/tux_osl_event_cmd_client.py 2008-01-24 10:54:19 UTC (rev 874) @@ -0,0 +1,194 @@ +#!/usr/bin/python +# -*- coding: latin1 -*- +# ----------------------------------------------------------------------------- +# Tux Droid - OSL - XMLRPC client of osl server +# Copyright (C) 2007 C2ME Sa <rem...@c2...> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. +# ----------------------------------------------------------------------------- +# $Id: $ +# ----------------------------------------------------------------------------- +import xmlrpclib +import time +import sys +import os +import threading + +from tux_osl_const import * +from tux_osl_event_controler import EventsHandler + +EVENT_CLIENT_DEFAULT_PORT = 5510 +CMD_CLIENT_DEFAULT_PORT = 5511 + + +class TuxOSLClientBase(object): + + def __init__(self): + self.__host = 'localhost' + self.__port = '5510' + self.__connected = False + self.__connected_mutex = threading.Lock() + self.__server = None + self.__auto_connect_flag = False + self.__auto_connect_mutex = threading.Lock() + self.__auto_connect_thread = None + self._events_hdl = EventsHandler() + self._events_hdl.insert('all') + self.on_event = self._events_hdl.event['all'] + + def destroy(self): + self.auto_connect(False) + self.disconnect() + self._events_hdl.destroy() + + def server(self): + return self.__server + + def get_connected(self): + self.__connected_mutex.acquire() + result = self.__connected + self.__connected_mutex.release() + return result + + def _set_connected(self, value): + self.__connected_mutex.acquire() + self.__connected = value + self.__connected_mutex.release() + if value: + self.on_event.notify('client', 'connected') + else: + self.on_event.notify('client', 'disconnected') + + def __get_auto_connect_flag(self): + self.__auto_connect_mutex.acquire() + result = self.__auto_connect_flag + self.__auto_connect_mutex.release() + return result + + def __set_auto_connect_flag(self, value): + self.__auto_connect_mutex.acquire() + self.__auto_connect_flag = value + self.__auto_connect_mutex.release() + + def connect(self, host = 'localhost', port = 5510): + if self.get_connected(): + # Error: Already connected + return False + self.__host = host + self.__port = port + proxy = "http://%s:%d" % (self.__host, self.__port) + try: + self.__server = xmlrpclib.Server(proxy) + self.__server.system.listMethods() + except: + # Error: Server not found + return False + self._set_connected(True) + #print 'Connected to [%s] server' % proxy + return True + + def disconnect(self): + if not self.get_connected(): + # Error: Already disconnected + return False + else: + self._events_hdl.clear_conditions() + return True + + def auto_connect(self, active, host = 'localhost', port = 5510): + def ac_async(host, port): + while self.__get_auto_connect_flag(): + if not self.get_connected(): + self.connect(host, port) + time.sleep(1.0) + + if active: # Enabling the auto-connect + # Disabling of the auto-connect + self.auto_connect(False) + # Disconnect the client + if self.get_connected(): + self.disconnect() + # Reconnect + self.__host = host + self.__port = port + self.__set_auto_connect_flag(True) + self.__auto_connect_thread = threading.Thread(target = ac_async, args = (host, port)) + self.__auto_connect_thread.start() + else: # Disabling the auto-connect + if self.__get_auto_connect_flag(): + # Stop the auto-connect loop + self.__set_auto_connect_flag(False) + # Wait + if self.__auto_connect_thread != None: + if self.__auto_connect_thread.isAlive(): + self.__auto_connect_thread.join() + +class TuxOSLEventClient(TuxOSLClientBase): + + def __init__(self, client_name): + TuxOSLClientBase.__init__(self) + self.__client_name = client_name + self.__client_id = -1 + self.__capture_thread = None + + def connect(self, host = 'localhost', port = EVENT_CLIENT_DEFAULT_PORT): + if not TuxOSLClientBase.connect(self, host, port): + return False + self.__client_id = self.server().register_me(self.__client_name) + if self.__client_id == -1: + return False + self.__capture_thread = threading.Thread(target = self.__capture_events) + self.__capture_thread.start() + return True + + def disconnect(self): + if self.get_connected(): + TuxOSLClientBase.disconnect(self) + try: + self.server().unregister_me(self.__client_id) + except: + pass # Server already disconnected + self._set_connected(False) + time.sleep(0.5) + if self.__capture_thread != None: + if self.__capture_thread.isAlive(): + self.__capture_thread._Thread__stop() + + def __capture_events(self): + while self.get_connected(): + try: + events = self.server().get_events(self.__client_id) + except: + self._set_connected(False) + self._events_hdl.clear_conditions() + break + if len(events) > 0: + for event in events: + self.on_event.notify(*event) + else: + time.sleep(0.05) + +class TuxOSLCmdClient(TuxOSLClientBase): + pass + +if __name__ == "__main__": + + def on_event(*args): + print args + + e = TuxOSLEventClient("Test") + e.on_event.connect(on_event) + e.auto_connect(True, 'localhost', EVENT_CLIENT_DEFAULT_PORT) Added: software/tuxosl/trunk/tux_osl_event_cmd_server.py =================================================================== --- software/tuxosl/trunk/tux_osl_event_cmd_server.py (rev 0) +++ software/tuxosl/trunk/tux_osl_event_cmd_server.py 2008-01-24 10:54:19 UTC (rev 874) @@ -0,0 +1,322 @@ +#!/usr/bin/python +# -*- coding: latin1 -*- +# ----------------------------------------------------------------------------- +# Tux Droid - OSL - XMLRPC server of osl object +# Copyright (C) 2007 C2ME Sa <rem...@c2...> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. +# ----------------------------------------------------------------------------- +# $Id: $ +# ----------------------------------------------------------------------------- +import time +import threading +import copy +import socket +from SimpleXMLRPCServer import SimpleXMLRPCServer, SimpleXMLRPCRequestHandler +from tux_osl_event_controler import EventsHandler + +EVENT_SERVER_DEFAULT_PORT = 5510 +CMD_SERVER_DEFAULT_PORT = 5511 + + +class TuxOSLEventServer(object): + + def __init__(self, port = EVENT_SERVER_DEFAULT_PORT): + self.__clients = [] + self.__client_mutex = threading.Lock() + self.__port = port + self.__server_can_start = True + try: + self.__server = SimpleXMLRPCServer(("localhost", self.__port), LogHandler) + self.__server.register_function(self.register_client, 'register_me') + self.__server.register_function(self.unregister_client, 'unregister_me') + self.__server.register_function(self.get_events, 'get_events') + self.__server.register_introspection_functions() + self.__server.register_multicall_functions() + except socket.error: + print '[TUXOSL] : Event server : Binding error' + self.__server_can_start = False + self.__connected = False + self.__connected_mutex = threading.Lock() + self.__server_thread = None + self.__stop_flag = False + + def destroy(self): + self.stop() + + def set_connected(self, value): + self.__connected_mutex.acquire() + self.__connected = value + self.__connected_mutex.release() + + def get_connected(self): + self.__connected_mutex.acquire() + result = self.__connected + self.__connected_mutex.release() + return result + + def __serve_forever(self): + print '[TUXOSL] : Event server started' + while not self.__stop_flag: + try: + self.__server.handle_request() + except: + pass + + def __start(self): + self.set_connected(True) + try: + self.__server.socket.settimeout(0.5) + self.__serve_forever() + except: + print "[TUXOSL] : Error on start the event server" + self.set_connected(False) + + def start(self): + if not self.__server_can_start: + return False + self.__server_thread = threading.Thread(target = self.__start) + self.__server_thread.start() + return True + + def stop(self): + self.__client_mutex.acquire() + self.__clients = [] + self.__client_mutex.release() + self.__stop_flag = True + if self.__server_thread != None: + if self.__server_thread.isAlive(): + self.__server_thread.join() + print '[TUXOSL] : Event server stopped' + self.__stop_flag = False + self.__server.socket.close() + self.__server.server_close() + + def get_events(self, client_id): + self.__client_mutex.acquire() + if client_id >= len(self.__clients): + self.__client_mutex.release() + return [] + my_client = self.__clients[client_id] + self.__client_mutex.release() + if my_client != None: + result = my_client.get_event_stack().pop(0.5) + else: + result = [] + return result + + def update_events(self, event): + self.__client_mutex.acquire() + for client in self.__clients: + if client != None: + client.get_event_stack().push([event,]) + self.__client_mutex.release() + + def register_client(self, client_name): + self.__client_mutex.acquire() + cli_id = len(self.__clients) + new_client = TuxOSLClientEventObj(client_name, cli_id) + self.__clients.append(new_client) + self.__client_mutex.release() + print '[TUXOSL] : Client (%s:%d) has been added' % (client_name, cli_id) + return cli_id + + def unregister_client(self, client_id): + self.__client_mutex.acquire() + if client_id >= len(self.__clients): + self.__client_mutex.release() + return False + client_name = self.__clients[client_id].get_name() + self.__clients[client_id] = None + self.__client_mutex.release() + print '[TUXOSL] : Client (%s:%d) has been removed' % (client_name, client_id) + return True + +class TuxOSLClientEventObj(object): + + def __init__(self, name, id): + self.__name = name + self.__id = id + self.__event_stack = TuxOSLClientEventStack() + + def get_event_stack(self): + return self.__event_stack + + def get_id(self): + return self.__id + + def get_name(self): + return self.__name + +class TuxOSLClientEventStack(object): + + def __init__(self): + self.__stack = [] + self.__stack_mutex = threading.Lock() + + def push(self, events = []): + if len(events) == 0: + return + self.__stack_mutex.acquire() + for event in events: + self.__stack.append(event) + self.__stack_mutex.release() + + def pop(self, timeout = 1.0): + tb = time.time() + result = [] + while True: + if (time.time() - tb) > timeout: + break + self.__stack_mutex.acquire() + if len(self.__stack) != 0: + result = copy.copy(self.__stack) + self.__stack = [] + self.__stack_mutex.release() + break + self.__stack_mutex.release() + time.sleep(0.005) + return result + +class LogHandler(SimpleXMLRPCRequestHandler): + def send_response(self, code, message=None): + try: + SimpleXMLRPCRequestHandler.send_response(self, code, message=None) + except: + pass + + def send_header(self, keyword, value): + try: + SimpleXMLRPCRequestHandler.send_header(self, keyword, value) + except: + pass + + def end_headers(self): + try: + SimpleXMLRPCRequestHandler.end_headers(self) + except: + pass + + def log_request(self, code='-', size='-'): + pass + + def handle_one_request(self): + try: + SimpleXMLRPCRequestHandler.handle_one_request(self) + except: + pass + + def handle(self): + try: + SimpleXMLRPCRequestHandler.handle(self) + except: + pass + +class TuxOSLCmdServer(object): + + def __init__(self, osl_obj, port = CMD_SERVER_DEFAULT_PORT): + self.__port = port + self.__osl_obj = osl_obj + self.__server_can_start = True + try: + self.__server = SimpleXMLRPCServer(("localhost", self.__port), LogHandler) + self.__server.register_function(self.__osl_obj._tts_speak, '_tts_speak') + self.__server.register_function(self.__osl_obj._tts_set_pause, '_tts_set_pause') + self.__server.register_function(self.__osl_obj._tts_set_stop, '_tts_set_stop') + self.__server.register_function(self.__osl_obj._tts_get_authorized_voices_list, '_tts_get_authorized_voices_list') + self.__server.register_function(self.__osl_obj._tts_get_sound_state, '_tts_get_sound_state') + self.__server.register_function(self.__osl_obj._tts_get_pause_state, '_tts_get_pause_state') + self.__server.register_function(self.__osl_obj._tts_get_pitch, '_tts_get_pitch') + self.__server.register_function(self.__osl_obj.kill, 'kill') + self.__server.register_function(self.__osl_obj._wav_play, '_wav_play') + self.__server.register_function(self.__osl_obj._wav_set_pause, '_wav_set_pause') + self.__server.register_function(self.__osl_obj._wav_set_stop, '_wav_set_stop') + self.__server.register_function(self.__osl_obj._wav_get_sound_state, '_wav_get_sound_state') + self.__server.register_function(self.__osl_obj._wav_get_pause_state, '_wav_get_pause_state') + self.__server.register_function(self.__osl_obj.get_version, 'get_version') + self.__server.register_function(self.__osl_obj.get_connect_state, 'get_connect_state') + self.__server.register_introspection_functions() + self.__server.register_multicall_functions() + except socket.error: + print '[TUXOSL] : Cmd server : Binding error' + self.__server_can_start = False + self.__connected = False + self.__connected_mutex = threading.Lock() + self.__server_thread = None + self.__stop_flag = False + + def destroy(self): + self.stop() + + def set_connected(self, value): + self.__connected_mutex.acquire() + self.__connected = value + self.__connected_mutex.release() + + def get_connected(self): + self.__connected_mutex.acquire() + result = self.__connected + self.__connected_mutex.release() + return result + + def __serve_forever(self): + print '[TUXOSL] : Cmd server started' + while not self.__stop_flag: + try: + self.__server.handle_request() + except: + pass + + def __start(self): + self.set_connected(True) + try: + self.__server.socket.settimeout(0.5) + self.__serve_forever() + except: + print "[TUXOSL] : Error on start the cmd server" + self.set_connected(False) + + def start(self): + if not self.__server_can_start: + return False + self.__server_thread = threading.Thread(target = self.__start) + self.__server_thread.start() + return True + + def stop(self): + if not self.__server_can_start: + return + self.__stop_flag = True + if self.__server_thread != None: + if self.__server_thread.isAlive(): + self.__server_thread.join() + print '[TUXOSL] : Cmd server stopped' + self.__stop_flag = False + self.__server.socket.close() + self.__server.server_close() + + +if __name__ == "__main__": + e = TuxOSLEventServer() + def send_dummy_event(): + time.sleep(0.5) + while e.get_connected(): + e.update_events(('coucou', 'Test', 1)) + time.sleep(1) + t = threading.Thread(target = send_dummy_event) + t.start() + e.start() + Added: software/tuxosl/trunk/tux_osl_event_controler.py =================================================================== --- software/tuxosl/trunk/tux_osl_event_controler.py (rev 0) +++ software/tuxosl/trunk/tux_osl_event_controler.py 2008-01-24 10:54:19 UTC (rev 874) @@ -0,0 +1,344 @@ +#!/usr/bin/python +# -*- coding: latin1 -*- +# ----------------------------------------------------------------------------- +# Tux Droid - OSL - Events handlers +# Copyright (C) 2007 C2ME Sa <rem...@c2...> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. +# ----------------------------------------------------------------------------- +# $Id: $ +# ----------------------------------------------------------------------------- +import threading +import time +import copy + +class EventsHandler(object): + + def __init__(self): + self.event = {} + + def destroy(self): + for event_hdler in self.event.keys(): + self.event[event_hdler].destroy() + self.event = {} + + def insert(self, event_name): + if event_name not in self.event.keys(): + self.event[event_name] = EventHandler() + return True + else: + return False + + def connect(self, event_name, funct, condition = None, threaded = True, idx = None): + if event_name not in self.event.keys(): + return -1 + return self.event[event_name].connect(funct, condition, threaded, idx) + + def disconnect(self, event_name, idx): + if event_name not in self.event.keys(): + return + self.event[event_name].disconnect(idx) + + def push(self): + for event_hdler in self.event.keys(): + self.event[event_hdler].push() + + def pop(self): + for event_hdler in self.event.keys(): + self.event[event_hdler].pop() + + def clear(self): + for event_hdler in self.event.keys(): + self.event[event_hdler].clear() + + def emit(self, event_name, args): + if event_name not in self.event.keys(): + return + self.event[event_name].emit(*args) + + def notify(self, event_name, args): + if event_name not in self.event.keys(): + return + self.event[event_name].emit(*args) + + def wait_condition(self, event_name, condition, timeout = 999999999.0): + if event_name not in self.event.keys(): + return False, [] + return self.event[event_name].wait_condition(condition, timeout) + + def clear_conditions(self): + for event_hdler in self.event.keys(): + self.event[event_hdler].clear_conditions() + +class EventHandler(object): + + def __init__(self): + self.__funct_struct_list = [] + self.__fifo_list = [] + self.__list_mutex = threading.Lock() + self.__threads_list = [] + self.__lock_list = [] + self.__lock_mutex = threading.Lock() + self.__run_flag = True + self.__run_mutex = threading.Lock() + self.connect(self.__lock_list_process) + + def __get_run_flag(self): + self.__run_mutex.acquire() + result = self.__run_flag + self.__run_mutex.release() + return result + + def __set_run_flag(self, value): + self.__run_mutex.acquire() + self.__run_flag = value + self.__run_mutex.release() + + def destroy(self): + self.clear_conditions() + self.__set_run_flag(False) + for my_thread in self.__threads_list: + if my_thread.isAlive(): + my_thread._Thread__stop() + + def connect(self, funct, condition = None, threaded = True, idx = None): + if idx == None: + result = self.__connect(funct, condition, threaded) + else: + ret = self.__update_connect(idx, funct, condition, threaded) + if not ret: + result = self.__connect(funct, condition, threaded) + else: + result = idx + return result + + def __connect(self, funct, condition = None, threaded = True): + self.__list_mutex.acquire() + idx = len(self.__funct_struct_list) + n_funct = { + 'funct' : funct, + 'condition' : condition, + 'threaded' : threaded + } + self.__funct_struct_list.append(n_funct) + self.__list_mutex.release() + return idx + + def __update_connect(self, idx, funct, condition = None, threaded = True): + self.__list_mutex.acquire() + if idx < len(self.__funct_struct_list): + n_funct = { + 'funct' : funct, + 'condition' : condition, + 'threaded' : threaded + } + self.__funct_struct_list[idx] = n_funct + result = True + else: + result = False + self.__list_mutex.release() + return result + + def push(self): + self.__list_mutex.acquire() + self.__fifo_list.append(self.__funct_struct_list) + self.__list_mutex.release() + self.clear() + + def pop(self): + if len(self.__fifo_list) > 0: + self.__list_mutex.acquire() + self.__funct_struct_list = self.__fifo_list.pop() + self.__list_mutex.release() + + def clear(self): + self.__list_mutex.acquire() + self.__funct_struct_list = [] + self.__list_mutex.release() + + def disconnect(self, idx): + self.__list_mutex.acquire() + if idx < len(self.__funct_struct_list): + self.__funct_struct_list[idx] = None + self.__list_mutex.release() + + def __refresh_threads_list(self): + nl = [] + for t in self.__threads_list: + if t.isAlive(): + nl.append(t) + self.__threads_list = nl + + def __run(self, funct_ptr, idx, fargs): + try: + funct_ptr(*fargs) + except: + self.__list_mutex.acquire() + self.__funct_struct_list[idx] == None + self.__list_mutex.release() + + def emit(self, *fargs): + self.notify(*fargs) + + def notify(self, *fargs): + m_fargs = copy.copy(fargs) + self.__list_mutex.acquire() + if len(self.__funct_struct_list) == 0: + self.__list_mutex.release() + return + try: + funct_struct_list = self.__funct_struct_list + except: + self.__list_mutex.release() + return + self.__list_mutex.release() + for idx, funct_struct in enumerate(funct_struct_list): + if not self.__get_run_flag(): + break + if funct_struct != None: + condition_matched = True + if funct_struct['condition'] != None: # funct entry have a condition + if len(funct_struct['condition']) != len(m_fargs): + condition_matched = False + for i, rule in enumerate(funct_struct['condition']): + if funct_struct['condition'][i] not in [None, m_fargs[i]]: + condition_matched = False + break + if condition_matched: + self.__refresh_threads_list() + if funct_struct['threaded']: + t=threading.Thread(target=self.__run, args=(funct_struct['funct'], idx, m_fargs)) + t.setName('Event_CallBack') + try: + t.start() + self.__threads_list.append(t) + except: + pass + else: + self.__run(funct_struct['funct'], idx, m_fargs) + + def __lock_list_process(self, *args): + self.__lock_mutex.acquire() + new_lock_list = [] + + for my_lock in self.__lock_list: + if my_lock['timeout'] <= (time.time() - my_lock['start_time']): + my_lock['result'].append((None,)) + my_lock['mutex'].acquire() + my_lock['mutex'].notify() + my_lock['mutex'].release() + continue + + rules = my_lock['rules'] + if len(rules) != len(args): + new_lock_list.append(my_lock) + continue + + matched_rule = True + for i, rule in enumerate(rules): + if not rule in [None, args[i]]: + matched_rule = False + break + + if not matched_rule: + new_lock_list.append(my_lock) + continue + else: + my_lock['result'].append(args) + my_lock['mutex'].acquire() + my_lock['mutex'].notify() + my_lock['mutex'].release() + + self.__lock_list = new_lock_list + self.__lock_mutex.release() + + + def wait_condition(self, condition, timeout = 999999999.0): + result = [] + condition_mutex = threading.Condition(threading.Lock()) + new_lock = { + 'rules' : condition, + 'result' : result, + 'mutex' : condition_mutex, + 'start_time' : time.time(), + 'timeout' : timeout + } + self.__lock_mutex.acquire() + self.__lock_list.append(new_lock) + self.__lock_mutex.release() + condition_mutex.acquire() + condition_mutex.wait(timeout) + condition_mutex.release() + if len(result) != 0: + return True, result[0] + else: + return False, [] + + def clear_conditions(self): + for my_lock in self.__lock_list: + my_lock['timeout'] = 0.0 + my_lock['result'].append((None,)) + my_lock['mutex'].acquire() + my_lock['mutex'].notify() + my_lock['mutex'].release() + +if __name__ == "__main__": + import time + import thread + + def on_ten_event(*args): + print '--> Ten event (%d)' % args[0] + + def on_unit_event(*args): + print 'Unit event (%d)' % args[0] + + def dummy_events_loop(events_handler): + for i in range (100): + events_handler.emit('unit_event', (i,)) + if (i % 10) == 0: + events_handler.emit('ten_event', (i,)) + time.sleep(0.1) + + # Create an events handler + my_events_handler = EventsHandler() + + # Add two events + my_events_handler.insert('unit_event') + my_events_handler.insert('ten_event') + + # Connect callback functions + u_idx = my_events_handler.connect('unit_event', on_unit_event, threaded = False) + t_idx = my_events_handler.connect('ten_event', on_ten_event, threaded = False) + + # Start a dummy events loop in a thread + thread.start_new_thread(dummy_events_loop, (my_events_handler,)) + + # Wait a specific event with a timeout of 10 seconds + print 'Wait that unit is equal to 45' + my_events_handler.wait_condition('unit_event', (45,), 10.0) + print 'Wait ok ! The number is equal to 45' + + # Wait a specific event with a timeout of 10 seconds + print 'Wait that the number is equal to 90' + my_events_handler.wait_condition('ten_event', (90,), 10.0) + print 'Wait ok ! The number is equal to 90' + + # Disconnect callback functions + my_events_handler.disconnect('unit_event', u_idx) + my_events_handler.disconnect('ten_event', t_idx) + + # Destroy the handler + my_events_handler.destroy() Added: software/tuxosl/trunk/tux_osl_obj.py =================================================================== --- software/tuxosl/trunk/tux_osl_obj.py (rev 0) +++ software/tuxosl/trunk/tux_osl_obj.py 2008-01-24 10:54:19 UTC (rev 874) @@ -0,0 +1,600 @@ +#!/usr/bin/python +# -*- coding: latin1 -*- +# ----------------------------------------------------------------------------- +# Tux Droid - OSL - OSL Object +# Copyright (C) 2007 C2ME Sa <rem...@c2...> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. +# ----------------------------------------------------------------------------- +# $Id: $ +# ----------------------------------------------------------------------------- +import time +import sys +import threading +import os +from tux_osl_wrapper import TuxOSLWrapper +from tux_osl_const import * +from tux_osl_event_controler import EventsHandler +from tux_osl_event_cmd_client import TuxOSLEventClient, TuxOSLCmdClient + +TUX_OSL_OBJ_VERSION = '0.0.2-alpha' + +class TUXOSLVClass(object): + pass + +class TuxOSLObjAncestor(object): + + def __init__(self): + self.__version = TUX_OSL_OBJ_VERSION + self.__connect_state = False + self.__connect_mutex = threading.Lock() + self.current_wav_channel = 0 + self.current_tts_channel = 0 + self._events_hdl = EventsHandler() + self.__create_event_handlers() + self.on_event = self._events_hdl.event['all'] + self.on_connected = self._events_hdl.event['connected'] + self.on_disconnected = self._events_hdl.event['disconnected'] + self.on_sound_on = self._events_hdl.event['sound_on'] + self.on_sound_off = self._events_hdl.event['sound_off'] + self.on_kill = self._events_hdl.event['kill'] + self.tts = TUXOSLVClass() + self._bind_tts_functions() + self.wav = TUXOSLVClass() + self._bind_wav_functions() + + def destroy(self): + if self.get_connect_state(): + self.auto_connect(False) + self.disconnect() + self._events_hdl.destroy() + + def get_connect_state(self): + self.__connect_mutex.acquire() + result = self.__connect_state + self.__connect_mutex.release() + return result + + def set_connect_state(self, value): + self.__connect_mutex.acquire() + self.__connect_state = value + self.__connect_mutex.release() + + def connect(self, host = 'localhost', ports = [5510, 5511]): + pass + + def disconnect(self): + pass + + def auto_connect(self, value, host = 'localhost', ports = [5510, 5511]): + pass + + def get_version(self): + return self.__version + + def kill(self): + self._events_hdl.event['kill'].notify() + return True + + def update_events(self, *args): + self._events_hdl.event['all'].notify(*args) + if args[0] == 'text_to_speech': + if args[1] == self.current_tts_channel: + if args[2] == 'sound': + if args[3] == 'on': + self._events_hdl.event['tts_speak_start'].notify() + else: + self._events_hdl.event['tts_speak_stop'].notify() + if args[2] == 'pause': + if args[3] == 'on': + self._events_hdl.event['tts_pause_on'].notify() + else: + self._events_hdl.event['tts_pause_off'].notify() + if args[2] == 'voice_list': + self._events_hdl.event['voice_list_changed'].notify() + self._events_hdl.event['voice_list'].notify(args[3]) + if args[2] == 'speak_status': + self._events_hdl.event['speak_status'].notify(args[3]) + elif args[0] == 'wav_player': + if args[1] == self.current_wav_channel: + if args[2] == 'sound': + if args[3] == 'on': + self._events_hdl.event['wav_play_start'].notify() + else: + self._events_hdl.event['wav_play_stop'].notify() + if args[2] == 'pause': + if args[3] == 'on': + self._events_hdl.event['wav_pause_on'].notify() + else: + self._events_hdl.event['wav_pause_off'].notify() + elif args[0] == 'general': + if args[1] == 'sound': + if args[2] == 'on': + self._events_hdl.event['sound_on'].notify() + else: + self._events_hdl.event['sound_off'].notify() + elif args[1] == 'connected': + self._events_hdl.event['connected'].notify() + elif args[1] == 'disconnected': + self._events_hdl.event['disconnected'].notify() + + def __create_event_handlers(self): + self._events_hdl.insert('all') + self._events_hdl.insert('kill') + self._events_hdl.insert('sound_on') + self._events_hdl.insert('sound_off') + self._events_hdl.insert('connected') + self._events_hdl.insert('disconnected') + self._events_hdl.insert('voice_list_changed') + self._events_hdl.insert('voice_list') + self._events_hdl.insert('speak_status') + self._events_hdl.insert('tts_speak_start') + self._events_hdl.insert('tts_speak_stop') + self._events_hdl.insert('tts_pause_on') + self._events_hdl.insert('tts_pause_off') + self._events_hdl.insert('wav_play_start') + self._events_hdl.insert('wav_play_stop') + self._events_hdl.insert('wav_pause_on') + self._events_hdl.insert('wav_pause_off') + + def _bind_tts_functions(self): + self.tts.get_version = self.get_version + self.tts.get_connect_state = self.get_connect_state + self.tts.speak = self._tts_speak + self.tts.set_pause = self._tts_set_pause + self.tts.set_stop = self._tts_set_stop + self.tts.get_authorized_voices_list = self._tts_get_authorized_voices_list + self.tts.get_sound_state = self._tts_get_sound_state + self.tts.get_pause_state = self._tts_get_pause_state + self.tts.get_pitch = self._tts_get_pitch + self.tts._wait_speak_start = self._tts_wait_speak_start + self.tts.on_voice_list = self._events_hdl.event["voice_list"] + self.tts.on_voice_list_changed = self._events_hdl.event["voice_list_changed"] + self.tts.on_speak_start = self._events_hdl.event["tts_speak_start"] + self.tts.on_speak_stop = self._events_hdl.event["tts_speak_stop"] + self.tts.on_pause_on = self._events_hdl.event["tts_pause_on"] + self.tts.on_pause_off = self._events_hdl.event["tts_pause_off"] + self.tts.on_speak_status = self._events_hdl.event["speak_status"] + + def _bind_wav_functions(self): + self.wav.get_version = self.get_version + self.wav.get_connect_state = self.get_connect_state + self.wav.play = self._wav_play + self.wav.set_pause = self._wav_set_pause + self.wav.set_stop = self._wav_set_stop + self.wav.get_sound_state = self._wav_get_sound_state + self.wav.get_pause_state = self._wav_get_pause_state + self.wav._wait_play_start = self._wav_wait_play_start + self.wav.on_play_start = self._events_hdl.event["wav_play_start"] + self.wav.on_play_stop = sel... [truncated message content] |