speechd-discuss
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 5/6] move src/python to src/api/python


From: william hubbs
Subject: [PATCH 5/6] move src/python to src/api/python
Date: Wed, 15 Sep 2010 20:56:04 -0000

From: William Hubbs <address@hidden>
To: address@hidden

---
 configure.ac                                  |    6 +-
 src/Makefile.am                               |    6 +-
 src/api/Makefile.am                           |    4 +
 src/api/python/ChangeLog                      |  474 +++++++++++
 src/api/python/Makefile.am                    |    2 +
 src/api/python/README                         |   10 +
 src/api/python/speechd/Makefile.am            |   21 +
 src/api/python/speechd/__init__.py            |   18 +
 src/api/python/speechd/_test.py               |  136 +++
 src/api/python/speechd/client.py              | 1125 +++++++++++++++++++++++++
 src/api/python/speechd/paths.py.in            |    1 +
 src/api/python/speechd_config/Makefile.am     |   27 +
 src/api/python/speechd_config/__init__.py     |   18 +
 src/api/python/speechd_config/config.py       |  924 ++++++++++++++++++++
 src/api/python/speechd_config/paths.py.in     |    4 +
 src/api/python/speechd_config/spd-conf        |   10 +
 src/api/python/speechd_config/speechd.desktop |   11 +
 src/api/python/speechd_config/test.wav        |  Bin 0 -> 17410 bytes
 src/python/ChangeLog                          |  474 -----------
 src/python/Makefile.am                        |    2 -
 src/python/README                             |   10 -
 src/python/speechd/Makefile.am                |   21 -
 src/python/speechd/__init__.py                |   18 -
 src/python/speechd/_test.py                   |  136 ---
 src/python/speechd/client.py                  | 1125 -------------------------
 src/python/speechd/paths.py.in                |    1 -
 src/python/speechd_config/Makefile.am         |   27 -
 src/python/speechd_config/__init__.py         |   18 -
 src/python/speechd_config/config.py           |  924 --------------------
 src/python/speechd_config/paths.py.in         |    4 -
 src/python/speechd_config/spd-conf            |   10 -
 src/python/speechd_config/speechd.desktop     |   11 -
 src/python/speechd_config/test.wav            |  Bin 17410 -> 0 bytes
 33 files changed, 2789 insertions(+), 2789 deletions(-)
 create mode 100644 src/api/python/ChangeLog
 create mode 100644 src/api/python/Makefile.am
 create mode 100644 src/api/python/README
 create mode 100644 src/api/python/speechd/Makefile.am
 create mode 100644 src/api/python/speechd/__init__.py
 create mode 100644 src/api/python/speechd/_test.py
 create mode 100644 src/api/python/speechd/client.py
 create mode 100644 src/api/python/speechd/paths.py.in
 create mode 100644 src/api/python/speechd_config/Makefile.am
 create mode 100644 src/api/python/speechd_config/__init__.py
 create mode 100644 src/api/python/speechd_config/config.py
 create mode 100644 src/api/python/speechd_config/paths.py.in
 create mode 100644 src/api/python/speechd_config/spd-conf
 create mode 100644 src/api/python/speechd_config/speechd.desktop
 create mode 100644 src/api/python/speechd_config/test.wav
 delete mode 100644 src/python/ChangeLog
 delete mode 100644 src/python/Makefile.am
 delete mode 100644 src/python/README
 delete mode 100644 src/python/speechd/Makefile.am
 delete mode 100644 src/python/speechd/__init__.py
 delete mode 100644 src/python/speechd/_test.py
 delete mode 100644 src/python/speechd/client.py
 delete mode 100644 src/python/speechd/paths.py.in
 delete mode 100644 src/python/speechd_config/Makefile.am
 delete mode 100644 src/python/speechd_config/__init__.py
 delete mode 100644 src/python/speechd_config/config.py
 delete mode 100644 src/python/speechd_config/paths.py.in
 delete mode 100644 src/python/speechd_config/spd-conf
 delete mode 100644 src/python/speechd_config/speechd.desktop
 delete mode 100644 src/python/speechd_config/test.wav

diff --git a/configure.ac b/configure.ac
index 7902cf6..89448f3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -424,6 +424,9 @@ AC_CONFIG_FILES([Makefile
        src/Makefile
        src/api/Makefile
        src/api/c/Makefile
+       src/api/python/Makefile
+       src/api/python/speechd/Makefile
+       src/api/python/speechd_config/Makefile
        src/audio/Makefile
        src/audio/static_plugins.c
        src/clients/Makefile
@@ -431,9 +434,6 @@ AC_CONFIG_FILES([Makefile
        src/clients/spdsend/Makefile
        src/common/Makefile
        src/modules/Makefile
-       src/python/Makefile
-       src/python/speechd/Makefile
-       src/python/speechd_config/Makefile
        src/server/Makefile
        src/tests/Makefile])
 AC_OUTPUT
diff --git a/src/Makefile.am b/src/Makefile.am
index edefd62..47d134e 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -2,9 +2,5 @@
 
 SUBDIRS=common server audio modules api clients tests
 
-if HAVE_PYTHON
-SUBDIRS += python
-endif
-
-DIST_SUBDIRS=common server audio modules api clients tests python
+DIST_SUBDIRS=common server audio modules api clients tests
 
diff --git a/src/api/Makefile.am b/src/api/Makefile.am
index 2a90e9e..9f3ddfe 100644
--- a/src/api/Makefile.am
+++ b/src/api/Makefile.am
@@ -2,5 +2,9 @@
 
 SUBDIRS= c
 
+if HAVE_PYTHON
+SUBDIRS += python
+endif
+
 EXTRA_DIST = cl guile
 
diff --git a/src/api/python/ChangeLog b/src/api/python/ChangeLog
new file mode 100644
index 0000000..419f6b2
--- /dev/null
+++ b/src/api/python/ChangeLog
@@ -0,0 +1,474 @@
+2008-12-17  Hynek Hanke  <hanke at mach>
+
+       * Makefile.in: Create conf/desktop/ directory for
+       installation.
+
+2008-12-10  Hynek Hanke  <hanke at mach>
+
+       * speechd_config/config.py (Tests.diagnostics.decide_to_test): Set port 
in
+       ~/.profile and place speechd.desktop in ~/.config/autostart
+
+       * Makefile.in (all): Handle speechd.desktop.
+
+2008-11-26  Hynek Hanke  <hanke at mach>
+
+       * Makefile.in (maintainer-clean): Maintainer-clean does clean.
+
+2008-10-15  Hynek Hanke  <hanke at mach>
+
+       * Makefile.in: Respect ${DESTDIR}. 
+
+2008-08-11  Hynek Hanke  <hanke at brailcom.org>
+
+       * speechd_config/config.py (Tests.audio_try_play): Use proper 
os.path.join
+       for constructing path to the testing wav file.
+
+2008-07-31  Hynek Hanke  <hanke at brailcom.org>
+
+       * speechd_config/config.py (Tests.diagnostics): Only try hearing
+       test if Speech Dispatcher was started successfuly.
+       (Tests.diagnostics.decide_to_test): Do not ask whether to
+       start/restart but first try to stop and then subsequently
+       start via /etc/init.d/ (this covers both cases).
+
+2008-07-14  Hynek Hanke  <hanke at brailcom.org>
+
+       * Makefile.in (clean): Delete speechd_config/paths.py
+       (install): Include prefix correctly.
+       (sysconfdir): Define sysconfdir.
+
+2008-07-12  Hynek Hanke  <hanke at brailcom.org>
+
+       * speechd_config/config.py (Tests.diagnostics.decide_to_test):
+       AudioOutput method is the proper parameter name, not
+       DefaultAudioOutput.
+
+2008-07-11  Hynek Hanke  <hanke at brailcom.org>
+
+       * speechd_config/config.py (Options.__init__): Added basic
+       description into help message.
+
+       * Makefile.in (all): Typo in directory paths.
+
+       * speechd_config/config.py (Options.__init__): Include summary
+       message into help.
+
+2008-07-10  Hynek Hanke  <hanke at brailcom.org>
+
+       * speechd_config/config.py (Options): Restructured.
+       test_spd_say: New test.
+       Handle SPEECHD_PORT correctly.
+       (Tests.write_diagnostics_results): New method. 
+       Use TMPDIR correctly.
+       (Configuration.
+       (Configure.speechd_start_system): Allow also restart.
+       Bugfixes.
+
+2008-07-09  Hynek Hanke  <hanke at brailcom.org>
+
+       * speechd_config/config.py (Tests.diagnostics.decide_to_test):
+       Also include configuration into debugging archive.
+
+       * speechd_config/spd-conf: Do not call main() since it will
+       be called automatically on import.
+
+       * speechd_config/config.py: Typo.
+
+       * Makefile.in (all): speechd_config/paths.py generation moved
+       from install.
+
+       * setup.py (speechd_config) New module.
+
+       * Makefile.in (speechd_config): New module.
+       Write necessary paths into speech_config/conf_path.py
+
+2008-06-27  Hynek Hanke  <hanke at brailcom.org>
+
+       * speechd/client.py (SSIPClient.set_debug): New method.
+       (SSIPClient.set_debug_destination): New method.
+       (SSIPClient.set_debug): New method.
+       (SSIPClient.set_debug_destination): New method.
+
+2008-02-19  Tomas Cerha  <cerha at brailcom.org>
+
+       * README: New file.
+
+       * speechd/client.py (SSIPClient.__init__): Docstring improved.
+
+2008-02-04  Hynek Hanke  <hanke at mach>
+
+       * Makefile.in: New file. Propagate $prefix correctly.
+
+2008-01-29  Tomas Cerha  <cerha at brailcom.org>
+
+       * speechd/client.py (SSIPClient.__init__): Use the environment
+       variable `SPEECHD_HOST' if defined.
+
+2007-11-25  Tomas Cerha  <cerha at brailcom.org>
+
+       * speechd/client.py: Handle TypeError while SPEECHD_PORT value
+       conversion.
+
+2007-11-22  Tomas Cerha  <cerha at brailcom.org>
+
+       * speechd/client.py (SSIPClient.__init__): Use the environment
+       variable `SPEECHD_PORT' if defined.
+
+2007-07-11  Tomas Cerha  <cerha at brailcom.org>
+
+       * speechd/client.py (SSIPClient.list_synthesis_voices.split):
+       Convert empty strings to `None'.  Docstring improved.
+
+2007-07-10  Tomas Cerha  <cerha at brailcom.org>
+
+       * speechd/_test.py (AutomaticTest.test_callbacks): Test also the
+       `END' callback, which doesn't currently work with Flite.
+
+2007-07-04  Tomas Cerha  <cerha at brailcom.org>
+
+       * speechd/client.py (SSIPClient.resume, SSIPClient.pause): Send
+       the right SSIP commands.
+
+2007-07-03  Tomas Cerha  <cerha at brailcom.org>
+
+       * speechd/client.py (_SSIP_Connection._recv_response): Raise
+       exception if the communication thread is not alive.
+
+2007-07-02  Tomas Cerha  <cerha at brailcom.org>
+
+       * speechd/client.py (SSIPCommunicationError): New class.
+       (_SSIP_Connection._recv_response): Quit if the communication
+       thread is not alive.
+       (_SSIP_Connection.send_command, _SSIP_Connection.send_data): Raise
+       `SSIPCommunicationError' on socket error.
+
+2007-07-02  Hynek Hanke  <hanke at syrr.buchal.name>
+
+       * speechd/_test.py: Voice list test uncommented.
+
+2007-06-26  Tomas Cerha  <cerha at brailcom.org>
+
+       * speechd/_test.py (VoiceTest.test_lists): New test.
+
+       * speechd/client.py (SSIPClient.list_output_modules)
+       (SSIPClient.list_synthesis_voices, SSIPClient.set_output_module)
+       (SSIPClient.set_synthesis_voice): New methods.
+
+2007-05-03  Hynek Hanke  <hanke at brailcom.org>
+
+       * Makefile (clean): Remove build.
+
+2007-02-21  Tomas Cerha  <cerha at brailcom.org>
+
+       * speechd/_test.py (AutomaticTest.test_callbacks): Added warning.
+
+2007-02-17  Hynek Hanke  <hanke at brailcom.org>
+
+       * speechd/_test.py (AutomaticTest.test_callbacks): Removed comment
+       about Scope.SELF not working.
+       Added TODO comment about fixing this test.
+
+2007-02-05  Tomas Cerha  <cerha at brailcom.org>
+
+       * speechd/client.py (_SSIP_Connection.__init__): Thread name
+       changed.
+       (SSIPClient.__init__): Allocate lock.
+       (SSIPClient._callback_handler): Lock before accessing
+       `self._callbacks'.
+       (SSIPClient.speak): Added more doc.  Lock before accessing
+       `self._callbacks'.
+
+2007-01-29  Tomas Cerha  <cerha at brailcom.org>
+
+       * speechd/client.py (SSIPClient._callback_handler)
+       (SSIPClient.speak): Removed prints.
+
+       * speechd/_test.py (SSIPClientTest.check_callbacks): Wait for
+       callbacks after canceling messages.
+       (TestSuite): Class removed.
+       (tests): Instance removed.
+       (SSIPClientTest): Class split into `AutomaticTest' and `VoiceTest'.
+       (_SSIPClientTest, AutomaticTest, VoiceTest): New classes.
+       (SpeakerTest): Class removed.
+       (get_tests): Function removed.
+
+2007-01-26  Tomas Cerha  <cerha at brailcom.org>
+
+       * speechd/_test.py (SSIPClientTest.check_callbacks): New test.
+       (SSIPClientTest.check_notification): Temporarily commented out.
+
+       * speechd/client.py
+       (_SSIP_Connection._CALLBACK_TYPE_MAP): New constant.
+       (_SSIP_Connection.__init__): Initialize `self._callback' instead
+       of `self._callbacks'.
+       (_SSIP_Connection._communication): Docstring reformatted.  The
+       whole event dispatching rewritten to use `_CALLBACK_TYPE_MAP' and
+       use a single callback function.
+       (_SSIP_Connection.send_command): Docstring typo fixed.
+       (_SSIP_Connection.send_data): Docstring typo fixed.
+       (_SSIP_Connection.send_data): Return also server response data.
+       (_SSIP_Connection.set_callback): Argument `events' removed.
+       Docstring updated and extended.
+       (SSIPClient.__init__): Find out and store the client id.  Register
+       callback and turn on notifications for all supported event types.
+       (SSIPClient._callback_handler): New method.
+       (SSIPClient.speak): New keyword arguments `callback' and
+       `event_types'.  Docstring extended.  Convert `text' to `utf-8' if
+       it is a unicode instance.
+       (SSIPClient.char): Convert `char' to `utf-8' if it is a unicode
+       instance.
+       (SSIPClient.set_notification): Method removed.
+       (SSIPClient.close): Only operate on `self._conn' if it is defined.
+
+2006-11-05  Hynek Hanke  <hanke at brailcom.org>
+
+       * speechd/client.py: IMPORTANT: On initialization of the
+       connection, new lateral thread is started to handle the
+       communication. This thread is terminated when the connection is
+       closed.
+       (_SSIP_Connection._com_buffer): New attribute.
+       (_SSIP_Connection._callbacks): New attribute.
+       (_SSIP_Connection._ssip_reply_semaphore): New attribute.
+       (_SSIP_Connection._communication_thread): New attribute.
+       (_SSIP_Connection.send_command): 'or isinstance(args[0], int)'
+       added back again. This is valid SSIP.
+       (SSIPClient.set_notification): New public API function.
+
+       * speechd/_test.py
+       (SSIPClientTest.check_notification.my_callback): New test.
+
+       * speechd/client.py (_SSIP_Connection.__init__): Start the
+       self._communication method in a new thread.
+       (_SSIP_Connection._recv_response): 1->True
+       (_SSIP_Connection._recv_message): Renamed from _recv_response.
+       (SSIPClient.__del__): New destructor.
+
+2006-08-09  Hynek Hanke  <hanke at brailcom.org>
+
+       * setup.py: Use /usr/bin/env instead of /usr/bin/python
+
+       * Makefile (install): Install with correct prefix.
+
+2006-07-13  Hynek Hanke  <hanke at brailcom.org>
+
+       * Makefile: Only attempt to use distutils if python is installed.
+
+2006-07-11  Hynek Hanke  <hanke at chopin>
+
+       * speechd/client.py: Typos in docstrings.
+       (Speaker): Docstring clarification.
+       Method say() removed.
+
+2006-07-11  Tomas Cerha  <cerha at brailcom.org>
+
+       * speechd/_test.py: `Client' -> `SSIPClient'.
+       (ClientTest): -> `SSIPClientTest'.
+       (SSIPClientTest.check_escapes)
+       (SSIPClientTest.check_voice_properties) 
+       (SSIPClientTest.check_other_commands): `say' -> `speak'.
+       (SpeakerTest): New test class.
+
+       * speechd/client.py (Module): Docstring updated.
+       (Client): Class renamed to `SSIPClient'.
+       (SSIPClient): Docstring improved.
+       (SSIPClient.__init__): Don't initialize `self._current_priority'.
+       (SSIPClient.set_priority): Added docstring.  Always send the
+       command.  Don't check `self._current_priority'.
+       (SSIPClient.say): Method renamed to `speak'.
+       (SSIPClient.speak, SSIPClient.char, SSIPClient.key)
+       (SSIPClient.sound_icon): The arguent `priority' removed.  Don't
+       set the priority here.
+       (Speaker): New class.
+       (Client): New class.
+
+2006-07-10  Tomas Cerha  <cerha at brailcom.org>
+
+       * speechd/_test.py: Import `speechd' not `client'.
+       (Client): Renamed to `ClientTest'.
+       (ClientTest._client): New method.
+       (ClientTest.check_escapes, ClientTest.check_voice_properties) 
+       (ClientTest.check_other_commands): New methods.
+       (ClientTest.check_it): Method split into the above new methods.
+
+       * speechd/client.py: Don't import `string'.
+       (SSIPCommandError, SSIPDataError): Docstrings improved.
+       (_SSIP_Connection.NEWLINE): Renamed to `_NEWLINE'.
+       (_SSIP_Connection.END_OF_DATA_SINGLE): Renamed to
+       `_END_OF_DATA_MARKER'.
+       (_SSIP_Connection.END_OF_DATA_ESCAPED_SINGLE): Renamed to
+       `_END_OF_DATA_MARKER_ESCAPED'.
+       (_SSIP_Connection.END_OF_DATA_BEGIN)
+       (_SSIP_Connection.END_OF_DATA_ESCAPED_BEGIN): Constants removed.
+       (_SSIP_Connection.END_OF_DATA): Renamed to `_END_OF_DATA'.
+       (_SSIP_Connection.END_OF_DATA_ESCAPED): Renamed to
+       `_END_OF_DATA_ESCAPED'.
+       (_SSIP_Connection._readline): Docstring improved.  `self.NEWLINE'
+       -> `self._NEWLINE'.
+       (_SSIP_Connection.send_command): `self.NEWLINE' ->
+       `self._NEWLINE'.
+       (_SSIP_Connection.send_data): Use new constant names.
+       (Client.__init__): Initialize the `_priority' attribute to None.
+       (Client._set_priority): Only set the priority if it is different
+       than the last priority stored in the `_priority' attribute.  Set
+       this attribute on change.
+       (Client.char): Replace the space by `space' as required by SSIP.
+       (Client.__init__): `self._priority' renamed to
+       `self._current_priority'.
+       (Client._set_priority): Renamed to `_set_priority'.
+       (Client.set_priority): `self._priority' ->
+       `self._current_priority'.
+       (Client.char, Client.key, Client.sound_icon, Client.say):
+       `self._set_priority' -> `self.set_priority'.
+       (Client.pause): Improved docstring formatting.
+
+       * speechd/util.py: File removed.
+
+2006-06-28  Tomas Cerha  <cerha at brailcom.org>
+
+       * speechd/client.py (SSIPCommandError)
+       (_CommunicationError): Renamed to `SSIPError'.
+       (CommandError): Renamed to `SSIPCommandError'.
+       (SendDataError): Renamed to `SSIPDataError'.
+       (_SSIP_Connection.send_command): Added an assertion on the 'scope'
+       argument for certain commands.
+       (_SSIP_Connection.send_command): `CommandError' ->
+       `SSIPCommandError'.
+       (_SSIP_Connection.send_data): `SendDataError' -> `SSIPDataError'.
+       (Scope, Priority): New classes.
+       (Client): Derive from `object'.  Some doc added.
+       (Client.__init__): The `port' default value set to `None'.
+       (Client.__set_priority): Renamed to `_set_priority()'.
+       (Client._set_priority): Use the `Priority' constants for
+       assertion.
+       (__check_scope): Method removed.
+       (Client.say, Client.char, Client.key, Client.sound_icon): Use
+       `Priority' constants for default values.  `__set_priority()' ->
+       `_set_priority()'.  Docstrings updated.
+       (Client.char): Don't replace space by "space".
+       (Client.cancel, Client.stop, Client.resume, Client.set_language)
+       (Client.set_pitch, Client.set_rate, Client.set_volume)
+       (Client.set_punctuation, Client.set_spelling)
+       (Client.set_cap_let_recogn, Client.set_voice)
+       (Client.set_pause_context): Use `Scope' constants for default
+       values.  Don't call `__check_scope()'.  Docstrings updated.
+       (Client.say): Only set the priority if it's not a 'MESSAGE'.
+       (Client.set_rate, _SSIP_Connection.send_command): Use the `Scope'
+       constants for assertions.
+       (_SSIP_Connection.close): Unset the `_socket' attribute.
+       (PunctuationMode): New class.
+       (Client.__init__, Client._set_priority): Use the `Scope'
+       constants.
+       (Client.say): Don't set the priority if it is 'MESSAGE'.
+       (Client.set_pitch, Client.set_rate, Client.set_volume)
+       (Client.set_voice, Client.set_pause_context): Use `isinstance'
+       instead of comparint types.
+       (Client.set_punctuation): Use the 'PunctuationMode' constants for
+       assertions.
+
+2006-06-27  Tomas Cerha  <cerha at brailcom.org>
+
+       * speechd/client.py (_SSIP_Connection.__init__): Initialize
+       the `_buffer' attribute.
+       (_SSIP_Connection._readline): Read data from the socket using a
+       buffer, not character by character...
+       (Client.__init__): Require the `name' argument.  Changed the
+       default value of `user' to `unknown' and `component' to `default'.
+       (Client.pause): Cosmetical change.
+
+2003-11-20  Tomas Cerha  <cerha at freebsoft.org>
+
+       * speechd/client.py (Client): Changed the port number.
+
+       * speechd/_test.py (get_tests): Don't set the language.
+
+2003-07-22  Tomas Cerha  <cerha at freebsoft.org>
+
+       * speechd/_test.py (Client.check_it): Added tests for `set_rate()'
+       and `set_pitch()' methods.
+       (Client.check_it): Added test for Czech language.
+
+       * speechd/client.py: `Speech Daemon' changed to `Speech
+       Dispatcher'.
+       (_SSIP_Connection): New Class.
+       (Client.RECV_BUFFER_SIZE, Client.SSIP_NEWLINE)
+       (Client._SSIP_END_OF_DATA, Client._SSIP_END_OF_DATA_ESCAPED):
+       Constants removed.
+       (_Socket): Class removed.
+       (Client.__init__): Use `_SSIP_Conection' instead of plain socket.
+       (Client._send_command, Client._send_data, Client._recv_response):
+       Methods removed.
+       (Client.close): Close `self._conn' instead of `self._socket'.
+       (Client.say, Client.stop): Use `self._conn.send_command()' instead
+       of `self._send_command()'.
+       (Client.set_language): New method.
+       (Client.set_pitch): New method.
+       (Client.set_pitch): New method.
+       (Client.get_client_list): Use `self._conn.send_command()' instead
+       of `self._send_command()'.
+
+2003-07-17  Tomas Cerha  <cerha at freebsoft.org>
+
+       * speechd/_test.py (Client.check_it): Pass a new `user' argument
+       to `Client' constructor.
+
+       * speechd/client.py (Client.__init__._Socket): New class.
+       (Client.__init__): Use `_Socket' instead of `socket.socket'.
+       (Client._recv_response): Use `_Socket.readline()'.
+       (module): The commented out C library code removed.
+       (Client.say): Use new priority names.
+       (Client.__init__): Arguments `client_name' and `connection_name'
+       replaced by `user', `client' and `component'.  Send `self' in the
+       'SET self CLIENT_NAME' command.
+
+2003-03-30  Tomas Cerha  <cerha at brailcom.org>
+
+       * speechd/client.py (Client.SPEECH_PORT): Updated docstring.
+       (Client.RECV_BUFFER_SIZE, Client.SSIP_NEWLINE)
+       (Client._SSIP_END_OF_DATA, Client._SSIP_END_OF_DATA_ESCAPED): New
+       constants.
+       (Client._send_command, Client._send_data, Client._recv_response):
+       Use them.
+       (Client._send_data, Client._recv_response): Rewritten, to handle
+       multiline responses.  Return response data as third item of
+       returned tuple.
+       (Client.close): Don't send `BYE' command.
+       (Client.say): Don't return server response (isolate client from
+       those details). 
+       (Client.get_client_list): New method.
+
+2003-03-29  Tomas Cerha  <cerha at freebsoft.org>
+
+       * speechd/client.py (SPEECH_PORT, RECV_BUFFER_SIZE): Moved to
+       class `Client'.
+       (Client): Documentation added.
+       (Client.SPEECH_PORT, Client.RECV_BUFFER_SIZE): New constants.
+       (Client.__init__): `SPEECH_PORT' -> `self.SPEECH_PORT'
+       (Client._send_command): Cosmetic changes.
+       (Client._send_data): Cosmetic changes.
+       (Client._recv_response): Commant added. `RECV_BUFFER_SIZE' ->
+       `self.RECV_BUFFER_SIZE'.
+       (Client.close): Documentation added.
+       (Client.stop): New keyword argument `all'.
+       (Client.say): Documentation added.  Return the value of respose
+       code and message.
+
+2003-03-27  Tomas Cerha  <cerha at freebsoft.org>
+
+       * speechd/client.py: Import `string' module.
+       (SPEECH_PORT): Added docstring.
+       (RECV_BUFFER_SIZE): New constant.
+       (_CommunicationError): New class.
+       (CommandError): New class.
+       (SendDataError.data): New class.
+       (Client.__init__): Make `client_name' and `conn_name' keyword
+       args.
+       (Client._send_command): Convert `args' to strings.  Handle server
+       response.  Return resonse code and message.
+       (Client._send_data): New method.
+       (Client._recv_response): New method.
+       (Client.close): Before closing socket send a `BYE' command.
+       (Client.stop): New method.
+       (Client.say): New method.
+
+       * speechd/_test.py (Client.check_it): Test the `say()' method.
+
diff --git a/src/api/python/Makefile.am b/src/api/python/Makefile.am
new file mode 100644
index 0000000..d54489f
--- /dev/null
+++ b/src/api/python/Makefile.am
@@ -0,0 +1,2 @@
+## Process this file with automake to produce Makefile.in
+SUBDIRS = speechd speechd_config
diff --git a/src/api/python/README b/src/api/python/README
new file mode 100644
index 0000000..39d74a3
--- /dev/null
+++ b/src/api/python/README
@@ -0,0 +1,10 @@
+This is a Python interface to SSIP.
+
+Full range of SSIP commands is implemented including callback handling.  See
+the section "Python API" in Speech Dispatcher documentation for more
+information.
+
+If you have any questions, suggestions, etc., feel free to contact us at the
+mailing list <speechd at lists.freebsoft.org>.
+
+-- Tomas Cerha <cerha at freebsoft.org>
diff --git a/src/api/python/speechd/Makefile.am 
b/src/api/python/speechd/Makefile.am
new file mode 100644
index 0000000..59a7afe
--- /dev/null
+++ b/src/api/python/speechd/Makefile.am
@@ -0,0 +1,21 @@
+## Process this file with automake to produce Makefile.in
+
+speechd_pythondir = $(pyexecdir)/speechd
+speechd_python_PYTHON = __init__.py _test.py client.py
+
+nodist_speechd_python_PYTHON = paths.py
+
+edit = sed  \
+       -e 's:@address@hidden:$(bindir):g'
+
+paths.py: Makefile
+       rm -f $@
+       srcdir=; \
+       test -f ./address@hidden || srcdir=$(srcdir)/; \
+       $(edit) address@hidden > $@
+
+paths.py: $(srcdir)/paths.py.in
+
+CLEANFILES = paths.py
+
+EXTRA_DIST = paths.py.in
diff --git a/src/api/python/speechd/__init__.py 
b/src/api/python/speechd/__init__.py
new file mode 100644
index 0000000..2bb2923
--- /dev/null
+++ b/src/api/python/speechd/__init__.py
@@ -0,0 +1,18 @@
+# Copyright (C) 2001, 2002 Brailcom, o.p.s.
+#
+# 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 of the License, 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+from client import *
+
diff --git a/src/api/python/speechd/_test.py b/src/api/python/speechd/_test.py
new file mode 100644
index 0000000..d503e81
--- /dev/null
+++ b/src/api/python/speechd/_test.py
@@ -0,0 +1,136 @@
+#!/usr/bin/env python
+
+# Copyright (C) 2003, 2006, 2007 Brailcom, o.p.s.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public Licensex1 as published by
+# the Free Software Foundation; either version 2 of the License, 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+import unittest
+import time
+
+from client import PunctuationMode, CallbackType, SSIPClient, Scope, Speaker
+
+
+class _SSIPClientTest(unittest.TestCase):
+        
+    def setUp(self):
+        self._client = SSIPClient('test')
+        self._client.set_language('en')
+        self._client.set_rate(30)
+
+    def tearDown(self):
+        self._client.close()
+
+class AutomaticTest(_SSIPClientTest):
+    """A set of tests which may be evaluated automatically.
+
+    Please put all tests which require a user to listen to their output to the
+    VoiceTest below.
+
+    """
+    def test_callbacks(self):
+        # TODO: This needs to be fixed. There is no guarantee that
+        # the message will start in one second nor is there any
+        # guarantee that it will start at all. It can be interrupted
+        # by other applications etc. Also there is no guarantee that
+        # the cancel will arrive on time and the end callback will be
+        # received on time. Also the combination cancel/end does not have
+        # to work as expected and SD and the interface can still be ok.
+        # -- Hynek Hanke
+        self._client.set_output_module('flite')
+        called = {CallbackType.BEGIN: [],
+                  CallbackType.CANCEL: [],
+                  CallbackType.END: []}
+        self._client.speak("This message should get interrupted.  It is "
+                           "hopefully long enough to last more than 1 second.",
+                           callback=lambda type: called[type].append('msg1'))
+        self._client.speak("This second message should not be spoken at all.",
+                           callback=lambda type: called[type].append('msg2'))
+        time.sleep(1)
+        self._client.cancel()
+        self._client.speak("Hi.",
+                           callback=lambda type: called[type].append('msg3'))
+        # Wait for pending events...
+        time.sleep(3)
+        started, canceled, ended = [called[t] for t in (CallbackType.BEGIN,
+                                                        CallbackType.CANCEL,
+                                                        CallbackType.END)]
+        assert started == ['msg1', 'msg3'] and ended == ['msg3'] and \
+               'msg1' in canceled and 'msg2' in canceled and \
+               'msg3' not in canceled, \
+               (called,
+                "This failure only indicates a possible error.  The test "
+                "depends on proper timing and results may warry depending "
+                "on the used output module and other conditions.  See the "
+                "code of this test method if you want to investigate "
+                "further.")
+
+    
+
+class VoiceTest(_SSIPClientTest):
+    """This set of tests requires a user to listen to it.
+
+    The success or failure of the tests defined here can not be detected
+    automatically.
+
+    """
+    
+    def test_escapes(self):
+        c = self._client
+        c.speak("Testing data escapes:")
+        c.set_punctuation(PunctuationMode.ALL)
+        c.speak(".")
+        c.speak("Marker at the end.\r\n.\r\n")
+        c.speak(".\r\nMarker at the beginning.")
+    
+    def test_voice_properties(self):
+        c = self._client
+        c.speak("Testing voice properties:")
+        c.set_pitch(-100)
+        c.speak("I am fat Billy")
+        c.set_pitch(100)
+        c.speak("I am slim Willy")
+        c.set_pitch(0)
+        c.set_rate(100)
+        c.speak("I am quick Dick.")
+        c.set_rate(-80)
+        c.speak("I am slow Joe.")
+        c.set_rate(0)
+        c.set_pitch(100)
+        c.set_volume(-50)
+        c.speak("I am quiet Mariette.")
+        c.set_volume(100)
+        c.speak("I am noisy Daisy.")
+
+    def test_other_commands(self):
+        c = self._client
+        c.speak("Testing other commands:")
+        c.char("a")
+        c.key("shift_b")
+        c.sound_icon("empty")
+        
+    def test_lists(self):
+         c = self._client
+         for module in  c.list_output_modules():
+             c.set_output_module(module)
+             print "**", module
+             c.speak(module +"using default voice")
+             for name, lang, dialect in c.list_synthesis_voices():
+                 print " -", module, name, lang, dialect
+                 c.set_synthesis_voice(name)
+                 c.speak(module +" using voice "+ name)
+        
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/src/api/python/speechd/client.py b/src/api/python/speechd/client.py
new file mode 100644
index 0000000..13a9c7e
--- /dev/null
+++ b/src/api/python/speechd/client.py
@@ -0,0 +1,1125 @@
+# Copyright (C) 2003-2008 Brailcom, o.p.s.
+#
+# 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 of the License, 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+"""Python API to Speech Dispatcher
+
+Basic Python client API to Speech Dispatcher is provided by the 'SSIPClient'
+class.  This interface maps directly to available SSIP commands and logic.
+
+A more convenient interface is provided by the 'Speaker' class.
+
+"""
+
+#TODO: Blocking variants for speak, char, key, sound_icon.
+
+import socket, sys, os, subprocess, time, tempfile
+
+try:
+    import threading
+except:
+    import dummy_threading as threading
+
+import paths
+    
+class CallbackType(object):
+    """Constants describing the available types of callbacks"""
+    INDEX_MARK = 'index_marks'
+    """Index mark events are reported when the place they were
+    included into the text by the client application is reached
+    when speaking them"""
+    BEGIN = 'begin'
+    """The begin event is reported when Speech Dispatcher starts
+    actually speaking the message."""
+    END = 'end'
+    """The end event is reported after the message has terminated and
+    there is no longer any sound from it being produced"""
+    CANCEL = 'cancel'
+    """The cancel event is reported when a message is canceled either
+    on request of the user, because of prioritization of messages or
+    due to an error"""
+    PAUSE = 'pause'
+    """The pause event is reported after speaking of a message
+    was paused. It no longer produces any audio."""
+    RESUME = 'resume'
+    """The resume event is reported right after speaking of a message
+    was resumed after previous pause."""
+
+class SSIPError(Exception):
+    """Common base class for exceptions during SSIP communication."""
+    
+class SSIPCommunicationError(SSIPError):
+    """Exception raised when trying to operate on a closed connection."""
+
+    _additional_exception = None
+
+    def __init__(self, description=None, original_exception=None, **kwargs):
+        self._original_exception = original_exception
+        self._description = description
+        super(SSIPError, self).__init__(**kwargs)
+
+    def original_exception(self):
+        """Return the original exception if any
+
+        If this exception is secondary, being caused by a lower
+        level exception, return this original exception, otherwise
+        None"""
+        return self._original_exception
+
+    def set_additional_exception(self, exception):
+        """Set an additional exception
+        
+        See method additional_exception().
+        """
+        self._additional_exception = exception
+
+    def additional_exception(self):
+        """Return an additional exception
+        
+        Additional exceptions araise from failed attempts to resolve
+        the former problem"""
+        return self._additional_exception
+
+    def description(self):
+        """Return error description"""
+        return self._description
+
+    def __str__(self):
+        msgs = []
+        if self.description():
+            msgs.append(self.description())
+        if self.original_exception:
+            msgs.append("Original error: " + str(self.original_exception()))
+        if self.additional_exception:
+            msgs.append("Additional error: " + 
str(self.additional_exception()))
+        return "\n".join(msgs)
+
+class SSIPResponseError(Exception):
+    def __init__(self, code, msg, data):
+        Exception.__init__(self, "%s: %s" % (code, msg))
+        self._code = code
+        self._msg = msg
+        self._data = data
+
+    def code(self):
+        """Return the server response error code as integer number."""
+        return self._code
+        
+    def msg(self):
+        """Return server response error message as string."""
+        return self._msg
+
+
+class SSIPCommandError(SSIPResponseError):
+    """Exception raised on error response after sending command."""
+
+    def command(self):
+        """Return the command string which resulted in this error."""
+        return self._data
+
+    
+class SSIPDataError(SSIPResponseError):
+    """Exception raised on error response after sending data."""
+
+    def data(self):
+        """Return the data which resulted in this error."""
+        return self._data
+
+    
+class SpawnError(Exception):
+    """Indicates failure in server autospawn."""
+
+class CommunicationMethod(object):
+    """Constants describing the possible methods of connection to server."""
+    UNIX_SOCKET = 'unix_socket'
+    """Unix socket communication using a filesystem path"""
+    INET_SOCKET = 'inet_socket'
+    """Inet socket communication using a host and port"""
+
+class _SSIP_Connection(object):
+    """Implemantation of low level SSIP communication."""
+    
+    _NEWLINE = "\r\n"
+    _END_OF_DATA_MARKER = '.'
+    _END_OF_DATA_MARKER_ESCAPED = '..'
+    _END_OF_DATA = _NEWLINE + _END_OF_DATA_MARKER + _NEWLINE
+    _END_OF_DATA_ESCAPED = _NEWLINE + _END_OF_DATA_MARKER_ESCAPED + _NEWLINE
+    # Constants representing \r\n. and \r\n..
+    _RAW_DOTLINE = _NEWLINE + _END_OF_DATA_MARKER
+    _ESCAPED_DOTLINE = _NEWLINE + _END_OF_DATA_MARKER_ESCAPED
+
+    _CALLBACK_TYPE_MAP = {700: CallbackType.INDEX_MARK,
+                          701: CallbackType.BEGIN,
+                          702: CallbackType.END,
+                          703: CallbackType.CANCEL,
+                          704: CallbackType.PAUSE,
+                          705: CallbackType.RESUME,
+                          }
+
+    def __init__(self, communication_method, socket_path, host, port):
+        """Init connection: open the socket to server,
+        initialize buffers, launch a communication handling
+        thread.
+        """
+
+        if communication_method == CommunicationMethod.UNIX_SOCKET:
+            socket_family = socket.AF_UNIX
+            socket_connect_args = socket_path
+        elif communication_method == CommunicationMethod.INET_SOCKET:
+            assert host and port
+            socket_family = socket.AF_INET
+            socket_connect_args = (socket.gethostbyname(host), port)
+        else:
+            raise ValueError("Unsupported communication method")
+
+        try:
+            self._socket = socket.socket(socket_family, socket.SOCK_STREAM)
+            self._socket.connect(socket_connect_args)
+        except socket.error, ex:
+            raise SSIPCommunicationError("Can't open socket using method "
+                                         + communication_method,
+                                         original_exception = ex)
+
+        self._buffer = ""
+        self._com_buffer = []
+        self._callback = None
+        self._ssip_reply_semaphore = threading.Semaphore(0)
+        self._communication_thread = \
+                threading.Thread(target=self._communication, kwargs={},
+                                 name="SSIP client communication thread")
+        self._communication_thread.start()
+    
+    def close(self):
+        """Close the server connection, destroy the communication thread."""
+        # Read-write shutdown here is necessary, otherwise the socket.recv()
+        # function in the other thread won't return at last on some platforms.
+        try:
+            self._socket.shutdown(socket.SHUT_RDWR)
+        except socket.error:
+            pass
+        self._socket.close()
+        # Wait for the other thread to terminate
+        self._communication_thread.join()
+        
+    def _communication(self):
+        """Handle incomming socket communication.
+
+        Listens for all incomming communication on the socket, dispatches
+        events and puts all other replies into self._com_buffer list in the
+        already parsed form as (code, msg, data).  Each time a new item is
+        appended to the _com_buffer list, the corresponding semaphore
+        'self._ssip_reply_semaphore' is incremented.
+
+        This method is designed to run in a separate thread.  The thread can be
+        interrupted by closing the socket on which it is listening for
+        reading."""
+
+        while True:
+            try:
+                code, msg, data = self._recv_message()
+            except IOError:
+                # If the socket has been closed, exit the thread
+                sys.exit()
+            if code/100 != 7:
+                # This is not an index mark nor an event
+                self._com_buffer.append((code, msg, data))
+                self._ssip_reply_semaphore.release()
+                continue
+            # Ignore the event if no callback function has been registered.
+            if self._callback is not None:
+                type = self._CALLBACK_TYPE_MAP[code]
+                if type == CallbackType.INDEX_MARK:
+                    kwargs = {'index_mark': data[2]}
+                else:
+                    kwargs = {}
+                # Get message and client ID of the event
+                msg_id, client_id = map(int, data[:2])
+                self._callback(msg_id, client_id, type, **kwargs)
+                
+                
+    def _readline(self):
+        """Read one whole line from the socket.
+
+        Blocks until the line delimiter ('_NEWLINE') is read.
+        
+        """
+        pointer = self._buffer.find(self._NEWLINE)
+        while pointer == -1:
+            try:
+                d = self._socket.recv(1024)
+            except:
+                raise IOError
+            if len(d) == 0:
+                raise IOError
+            self._buffer += d
+            pointer = self._buffer.find(self._NEWLINE)
+        line = self._buffer[:pointer]
+        self._buffer = self._buffer[pointer+len(self._NEWLINE):]
+        return line
+
+    def _recv_message(self):
+        """Read server response or a callback
+        and return the triplet (code, msg, data)."""
+        data = []
+        c = None
+        while True:
+            line = self._readline()
+            assert len(line) >= 4, "Malformed data received from server!"
+            code, sep, text = line[:3], line[3], line[4:]
+            assert code.isalnum() and (c is None or code == c) and \
+                   sep in ('-', ' '), "Malformed data received from server!"
+            if sep == ' ':
+                msg = text
+                return int(code), msg, tuple(data)
+            data.append(text)
+
+    def _recv_response(self):
+        """Read server response from the communication thread
+        and return the triplet (code, msg, data)."""
+        # TODO: This check is dumb but seems to work.  The main thread
+        # hangs without it, when the Speech Dispatcher connection is lost.
+        if not self._communication_thread.isAlive():
+            raise SSIPCommunicationError
+        self._ssip_reply_semaphore.acquire()
+        # The list is sorted, read the first item
+        response = self._com_buffer[0]
+        del self._com_buffer[0]
+        return response
+
+    def send_command(self, command, *args):
+        """Send SSIP command with given arguments and read server response.
+
+        Arguments can be of any data type -- they are all stringified before
+        being sent to the server.
+
+        Returns a triplet (code, msg, data), where 'code' is a numeric SSIP
+        response code as an integer, 'msg' is an SSIP rsponse message as string
+        and 'data' is a tuple of strings (all lines of response data) when a
+        response contains some data.
+        
+        'SSIPCommandError' is raised in case of non 2xx return code.  See SSIP
+        documentation for more information about server responses and codes.
+
+        'IOError' is raised when the socket was closed by the remote side.
+        
+        """
+        if __debug__:
+            if command in ('SET', 'CANCEL', 'STOP',):
+                assert args[0] in (Scope.SELF, Scope.ALL) \
+                       or isinstance(args[0], int)
+        cmd = ' '.join((command,) + tuple(map(str, args)))
+        try:
+            self._socket.send(cmd + self._NEWLINE)
+        except socket.error:
+            raise SSIPCommunicationError("Speech Dispatcher connection lost.")
+        code, msg, data = self._recv_response()
+        if code/100 != 2:
+            raise SSIPCommandError(code, msg, cmd)
+        return code, msg, data
+        
+    def send_data(self, data):
+        """Send multiline data and read server response.
+
+        Returned value is the same as for 'send_command()' method.
+
+        'SSIPDataError' is raised in case of non 2xx return code. See SSIP
+        documentation for more information about server responses and codes.
+        
+        'IOError' is raised when the socket was closed by the remote side.
+        
+        """
+        # Escape the end-of-data marker even if present at the beginning
+        # The start of the string is also the start of a line.
+        if data.startswith(self._END_OF_DATA_MARKER):
+            l = len(self._END_OF_DATA_MARKER)
+            data = self._END_OF_DATA_MARKER_ESCAPED + data[l:]
+
+        # Escape the end of data marker at the start of each subsequent
+        # line.  We can do that by simply replacing \r\n. with \r\n..,
+        # since the start of a line is immediately preceded by \r\n,
+        # when the line is not the beginning of the string.
+        data = data.replace(self._RAW_DOTLINE, self._ESCAPED_DOTLINE)
+
+        try:
+            self._socket.send(data + self._END_OF_DATA)
+        except socket.error:
+            raise SSIPCommunicationError("Speech Dispatcher connection lost.")
+        code, msg, response_data = self._recv_response()
+        if code/100 != 2:
+            raise SSIPDataError(code, msg, data)
+        return code, msg, response_data
+
+    def set_callback(self, callback):
+        """Register a callback function for handling asynchronous events.
+
+        Arguments:
+          callback -- a callable object (function) which will be called to
+            handle asynchronous events (arguments described below).  Passing
+            `None' results in removing the callback function and ignoring
+            events.  Just one callback may be registered.  Attempts to register
+            a second callback will result in the former callback being
+            replaced.
+
+        The callback function must accept three positional arguments
+        ('message_id', 'client_id', 'event_type') and an optional keyword
+        argument 'index_mark' (when INDEX_MARK events are turned on).
+
+        Note, that setting the callback function doesn't turn the events on.
+        The user is responsible to turn them on by sending the appropriate `SET
+        NOTIFICATION' command.
+
+        """
+        self._callback = callback
+
+class _CallbackHandler(object):
+    """Internal object which handles callbacks."""
+
+    def __init__(self, client_id):
+        self._client_id = client_id
+        self._callbacks = {}
+        self._lock = threading.Lock()
+
+    def __call__(self, msg_id, client_id, type, **kwargs):
+        if client_id != self._client_id:
+            # TODO: does that ever happen?
+            return
+        self._lock.acquire()
+        try:
+            try:
+                callback, event_types = self._callbacks[msg_id]
+            except KeyError:
+                pass
+            else:
+                if event_types is None or type in event_types:
+                    callback(type, **kwargs)
+                if type in (CallbackType.END, CallbackType.CANCEL):
+                    del self._callbacks[msg_id]
+        finally:
+            self._lock.release()
+
+    def add_callback(self, msg_id,  callback, event_types):
+        self._lock.acquire()
+        try:
+            self._callbacks[msg_id] = (callback, event_types)
+        finally:
+            self._lock.release()
+
+class Scope(object):
+    """An enumeration of valid SSIP command scopes.
+
+    The constants of this class should be used to specify the 'scope' argument
+    for the 'Client' methods.
+
+    """    
+    SELF = 'self'
+    """The command (mostly a setting) applies to current connection only."""
+    ALL = 'all'
+    """The command applies to all current Speech Dispatcher connections."""
+
+    
+class Priority(object):
+    """An enumeration of valid SSIP message priorities.
+
+    The constants of this class should be used to specify the 'priority'
+    argument for the 'Client' methods.  For more information about message
+    priorities and their interaction, see the SSIP documentation.
+    
+    """
+    IMPORTANT = 'important'
+    TEXT = 'text'
+    MESSAGE = 'message'
+    NOTIFICATION = 'notification'
+    PROGRESS = 'progress'
+
+    
+class PunctuationMode(object):
+    """Constants for selecting a punctuation mode.
+
+    The mode determines which characters should be read.
+
+    """
+    ALL = 'all'
+    """Read all punctuation characters."""
+    NONE = 'none'
+    """Don't read any punctuation character at all."""
+    SOME = 'some'
+    """Only the user-defined punctuation characters are read.
+
+    The set of characters is specified in Speech Dispatcher configuration.
+
+    """
+
+class DataMode(object):
+    """Constants specifying the type of data contained within messages
+    to be spoken.
+
+    """
+    TEXT = 'text'
+    """Data is plain text."""
+    SSML = 'ssml'
+    """Data is SSML (Speech Synthesis Markup Language)."""
+
+
+class SSIPClient(object):
+    """Basic Speech Dispatcher client interface.
+
+    This class provides a Python interface to Speech Dispatcher functionality
+    over an SSIP connection.  The API maps directly to available SSIP commands.
+    Each connection to Speech Dispatcher is represented by one instance of this
+    class.
+    
+    Many commands take the 'scope' argument, thus it is shortly documented
+    here.  It is either one of 'Scope' constants or a number of connection.  By
+    specifying the connection number, you are applying the command to a
+    particular connection.  This feature is only meant to be used by Speech
+    Dispatcher control application, however.  More datails can be found in
+    Speech Dispatcher documentation.
+
+    """
+    
+    DEFAULT_HOST = '127.0.0.1'
+    """Default host for server connections."""
+    DEFAULT_PORT = 6560
+    """Default port number for server connections."""
+    DEFAULT_SOCKET_PATH = "~/.speech-dispatcher/speechd.sock"
+    """Default name of the communication unix socket"""
+    
+    def __init__(self, name, component='default', user='unknown', address=None,
+                 autospawn=None,
+                 # Deprecated ->
+                 host=None, port=None, method=None, socket_path=None):
+        """Initialize the instance and connect to the server.
+
+        Arguments:
+          name -- client identification string
+          component -- connection identification string.  When one client opens
+            multiple connections, this can be used to identify each of them.
+          user -- user identification string (user name).  When multi-user
+            acces is expected, this can be used to identify their connections.
+          address -- server address as specified in Speech Dispatcher
+            documentation (e.g. 
"unix:/home/joe/.speech-dispatcher/speechd.sock"
+            or "inet:192.168.0.85:6561")
+          autospawn -- a flag to specify whether the library should
+            try to start the server if it determines its not already
+            running or not
+
+        Deprecated arguments:
+          method -- communication method to use, one of the constants defined 
in class
+            CommunicationMethod
+          socket_path -- for CommunicationMethod.UNIX_SOCKET, socket
+            path in filesystem. By default, this is 
~/.speech-dispatcher/speechd.sock
+            where `~' is the users home directory as determined from the system
+            defaults and from the $HOMEDIR environment variable.
+          host -- for CommunicationMethod.INET_SOCKET, server hostname
+            or IP address as a string.  If None, the default value is
+            taken from SPEECHD_HOST environment variable (if it
+            exists) or from the DEFAULT_HOST attribute of this class.
+          port -- for CommunicationMethod.INET_SOCKET method, server
+            port as number or None.  If None, the default value is
+            taken from SPEECHD_PORT environment variable (if it
+            exists) or from the DEFAULT_PORT attribute of this class.
+         
+        For more information on client identification strings see Speech
+        Dispatcher documentation.
+        """
+
+        # Resolve connection parameters:
+        connection_args = {'communication_method': 
CommunicationMethod.UNIX_SOCKET,
+                           'socket_path': 
os.path.expanduser(self.DEFAULT_SOCKET_PATH),
+                           'host': self.DEFAULT_HOST,
+                           'port': self.DEFAULT_PORT,
+                           }
+        # Respect address method argument and SPEECHD_ADDRESS environemt 
variable
+        _address = address or os.environ.get("SPEECHD_ADDRESS")        
+
+        if _address:
+            
connection_args.update(self._connection_arguments_from_address(_address))
+        # Respect the old (deprecated) key arguments and environment variables
+        # TODO: Remove this section in 0.8 release
+        else:
+            # Read the environment variables
+            env_speechd_host = os.environ.get("SPEECHD_HOST")
+            try:
+                env_speechd_port = int(os.environ.get("SPEECHD_PORT"))
+            except:
+                env_speechd_port = None
+            env_speechd_socket_path = os.environ.get("SPEECHD_SOCKET")
+            # Prefer old (deprecated) function arguments, but if
+            # not specified and old (deprecated) environment variable
+            # is set, use the value of the environment variable
+            if method:
+                connection_args['method'] = method
+            if port:
+                connection_args['port'] = port
+            elif env_speechd_port:
+                connection_args['port'] = env_speechd_port
+            if socket_path:
+                connection_args['socket_path'] = socket_path
+            elif env_speechd_socket_path:
+                connection_args['socket_path'] = env_speechd_socket_path
+        self._connect_with_autospawn(connection_args, autospawn)
+        self._initialize_connection(user, name, component)
+
+    def _connect_with_autospawn(self, connection_args, autospawn):
+        """Establish new connection (and/or autospawn server)"""
+        try:
+            self._conn = _SSIP_Connection(**connection_args)
+        except SSIPCommunicationError, ce:
+            # Suppose server might not be running, try the autospawn mechanism
+            if autospawn != False:
+                # Autospawn is however not guaranteed to start the server. The 
server
+                # will decide, based on it's configuration, whether to honor 
the request.
+                try:
+                    self._server_spawn(connection_args)
+                except SpawnError, se:
+                    ce.set_additional_exception(se)
+                    raise ce
+                self._conn = _SSIP_Connection(**connection_args)
+            else:
+                raise
+
+    def _initialize_connection(self, user, name, component):
+        """Initialize connection -- Set client name, get id, register 
callbacks etc."""
+        full_name = '%s:%s:%s' % (user, name, component)
+        self._conn.send_command('SET', Scope.SELF, 'CLIENT_NAME', full_name)
+        code, msg, data = self._conn.send_command('HISTORY', 'GET', 
'CLIENT_ID')
+        self._client_id = int(data[0])
+        self._callback_handler = _CallbackHandler(self._client_id)
+        self._conn.set_callback(self._callback_handler)
+        for event in (CallbackType.INDEX_MARK,
+                      CallbackType.BEGIN,
+                      CallbackType.END,
+                      CallbackType.CANCEL,
+                      CallbackType.PAUSE,
+                      CallbackType.RESUME):
+            self._conn.send_command('SET', 'self', 'NOTIFICATION', event, 'on')
+
+    def _connection_arguments_from_address(self, address):
+        """Parse a Speech Dispatcher address line and return a dictionary
+        of connection arguments"""
+        connection_args = {}
+        address_params = address.split(":")
+        try:
+            _method = address_params[0]
+        except:
+            raise SSIPCommunicationErrror("Wrong format of server address")
+        connection_args['communication_method'] = _method
+        if _method == CommunicationMethod.UNIX_SOCKET:
+            try:
+                connection_args['socket_path'] = address_params[1]
+            except IndexError:
+                pass # The additional parameters was not set, let's stay with 
defaults
+        elif _method == CommunicationMethod.INET_SOCKET:
+            try:
+                connection_args['host'] = address_params[1]
+                connection_args['port'] = int(address_params[2])
+            except ValueError: # Failed conversion to int
+                raise SSIPCommunicationError("Third parameter of inet_socket 
address must be a port number")
+            except IndexError:
+                pass # The additional parameters was not set, let's stay with 
defaults
+        else:
+            raise SSIPCommunicationError("Unknown communication method in 
address.");
+        return connection_args
+    
+    def __del__(self):
+        """Close the connection"""
+        self.close()
+
+    def _server_spawn(self, connection_args):
+        """Attempts to spawn the speech-dispatcher server."""
+        # Check whether we are not connecting to a remote host
+        # TODO: This is a hack. inet sockets specific code should
+        # belong to _SSIPConnection. We do not however have an _SSIPConnection
+        # yet.
+        if connection_args['communication_method'] == 'inet_socket':
+            addrinfos = socket.getaddrinfo(connection_args['host'],
+                                           connection_args['port'])
+            # Check resolved addrinfos for presence of localhost
+            ip_addresses = [addrinfo[4][0] for addrinfo in addrinfos]
+            localhost=False
+            for ip in ip_addresses:
+                if ip.startswith("127.") or ip == "::1":
+                    connection_args['host'] = ip
+                    localhost=True
+            if not localhost:
+                # The hostname didn't resolve on localhost in neither case,
+                # do not spawn server on localhost...
+                raise SpawnError(
+                    "Can't start server automatically (autospawn), requested 
address %s "
+                    "resolves on %s which seems to be a remote host. You must 
start the "
+                    "server manually or choose another connection address." % 
(connection_args['host'],
+                                                                               
str(ip_addresses),))
+        if os.path.exists(paths.SPD_SPAWN_CMD):
+            connection_params = []
+            for param, value in connection_args.items():
+                if param not in ["host",]:
+                    connection_params += ["--"+param.replace("_","-"), 
str(value)]
+
+            server = subprocess.Popen([paths.SPD_SPAWN_CMD, 
"--spawn"]+connection_params,
+                                      stdin=None, stdout=subprocess.PIPE, 
stderr=subprocess.PIPE)
+            stdout_reply, stderr_reply = server.communicate()
+            retcode = server.wait()
+            if retcode != 0:
+                raise SpawnError("Server refused to autospawn, stating this 
reason: %s" % (stderr_reply,))
+            return server.pid
+        else:
+            raise SpawnError("Can't find Speech Dispatcher spawn command %s"
+                                         % (paths.SPD_SPAWN_CMD,))
+
+    def set_priority(self, priority):
+        """Set the priority category for the following messages.
+
+        Arguments:
+          priority -- one of the 'Priority' constants.
+
+        """
+        assert priority in (Priority.IMPORTANT, Priority.MESSAGE,
+                            Priority.TEXT, Priority.NOTIFICATION,
+                            Priority.PROGRESS), priority
+        self._conn.send_command('SET', Scope.SELF, 'PRIORITY', priority)
+
+    def set_data_mode(self, value):
+        """Set the data mode for further speech commands.
+
+        Arguments:
+          value - one of the constants defined by the DataMode class.
+
+        """
+        if value == DataMode.SSML:
+            ssip_val = 'on'
+        elif value == DataMode.TEXT:
+            ssip_val = 'off'
+        else:
+            raise ValueError(
+                'Value "%s" is not one of the constants from the DataMode 
class.' % \
+                    value)
+        self._conn.send_command('SET', Scope.SELF, 'SSML_MODE', ssip_val)
+
+    def speak(self, text, callback=None, event_types=None):
+        """Say given message.
+
+        Arguments:
+          text -- message text to be spoken.  This may be either a UTF-8
+            encoded byte string or a Python unicode string.
+          callback -- a callback handler for asynchronous event notifications.
+            A callable object (function) which accepts one positional argument
+            `type' and one keyword argument `index_mark'.  See below for more
+            details.
+          event_types -- a tuple of event types for which the callback should
+            be called.  Each item must be one of `CallbackType' constants.
+            None (the default value) means to handle all event types.  This
+            argument is irrelevant when `callback' is not used.
+
+        The callback function will be called whenever one of the events occurs.
+        The event type will be passed as argument.  Its value is one of the
+        `CallbackType' constants.  In case of an index mark event, additional
+        keyword argument `index_mark' will be passed and will contain the index
+        mark identifier as specified within the text.
+
+        The callback function should not perform anything complicated and is
+        not allowed to issue any further SSIP client commands.  An attempt to
+        do so would lead to a deadlock in SSIP communication.
+
+        This method is non-blocking;  it just sends the command, given
+        message is queued on the server and the method returns immediately.
+
+        """
+        self._conn.send_command('SPEAK')
+        if isinstance(text, unicode):
+            text = text.encode('utf-8')
+        result = self._conn.send_data(text)
+        if callback:
+            msg_id = int(result[2][0])
+            # TODO: Here we risk, that the callback arrives earlier, than we
+            # add the item to `self._callback_handler'.  Such a situation will
+            # lead to the callback being ignored.
+            self._callback_handler.add_callback(msg_id, callback, event_types)
+        return result
+
+    def char(self, char):
+        """Say given character.
+
+        Arguments:
+          char -- a character to be spoken.  Either a Python unicode string or
+            a UTF-8 encoded byte string.
+
+        This method is non-blocking;  it just sends the command, given
+        message is queued on the server and the method returns immediately.
+
+        """
+        if isinstance(char, unicode):
+            char = char.encode('utf-8')
+        self._conn.send_command('CHAR', char.replace(' ', 'space'))
+        
+    def key(self, key):
+        """Say given key name.
+
+        Arguments:
+          key -- the key name (as defined in SSIP); string.
+
+        This method is non-blocking;  it just sends the command, given
+        message is queued on the server and the method returns immediately.
+
+        """
+        self._conn.send_command('KEY', key)
+
+    def sound_icon(self, sound_icon):
+        """Output given sound_icon.
+
+        Arguments:
+          sound_icon -- the name of the sound icon as defined by SSIP; string.
+
+        This method is non-blocking; it just sends the command, given message
+        is queued on the server and the method returns immediately.
+
+        """        
+        self._conn.send_command('SOUND_ICON', sound_icon)
+                    
+    def cancel(self, scope=Scope.SELF):
+        """Immediately stop speaking and discard messages in queues.
+
+        Arguments:
+          scope -- see the documentation of this class.
+            
+        """
+        self._conn.send_command('CANCEL', scope)
+
+
+    def stop(self, scope=Scope.SELF):
+        """Immediately stop speaking the currently spoken message.
+
+        Arguments:
+          scope -- see the documentation of this class.
+        
+        """
+        self._conn.send_command('STOP', scope)
+
+    def pause(self, scope=Scope.SELF):
+        """Pause speaking and postpone other messages until resume.
+
+        This method is non-blocking.  However, speaking can continue for a
+        short while even after it's called (typically to the end of the
+        sentence).
+
+        Arguments:
+          scope -- see the documentation of this class.
+        
+        """
+        self._conn.send_command('PAUSE', scope)
+
+    def resume(self, scope=Scope.SELF):
+        """Resume speaking of the currently paused messages.
+
+        This method is non-blocking.  However, speaking can continue for a
+        short while even after it's called (typically to the end of the
+        sentence).
+
+        Arguments:
+          scope -- see the documentation of this class.
+        
+        """
+        self._conn.send_command('RESUME', scope)
+
+    def list_output_modules(self):
+        """Return names of all active output modules as a tuple of strings."""
+        code, msg, data = self._conn.send_command('LIST', 'OUTPUT_MODULES')
+        return data
+
+    def list_synthesis_voices(self):
+        """Return names of all available voices for the current output module.
+
+        Returns a tuple of tripplets (name, language, dialect).
+
+        'name' is a string, 'language' is an ISO 639-1 Alpha-2 language code
+        and 'dialect' is a string.  Language and dialect may be None.
+
+        """
+        try:
+            code, msg, data = self._conn.send_command('LIST', 
'SYNTHESIS_VOICES')
+        except SSIPCommandError:
+            return ()
+        def split(item):
+            name, lang, dialect = tuple(item.rsplit(' ', 3))
+            return (name, lang or None, dialect or None)
+        return tuple([split(item) for item in data])
+
+    def set_language(self, language, scope=Scope.SELF):
+        """Switch to a particular language for further speech commands.
+
+        Arguments:
+          language -- two letter language code according to RFC 1776 as string.
+          scope -- see the documentation of this class.
+            
+        """
+        assert isinstance(language, str) and len(language) == 2
+        self._conn.send_command('SET', scope, 'LANGUAGE', language)
+
+    def set_output_module(self, name, scope=Scope.SELF):
+        """Switch to a particular output module.
+
+        Arguments:
+          name -- module (string) as returned by 'list_output_modules()'.
+          scope -- see the documentation of this class.
+        
+        """
+        self._conn.send_command('SET', scope, 'OUTPUT_MODULE', name)
+
+    def set_pitch(self, value, scope=Scope.SELF):
+        """Set the pitch for further speech commands.
+
+        Arguments:
+          value -- integer value within the range from -100 to 100, with 0
+            corresponding to the default pitch of the current speech synthesis
+            output module, lower values meaning lower pitch and higher values
+            meaning higher pitch.
+          scope -- see the documentation of this class.
+          
+        """
+        assert isinstance(value, int) and -100 <= value <= 100, value
+        self._conn.send_command('SET', scope, 'PITCH', value)
+
+    def set_rate(self, value, scope=Scope.SELF):
+        """Set the speech rate (speed) for further speech commands.
+
+        Arguments:
+          value -- integer value within the range from -100 to 100, with 0
+            corresponding to the default speech rate of the current speech
+            synthesis output module, lower values meaning slower speech and
+            higher values meaning faster speech.
+          scope -- see the documentation of this class.
+            
+        """
+        assert isinstance(value, int) and -100 <= value <= 100
+        self._conn.send_command('SET', scope, 'RATE', value)
+
+    def set_volume(self, value, scope=Scope.SELF):
+        """Set the speech volume for further speech commands.
+
+        Arguments:
+          value -- integer value within the range from -100 to 100, with 100
+            corresponding to the default speech volume of the current speech
+            synthesis output module, lower values meaning softer speech.
+          scope -- see the documentation of this class.
+            
+        """
+        assert isinstance(value, int) and -100 <= value <= 100
+        self._conn.send_command('SET', scope, 'VOLUME', value)
+
+    def set_punctuation(self, value, scope=Scope.SELF):
+        """Set the punctuation pronounciation level.
+
+        Arguments:
+          value -- one of the 'PunctuationMode' constants.
+          scope -- see the documentation of this class.
+            
+        """
+        assert value in (PunctuationMode.ALL, PunctuationMode.SOME,
+                         PunctuationMode.NONE), value
+        self._conn.send_command('SET', scope, 'PUNCTUATION', value)
+
+    def set_spelling(self, value, scope=Scope.SELF):
+        """Toogle the spelling mode or on off.
+
+        Arguments:
+          value -- if 'True', all incomming messages will be spelled
+            instead of being read as normal words. 'False' switches
+            this behavior off.
+          scope -- see the documentation of this class.
+            
+        """
+        assert value in [True, False]
+        if value == True:
+            self._conn.send_command('SET', scope, 'SPELLING', "on")
+        else:
+            self._conn.send_command('SET', scope, 'SPELLING', "off")
+
+    def set_cap_let_recogn(self, value, scope=Scope.SELF):
+        """Set capital letter recognition mode.
+
+        Arguments:
+          value -- one of 'none', 'spell', 'icon'. None means no signalization
+            of capital letters, 'spell' means capital letters will be spelled
+            with a syntetic voice and 'icon' means that the capital-letter icon
+            will be prepended before each capital letter.
+          scope -- see the documentation of this class.
+            
+        """
+        assert value in ("none", "spell", "icon")
+        self._conn.send_command('SET', scope, 'CAP_LET_RECOGN', value)
+
+    def set_voice(self, value, scope=Scope.SELF):
+        """Set voice by a symbolic name.
+
+        Arguments:
+          value -- one of the SSIP symbolic voice names: 'MALE1' .. 'MALE3',
+            'FEMALE1' ... 'FEMALE3', 'CHILD_MALE', 'CHILD_FEMALE'
+          scope -- see the documentation of this class.
+
+        Symbolic voice names are mapped to real synthesizer voices in the
+        configuration of the output module.  Use the method
+        'set_synthesis_voice()' if you want to work with real voices.
+            
+        """
+        assert isinstance(value, str) and \
+               value.lower() in ("male1", "male2", "male3", "female1",
+                                 "female2", "female3", "child_male",
+                                 "child_female")
+        self._conn.send_command('SET', scope, 'VOICE', value)
+
+    def set_synthesis_voice(self, value, scope=Scope.SELF):
+        """Set voice by its real name.
+
+        Arguments:
+          value -- voice name as returned by 'list_synthesis_voices()'
+          scope -- see the documentation of this class.
+            
+        """
+        self._conn.send_command('SET', scope, 'SYNTHESIS_VOICE', value)
+        
+    def set_pause_context(self, value, scope=Scope.SELF):
+        """Set the amount of context when resuming a paused message.
+
+        Arguments:
+          value -- a positive or negative value meaning how many chunks of data
+            after or before the pause should be read when resume() is executed.
+          scope -- see the documentation of this class.
+            
+        """
+        assert isinstance(value, int)
+        self._conn.send_command('SET', scope, 'PAUSE_CONTEXT', value)
+
+    def set_debug(self, val):
+        """Switch debugging on and off. When switched on,
+        debugging files will be created in the chosen destination
+        (see set_debug_destination()) for Speech Dispatcher and all
+        its running modules. All logging information will then be
+        written into these files with maximal verbosity until switched
+        off. You should always first call set_debug_destination.
+
+        The intended use of this functionality is to switch debuging
+        on for a period of time while the user will repeat the behavior
+        and then send the logs to the appropriate bug-reporting place.
+
+        Arguments:
+          val -- a boolean value determining whether debugging
+                 is switched on or off
+          scope -- see the documentation of this class.
+        
+        """
+        assert isinstance(val, bool)
+        if val == True:
+            ssip_val = "ON"
+        else:
+            ssip_val = "OFF"
+
+        self._conn.send_command('SET', scope.ALL, 'DEBUG', ssip_val)
+
+
+    def set_debug_destination(self, path):
+        """Set debug destination.
+
+        Arguments:
+          path -- path (string) to the directory where debuging
+                  files will be created
+          scope -- see the documentation of this class.
+        
+        """
+        assert isinstance(val, string)
+
+        self._conn.send_command('SET', scope.ALL, 'DEBUG_DESTINATION', val)
+
+    def block_begin(self):
+        """Begin an SSIP block.
+
+        See SSIP documentation for more details about blocks.
+
+        """
+        self._conn.send_command('BLOCK', 'BEGIN')
+
+    def block_end(self):
+        """Close an SSIP block.
+
+        See SSIP documentation for more details about blocks.
+
+        """
+        self._conn.send_command('BLOCK', 'END')
+
+    def close(self):
+        """Close the connection to Speech Dispatcher."""
+        if hasattr(self, '_conn'):
+            self._conn.close()
+            del self._conn
+
+
+class Client(SSIPClient):
+    """A DEPRECATED backwards-compatible API.
+
+    This Class is provided only for backwards compatibility with the prevoius
+    unofficial API.  It will be removed in future versions.  Please use either
+    'SSIPClient' or 'Speaker' interface instead.  As deprecated, the API is no
+    longer documented.
+
+    """
+    def __init__(self, name=None, client=None, **kwargs):
+        name = name or client or 'python'
+        super(Client, self).__init__(name, **kwargs)
+        
+    def say(self, text, priority=Priority.MESSAGE):
+        self.set_priority(priority)
+        self.speak(text)
+
+    def char(self, char, priority=Priority.TEXT):
+        self.set_priority(priority)
+        super(Client, self).char(char)
+
+    def key(self, key, priority=Priority.TEXT):
+        self.set_priority(priority)
+        super(Client, self).key(key)
+
+    def sound_icon(self, sound_icon, priority=Priority.TEXT):
+        self.set_priority(priority)
+        super(Client, self).sound_icon(sound_icon)
+        
+
+class Speaker(SSIPClient):
+    """Extended Speech Dispatcher Interface.
+
+    This class provides an extended intercace to Speech Dispatcher
+    functionality and tries to hide most of the lower level details of SSIP
+    (such as a more sophisticated handling of blocks and priorities and
+    advanced event notifications) under a more convenient API.
+    
+    Please note that the API is not yet stabilized and thus is subject to
+    change!  Please contact the authors if you plan using it and/or if you have
+    any suggestions.
+
+    Well, in fact this class is currently not implemented at all.  It is just a
+    draft.  The intention is to hide the SSIP details and provide a generic
+    interface practical for screen readers.
+    
+    """
+
+
+# Deprecated but retained for backwards compatibility
+
+# This class was introduced in 0.7 but later renamed to CommunicationMethod
+class ConnectionMethod(object):
+    """Constants describing the possible methods of connection to server.
+
+    Retained for backwards compatibility but DEPRECATED. See 
CommunicationMethod."""
+    UNIX_SOCKET = 'unix_socket'
+    """Unix socket communication using a filesystem path"""
+    INET_SOCKET = 'inet_socket'
+    """Inet socket communication using a host and port"""
diff --git a/src/api/python/speechd/paths.py.in 
b/src/api/python/speechd/paths.py.in
new file mode 100644
index 0000000..a2a9696
--- /dev/null
+++ b/src/api/python/speechd/paths.py.in
@@ -0,0 +1 @@
+SPD_SPAWN_CMD = "@bindir@/speech-dispatcher"
diff --git a/src/api/python/speechd_config/Makefile.am 
b/src/api/python/speechd_config/Makefile.am
new file mode 100644
index 0000000..8b57ad8
--- /dev/null
+++ b/src/api/python/speechd_config/Makefile.am
@@ -0,0 +1,27 @@
+## Process this file with automake to produce Makefile.in
+
+dist_snddata_DATA = test.wav
+
+dist_bin_SCRIPTS = spd-conf
+
+speechd_pythondir = $(pyexecdir)/speechd_config
+speechd_python_PYTHON = __init__.py config.py
+nodist_speechd_python_PYTHON = paths.py
+
+paths_edit = sed \
+       -e "s:address@hidden@]:$(spdconforigdir):" \
+       -e "s:address@hidden@]:$(spdconfdir):" \
+       -e "s:address@hidden@]:$(snddatadir):" \
+       -e "s:address@hidden@]:$(spddesktopconforigdir):"
+
+paths.py: Makefile
+       rm -f $@
+       srcdir=; \
+       test -f ./address@hidden || srcdir=$(srcdir)/; \
+       $(paths_edit) address@hidden > $@
+
+paths.py: $(srcdir)/paths.py.in
+
+CLEANFILES = paths.py
+
+EXTRA_DIST = paths.py.in
diff --git a/src/api/python/speechd_config/__init__.py 
b/src/api/python/speechd_config/__init__.py
new file mode 100644
index 0000000..6f7eef9
--- /dev/null
+++ b/src/api/python/speechd_config/__init__.py
@@ -0,0 +1,18 @@
+# Copyright (C) 2008 Brailcom, o.p.s.
+#
+# 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 of the License, 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+from config import *
+
diff --git a/src/api/python/speechd_config/config.py 
b/src/api/python/speechd_config/config.py
new file mode 100644
index 0000000..26bdccd
--- /dev/null
+++ b/src/api/python/speechd_config/config.py
@@ -0,0 +1,924 @@
+# config.py - A simple dialog based tool for basic configuration of
+#             Speech Dispatcher and problem diagnostics.
+#
+# Copyright (C) 2008, 2010 Brailcom, o.p.s.
+#
+# 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 of the License, 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+import sys
+import os
+import shutil
+import fileinput
+import socket
+import time
+import datetime
+
+from optparse import OptionParser
+
+# Configuration and sound data paths
+import paths
+
+def report(msg):
+    """Output information messages for the user on stdout
+    and if desired, by espeak synthesis"""
+    print msg
+    if options.use_espeak_synthesis:
+        os.system("espeak \"" + msg + "\"")
+
+def input_audio_icon():
+    """Produce a sound for the event 'input requested' used in question()"""
+    if options.use_espeak_synthesis:
+        os.system("espeak \"Type in\"")
+
+def question(text, default):
+    """Ask a simple question and suggest the default value"""
+
+    while 1:
+        if isinstance(default, bool):
+            if default == True:
+                default_str = "yes"
+            else:
+                default_str = "no"
+        else:
+            default_str = str(default)
+        report(text + " ["+default_str+"] :")
+        input_audio_icon()
+
+        if not options.dont_ask:
+            str_inp = raw_input(">") 
+
+        # On plain enter, return default
+        if options.dont_ask or (len(str_inp) == 0):
+            return default
+        # If a value was typed, check it and convert it
+        elif isinstance(default, bool):
+            if str_inp in ["yes","y", "Y", "true","t", "1"]:
+                return True
+            elif str_inp in ["no", "n", "N", "false", "f", "0"]:
+                return False
+            else:
+                report ("Unknown answer (type 'yes' or 'no')")
+                continue
+        elif isinstance(default, int):
+            return int(str_inp)
+        elif isinstance(default, str):
+            return str_inp
+        else:
+            raise TypeError("Invalid type for the default value")
+
+def question_with_suggested_answers(text, default, suggest):
+    """Ask a question with suggested answers. If the answer typed is not
+    in 'suggest', the user is notified and given an opportunity to correct
+    his choice"""
+    
+    reply = question(text, default)
+    while reply not in suggest:
+        report("""The value you have chosen is not among the suggested values.
+You have chosen '%s'.""" % reply)
+        report("The suggested values are " + str(suggest))
+        correct = question("Do you want to correct your answer?", True)
+        if correct == True:
+            reply = question(text, default)
+        else:
+            return reply
+    return reply
+
+def question_with_required_answers(text, default, required):
+    """Ask a question and repeat it until the answer typed in is in 
'required'"""
+    
+    reply = question(text, default)
+    while reply not in required:
+        report("You have chosen '%s'. Please choose one of %s" % (reply, 
str(required)))
+        reply = question(text, default)
+    return reply
+
+class Options(object):
+    """Configuration for spdconf"""
+
+    _conf_options = \
+        {
+        'create_user_configuration':
+            {
+            'descr' : "Create Speech Dispatcher configuration for the given 
user",
+            'doc' : None,
+            'type' : bool,
+            'default' : False,
+            'command_line' : ('-u', '--create-user-conf'),
+            },
+        'config_basic_settings_user':
+            {
+            'descr' : "Configure basic settings in user configuration",
+            'doc' : None,
+            'type' : bool,
+            'default' : False,
+            'command_line' : ('-c', '--config-basic-settings-user'),
+            },
+        'config_basic_settings_system':
+            {
+            'descr' : "Configure basic settings in system-wide configuration",
+            'doc' : None,
+            'type' : bool,
+            'default' : False,
+            'command_line' : ('-C', '--config-basic-settings-system'),
+            },
+        'diagnostics':
+            {
+            'descr' : "Diagnose problems with the current setup",
+            'doc' : None,
+            'type' : bool,
+            'default' : False,
+            'command_line' : ('-d', '--diagnostics'),
+            },
+        'test_spd_say':
+            {
+            'descr' : "Test connection to Speech Dispatcher using spd-say",
+            'doc' : None,
+            'type' : bool,
+            'default' : False,
+            'command_line' : ('-s', '--test-spd-say'),
+            },
+        'test_festival':
+            {
+            'descr' : "Test whether Festival works as a server",
+            'doc' : None,
+            'type' : bool,
+            'default' : False,
+            'command_line' : ('', '--test-festival'),
+            },
+        'test_espeak':
+            {
+            'descr' : "Test whether Espeak works as a standalone binary",
+            'doc' : None,
+            'type' : bool,
+            'default' : False,
+            'command_line' : ('', '--test-espeak'),
+            },
+        'test_alsa':
+            {
+            'descr' : "Test ALSA audio",
+            'doc' : None,
+            'type' : bool,
+            'default' : False,
+            'command_line' : ('', '--test-alsa'),
+            },
+
+        'test_pulse':
+            {
+            'descr' : "Test Pulse Audio",
+            'doc' : None,
+            'type' : bool,
+            'default' : False,
+            'command_line' : ('', '--test-pulse'),
+            },
+
+        'use_espeak_synthesis':
+            {
+            'descr' : "Use espeak to synthesize messages",
+            'doc' : None,
+            'type' : bool,
+            'default' : False,
+            'command_line' : ('-e', '--espeak'),
+            },
+        'dont_ask':
+            {
+            'descr' : "Do not ask any questions, allways use default values",
+            'doc' : None,
+            'type' : bool,
+            'default' : False,
+            'command_line' : ('-n', '--dont-ask'),
+            },
+        'debug':
+            {
+            'descr' : "Debug a problem and generate a report",
+            'doc' : None,
+            'type' : bool,
+            'default' : False,
+            'command_line' : ('-D', '--debug'),
+            },
+        }
+
+    def __init__(self):
+        usage = """%prog [options]
+A simple dialog based tool for basic configuration of Speech Dispatcher
+and problem diagnostics."""
+        self.cmdline_parser = OptionParser(usage)
+
+        for option, definition in self._conf_options.iteritems():
+            # Set object attributes to default values
+            def_val = definition.get('default', None)
+            setattr(self, option, def_val)
+            
+            # Fill in the cmdline_parser object
+            if definition.has_key('command_line'):
+                descr = definition.get('descr', None)                
+                type = definition.get('type', None)
+                
+                if definition.has_key('arg_map'):
+                    type, map = definition['arg_map']
+                if type == str:
+                    type_str = 'string'
+                elif type == int:
+                    type_str = 'int'
+                elif type == float:
+                    type_str = 'float'
+                elif type == bool:
+                    type_str = None
+                else:
+                    raise TypeError("Unknown type")
+                
+                if type != bool:
+                    self.cmdline_parser.add_option(type=type_str, dest=option,
+                                                   help=descr,
+                                                   *definition['command_line'])
+                else: # type == bool
+                    self.cmdline_parser.add_option(action="store_true", 
dest=option,
+                                                   help=descr,
+                                                   *definition['command_line'])
+            
+        # Set options according to command line flags
+        (cmdline_options, args) = self.cmdline_parser.parse_args()
+
+        for option, definition in self._conf_options.iteritems():
+                val = getattr(cmdline_options, option, None)
+                if val != None:
+                    if definition.has_key('arg_map'):
+                        former_type, map = definition['arg_map']
+                        try:
+                            val = map[val]
+                        except KeyError:
+                            raise ValueError("Invalid option value: "  + 
str(val))
+                        
+                    setattr(self, option, val)
+        
+        #if len(args) != 0:
+           # raise ValueError("This command takes no positional arguments 
(without - or -- prefix)")
+
+class Tests:
+    """Tests of functionality of Speech Dispatcher and its dependencies
+    and methods for determination of proper paths"""
+
+    def __init__(self):
+        self.festival_socket = None
+
+    def user_speechd_dir(self):
+        """Return user Speech Dispatcher configuration and logging directory"""
+        return os.path.expanduser(os.path.join('~', '.speech-dispatcher'))
+
+    def user_speechd_dir_exists(self):
+        """Determine whether user speechd directory exists"""
+        return os.path.exists(self.user_speechd_dir())
+
+    def user_conf_dir(self):
+        """Return user configuration directory"""
+        return os.path.join(self.user_speechd_dir(), "conf")
+
+    def system_conf_dir(self):
+        """Determine system configuration directory"""
+        return paths.SPD_CONF_PATH
+
+    def user_conf_dir_exists(self):
+        """Determine whether user configuration directory exists"""
+        return os.path.exists(self.user_conf_dir())
+
+    def festival_connect(self, host="localhost", port=1314):
+        """
+        Try to connect to festival and determine whether it is possible.
+        On success self.festival_socket is initialized with the openned socket.
+        """
+        self.festival_socket = socket.socket(socket.AF_INET, 
socket.SOCK_STREAM)
+        try:
+            self.festival_socket.connect((socket.gethostbyname(host), port))
+        except socket.error, (num, reson):
+            report("""ERROR: It was not possible to connect to Festival on the
+given host and port. Connection failed with error %d : %s .""" % (num, reson))
+            report("""Hint: Most likely, your Festival server is not running 
now
+or not at the default port %d.
+
+Try /etc/init.d/festival start or run 'festival --server' from the command 
line.""" % port)
+            return False
+        return True
+        
+    def festival_with_freebsoft_utils(self):
+        """Test whether festival works and contains working 
festival-freebsoft-utils.
+        """
+        if not self.festival_socket:
+            if not self.festival_connect():
+                return False
+        self.festival_socket.send("(require 'speech-dispatcher)\n")
+        reply = self.festival_socket.recv(1024)
+        if "LP" in reply:
+            report("Festival contains freebsoft-utils.")
+            return True
+        else:
+            report("""ERROR: Your Festival server is working but it doesn't 
seem
+to load festival-freebsoft-utils. You need to install festival-freebsoft-utils
+to be able to use Festival with Speech Dispatcher.""")
+            return False
+
+    def python_speechd_in_path(self):
+        """Try whether python speechd library is importable"""
+        try:
+            import speechd
+        except:
+            report("""Python can't find the Speech Dispatcher library.
+Is it installed? This won't prevent Speech Dispatcher to work, but no
+Python applications like Orca will be able to use it.
+Search for package like python-speechd, download and install it""")
+            return False
+        return True
+
+    def audio_try_play(self, type):
+        """Try to play a sound through the standard playback utility for the
+        given audio method."""
+        wavfile = os.path.join(paths.SPD_SOUND_DATA_PATH,"test.wav")
+
+        if type == 'alsa':
+            cmd = "aplay" + " " + wavfile
+        elif type == 'pulse':
+            cmd = "paplay" + " " + wavfile
+        else:
+            raise NotImplementedError("Test for this audio system is not 
implemented")
+
+        try:
+            ret = os.system(cmd)
+        except:
+            report("""Can't execute the %s command, this audio output might 
not be available
+on your system, but it might also be a false warning. Please make
+sure your audio is working.""")
+            reply = question("Are you sure that %s audio is working?" % type, 
False)
+            return reply
+    
+        if ret:
+            report("Can't play audio via\n     %s" % cmd)
+            report("""Your audio doesn't seem to work, please fix audio first 
or choose
+a different method.""")
+            return False
+
+
+        reply = question("Did you hear the sound?", True)
+        
+        if not reply:
+            report("""Please examine the above output from the sound playback
+utility. If everything seems right, are you sure your audio is loud enough and
+not muted in the mixer? Please fix your audio system first or choose a 
different
+audio output method in configuration.""")
+            return False
+        else:
+            report("Audio output '%s' works" % type)
+            return True
+
+    def test_spd_say(self):
+        """Test Speech Dispatcher using spd_say"""
+
+        report("Testing Speech Dispatcher using spd_say")
+        
+        while True:
+            try:
+                ret = os.system("spd-say -P important \"Speech Dispatcher 
works\"")
+            except:
+                report("""Can't execute the spd-say binary,
+it is very likely that Speech Dispatcher is not installed.""")
+                return False
+            hearing_test = question("Did you hear the message about Speech 
Dispatcher working?", True)
+            if hearing_test:
+                report("Speech Dispatcher is installed and working!")
+                return True
+            else:
+                report("Speech Dispatcher is installed but there is some 
problem")
+                return False
+
+    def test_festival(self):
+        """Test whether Festival works as a server"""
+        report("Testing whether Festival works as a server")
+
+        ret = self.festival_with_freebsoft_utils()
+        if not ret:
+            report("Festival server is not working.")
+            return False
+        else:
+            report("Festival server seems to work correctly")
+            return True
+
+    def test_espeak(self):
+        """Test the espeak utility"""
+
+        report("Testing whether Espeak works")
+        
+        while True:
+            try:
+                os.system("espeak \"Espeak seems to work\"")
+            except:
+                report("""Can't execute the espeak binary, it is likely that 
espeak
+is not installed.""")
+                return False
+
+            report("Espeak is installed")
+            return True
+
+    def test_alsa(self):
+        """Test ALSA sound output"""
+        report("Testing ALSA sound output")
+        return self.audio_try_play(type='alsa')
+
+    def test_pulse(self):
+        """Test Pulse Audio sound output"""
+        report("Testing PULSE sound output")
+        return self.audio_try_play(type='pulse')
+
+    def diagnostics(self, speechd_running = True, output_modules=[], 
audio_output=[]):
+
+        """Perform a complete diagnostics"""
+        working_modules = []
+        working_audio = []
+
+        if speechd_running:
+            # Test whether Speech Dispatcher works
+            if self.test_spd_say():
+                spd_say_working = True
+                skip = question("Speech Dispatcher works. Do you want to skip 
other tests?",
+                                True)
+                if skip:
+                    return {'spd_say_working': True}
+            else:
+                spd_say_working = False
+        else:
+            spd_say_working = False
+
+        if not spd_say_working:
+            if not question("""
+Speech Dispatcher isn't running or we can't connect to it (see above),
+do you want to proceed with other tests? (They can help to determine
+what is wrong)""", True):
+                return {'spd_say_working': False}
+
+        def decide_to_test(identifier, name, listing):
+            """"Ask the user whether to test a specific capability"""
+            if ((identifier in listing)
+                or (not len(listing)
+                    and question("Do you want to test the %s now?" % name, 
True))):
+                return True
+            else:
+                return False
+
+        if decide_to_test('festival', "Festival synthesizer", output_modules): 
+            if self.test_festival():
+                working_modules += ["festival"]
+
+        if decide_to_test('espeak', "Espeak synthesizer", output_modules): 
+            if self.test_espeak():
+                working_modules += ["espeak"]
+
+        if decide_to_test('alsa', "ALSA sound system", audio_output): 
+            if self.test_alsa():
+                working_audio += ["alsa"]
+
+        if decide_to_test('pulse', "Pulse Audio sound system", audio_output): 
+            if self.test_pulse():
+                working_audio += ["pulse"]
+
+        report("Testing whether Python Speech Dispatcher library is in path 
and importable")
+        python_speechd_working = test.python_speechd_in_path()
+        
+        return  {'spd_say_working': spd_say_working,
+                 'audio': working_audio,
+                 'synthesizers': working_modules,
+                 'python_speechd' : python_speechd_working}
+
+    def write_diagnostics_results(self, results):
+        """Write out diagnostics results using report()"""
+
+        report("""
+
+Diagnostics results:""")
+        if results.has_key('spd_say_working'):
+            if results['spd_say_working']:
+                report("Speech Dispatcher is working")
+            else:
+                report("Speech Dispatcher not working through spd-say")
+        if results.has_key('synthesizers'):
+            report("Synthesizers that were tested and seem to work: %s" %
+                   str(results['synthesizers']))
+        if results.has_key('audio'):
+            report("Audio systems that were tested and seem to work: %s" %
+                   str(results['audio']))
+        if results.has_key('python_speechd'):
+            if(results['python_speechd']):
+                report("Python Speech Dispatcher module is importable")
+            else:
+                report("""Python Speech Dispatcher module not importable.
+Either not installed or not in path.""")
+        report("End of diagnostics results")
+
+    def user_configuration_seems_complete(self):
+        """Decide if the user configuration seems reasonably complete"""
+        if not os.path.exists(os.path.join(self.user_conf_dir(), 
"speechd.conf")):
+            return False
+
+        if not len(os.listdir(self.user_conf_dir())) > 2:
+            return False
+
+        if not os.path.exists(os.path.join(self.user_conf_dir(), "modules")):
+            return False
+
+        if not os.path.exists(os.path.join(self.user_conf_dir(), "clients")):
+            return False
+
+        return True
+
+    def debug_and_report(self, type = None):
+        """Start Speech Dispatcher in debugging mode, collect the debugging 
output
+        and offer to send it to the developers"""
+
+        report("Starting collecting debugging output, configuration and 
logfiles")
+
+        if not type:
+            type = question_with_required_answers("""
+Do you want to debug 'system' or  'user' Speech Dispatcher?""",
+                                                  'user', ['user', 'system'])
+
+        # Try to kill running Speech Dispatcher
+        reply = question("""It is necessary to kill the currently running 
Speech Dispatcher
+processes. Do you want to do it now?""", True)
+        if reply:
+            os.system("killall speech-dispatcher")
+        else:
+            report("""
+You decided not to kill running Speech Dispatcher processes.
+Please make sure your Speech Dispatcher is not running now.""")
+            reply = question("Is your Speech Dispatcher not running now?", 
True)
+            if not reply:
+                report("Can't continue, please stop your Speech Dispatcher and 
try again")
+
+        time.sleep(2)
+
+        # All debugging files are written to TMPDIR/speech-dispatcher/
+        if os.environ.has_key('TMPDIR'):
+            tmpdir = os.environ['TMPDIR']
+        else:
+            tmpdir = "/tmp/"
+        debugdir_path = os.path.join(tmpdir, "speechd-debug")
+        date = datetime.date.today()
+        debugarchive_path = os.path.join(tmpdir, 
"speechd-debug-%d-%d-%d.tar.gz" %
+                                         (date.day, date.month, date.year))
+
+        # Start Speech Dispatcher with debugging enabled
+        if type == 'user':
+            report("Speech Dispatcher will be started now in debugging mode")
+            speechd_started = not os.system("speech-dispatcher -D")
+            configure_directory = test.user_conf_dir()
+        else:
+            report("Warning: You must be root or under sudo to do this.")      
  
+            report("""
+Please start your system Speech Dispatcher now with parameter '-D'""")
+            reply = question("Is your Speech Dispatcher running now?", True)
+            if reply:
+                speechd_started = True
+            else:
+                report("Can't continue")
+            configure_directory = test.system_conf_dir()
+        time.sleep(2)
+
+        if not speechd_started:
+            reply = question("Speech Dispatcher failed to start, continuing 
anyway")
+
+        report("Trying to speak some messages")
+        ret = os.system("spd-say \"Speech Dispatcher debugging 1\"")
+        if not ret:
+            os.system("spd-say \"Speech Dispatcher debugging 2\"")
+            os.system("spd-say \"Speech Dispatcher debugging 3\"")
+        else:
+            report("Can't test Speech Dispatcher connection, can't connect")
+
+        report("Please wait (about 5 seconds)")
+        time.sleep(5)
+
+        report("Collecting debugging output and your configuration 
information") 
+
+        os.system("umask 077")
+        os.system("tar -cz %s %s > %s" % 
+                  (debugdir_path, configure_directory, debugarchive_path))   
+        os.system("killall speech-dispatcher")
+        os.system("rm -rf %s" % debugdir_path)
+
+        report("""
+Please send %s to speechd at bugs.freebsoft.org with
+a short description of what you did. We will get in touch with you soon
+and suggest a solution.""" % debugarchive_path)
+        
+test = Tests()
+
+class Configure:
+
+    """Setup user configuration and/or set basic options in user/system 
configuration"""
+
+    default_output_module = None
+    default_language = None
+    default_audio_method = None
+    
+    def remove_user_configuration(self):
+        """Remove user configuration tree"""
+        shutil.rmtree(test.user_conf_dir())
+
+    def options_substitute(self, configfile, options):
+        """Substitute the given options with given values.
+
+        Arguments:
+        configfile -- the file path of the configuration file as a string
+        options -- a list of tuples (option_name, value)"""
+
+        # Parse config file in-place and replace the desired options+values
+        for line in fileinput.input(configfile, inplace=True, backup=".bak"):
+            # Check if the current line contains any of the desired options
+            for opt, value in options.iteritems():
+                if opt in line:
+                    # Now count unknown words and try to judge if this is
+                    # real configuration or just a comment
+                    unknown = 0
+                    for word in line.split():
+                        if word =='#' or word == '\t':
+                            continue
+                        elif word == opt:
+                            # If a foreign word went before our option 
identifier,
+                            # we are not in code but in comments
+                            if unknown != 0:
+                                unknown = 2
+                                break
+                        else:
+                            unknown += 1
+
+                    # Only consider the line as the actual code when the 
keyword
+                    # is followed by exactly one word value. Otherwise 
consider this
+                    # line as plain comment and leave intact
+                    if unknown == 1:
+                        # Convert value into string representation in spd_val
+                        if isinstance(value, bool):
+                            if value == True:
+                                spd_val = "1"
+                            elif value == False:
+                                spd_val = "2"
+                        elif isinstance(value, int):
+                            spd_val = str(value)
+                        else:
+                            spd_val = str(value)
+                            
+                        print opt + "   " + spd_val
+                        break
+            
+            else:
+                print line,
+                
+    def create_user_configuration(self):
+        """Create user configuration in the standard location"""
+
+        # Ask before touching things that we do not have to!
+        if test.user_speechd_dir_exists():
+            if test.user_conf_dir_exists():
+                if test.user_configuration_seems_complete():
+                    reply = question(
+                        """User configuration already exists.
+Do you want to rewrite it with a new one?""", False)
+                    if reply == False:
+                        report("Keeping configuration intact and continuing 
with settings.")
+                        return
+                    else:
+                        self.remove_user_configuration()
+                else:
+                    reply = question(
+                        """User configuration already exists, but it seems to 
be incomplete.
+Do you want to keep it?""", False)
+                    if reply == False:
+                        self.remove_user_configuration()
+                    else:
+                        report("Keeping configuration intact and aborting.")
+                        return
+
+            # TODO: Check for permissions on logfiles and pid
+        else:
+            report("Creating " + test.user_speechd_dir())
+            os.mkdir(test.user_speechd_dir())
+
+        # Copy the original intact configuration files
+        # creating a conf/ subdirectory
+        shutil.copytree(paths.SPD_CONF_ORIG_PATH, test.user_conf_dir())
+        
+        report("User configuration created in %s" % test.user_conf_dir())
+
+    def configure_basic_settings(self, type='user'):
+        """Ask for basic settings and rewrite them in the configuration file"""
+
+        if type == 'user':
+            report("Configuring user settings for Speech Dispatcher")
+        elif type == 'system':
+            report("Warning: You must be root or under sudo to do this.")
+            report("Configuring system settings for Speech Dispatcher")
+        else:
+            raise ValueError("Invalid configuration type")
+
+        # Now determine the most important config option
+        self.default_output_module = question_with_suggested_answers(
+            "Default output module",
+            "espeak",
+            ["espeak", "flite", "festival", "cicero", "ibmtts"])
+
+        self.default_language = question(
+            "Default language (two-letter iso language code like \"en\" or 
\"cs\")",
+            "en")
+
+        self.default_audio_method = question_with_suggested_answers(
+            "Default audio output method",
+            "pulse",
+            ["pulse", "alsa", "oss", "pulse,alsa"])
+
+        self.default_speech_rate = question(
+            "Default speech rate (on the scale of -100..100, 0 is default, 50 
is faster, -50 is slower)",
+            "0")
+
+        self.default_speech_pitch = question(
+            "Default speech pitch (on the scale of -100..100, 0 is default, 50 
is higher, -50 is lower)",
+            "0")
+    
+        # Substitute given configuration options
+        if type == 'user':
+            configfile = os.path.join(test.user_conf_dir(), "speechd.conf")
+        elif type == 'system':
+            configfile = os.path.join(test.system_conf_dir(), "speechd.conf")
+
+        self.options_substitute(configfile, 
+                                {"DefaultModule": self.default_output_module,
+                                 "DefaultLanguage": self.default_language,
+                                 "AudioOutputMethod": 
self.default_audio_method,
+                                 "DefaultRate": self.default_speech_rate,
+                                 "DefaultPitch": self.default_speech_pitch,
+                                 "DefaultLanguage": self.default_language,
+                                 })
+        if type == 'user':
+            self.setup_autostart = question(
+                """Do you want to have Speech Dispatcher automatically started 
from ~/.config/autostart ?
+This is usually not necessary, most applications will start Speech Dispatcher 
automatically.""",
+                False)
+            if self.setup_autostart:
+                os.system("""cp %s ~/.config/autostart/""" % 
os.path.join(paths.SPD_DESKTOP_CONF_PATH,
+                                                                          
"speechd.desktop")) 
+                         
+                report("""
+Configuration written to %s
+Basic configuration now complete. You might still need to fine tune it by
+manually editing the configuration file above. Especially if you need to
+use special audio settings, non-standard synthesizer ports etc.""" % 
configfile)
+
+    def speechd_start_user(self):
+        """Start Speech Dispatcher in user-mode"""
+
+        report("Starting Speech Dispatcher in user-mode")
+
+        err = os.system("speech-dispatcher")
+        if err:
+            report("Can't start Speech Dispatcher. Exited with status %d" % 
err)
+            reply = question("""Perhaps this is because your Speech Dispatcher 
is already running.
+Do you want to kill all running Speech Dispatchers and try again?""", True)
+            if reply:
+                os.system("killall speech-dispatcher")
+                err = os.system("speech-dispatcher")
+                if err:
+                    report("Can't start Speech Dispatcher")
+                    return False
+            else:
+                return False
+        return True
+
+    def speechd_start_system(self):
+        """Start Speech Dispatcher in system-mode"""
+
+        report("Warning: You must be root or under sudo to do this.")        
+        report("Starting Speech Dispatcher in system-mode")
+        
+        reply = question("Is your system using an 
/etc/init.d/speech-dispatcher script?",
+                         True)
+        if reply:
+            report("Stopping Speech Dispatcher in case any is running already")
+            os.system("/etc/init.d/speech-dispatcher stop") 
+            report("Starting Speech Dispatcher via 
/etc/init.d/speech-dispatcher")
+            ret = os.system("/etc/init.d/speech-dispatcher start")
+            if ret:
+                report("Can't start Speech Dispatcher. Exited with status %d" 
% ret)
+                return False
+        else:
+            report("""Do not know how to start system Speech Dispatcher,
+you have to start it manually to continue.""")
+            reply = question("Have you started Speech Dispatcher now?", True)
+            if not reply:
+                report("Can't continue")
+                return False
+        return True
+
+    def complete_config(self):
+        """Create a complete configuration, run diagnosis and if necessary, 
debugging"""
+
+        speechd_type = question_with_required_answers(
+            "Do you want to create/setup a 'user' or 'system' configuration",
+            'user', ['user', 'system'])
+
+        if speechd_type == 'user':
+            self.create_user_configuration()
+            self.configure_basic_settings(type='user')
+        elif speechd_type == 'system':
+            self.configure_basic_settings(type='system')
+        else:
+            raise ValueError("Invalid configuration type")
+
+        reply = question("Do you want to start/restart Speech Dispatcher now 
and run some tests?", True)
+        if not reply:
+            report("Your configuration is now done but not tested")
+            return
+        else:
+            if speechd_type == 'user':
+                started = self.speechd_start_user()
+            elif speechd_type == 'system':
+                started = self.speechd_start_system()
+
+        if not started:
+            report("Your Speech Dispatcher is not running")
+            
+        result = test.diagnostics(speechd_running = started,
+                                  audio_output=[self.default_audio_method],
+                                  output_modules=[self.default_output_module])
+        test.write_diagnostics_results(result)
+
+        if not started:
+            reply = question("Do you want to run debugging now and send a 
request for help to the developers?",
+                             False)
+            if reply:
+                test.debug_and_report(type=speechd_type)
+
+
+# Basic objects
+options = Options()
+configure = Configure()
+test = Tests()
+
+
+def main():
+
+    report("\nSpeech Dispatcher configuration tool\n")
+    
+    if options.create_user_configuration:
+        # Check for and/or create basic user configuration
+        configure.create_user_configuration()
+        reply = question("Do you want to continue with basic settings?", True)
+        if reply:
+            configure.configure_basic_settings(type='user')
+    elif options.config_basic_settings_user:
+        configure.configure_basic_settings(type='user')
+
+    elif options.config_basic_settings_system:
+        configure.configure_basic_settings(type='system')
+
+    elif options.test_festival:
+        test.test_festival()
+
+    elif options.test_spd_say:
+        test.test_spd_say()
+
+    elif options.test_espeak:
+        test.test_espeak()
+
+    elif options.test_alsa:
+        test.audio_try_play(type='alsa')
+
+    elif options.test_pulse:
+        test.audio_try_play(type='pulse')
+
+    elif options.diagnostics:
+        ret = test.diagnostics()
+        test.write_diagnostics_results(ret)
+
+    elif options.debug:
+        test.debug_and_report()
+
+    else:
+        reply = question("Do you want to setup a completely new 
configuration?", True)
+        if reply:
+            configure.complete_config()
+        else:
+            reply = question("Do you want to run diagnosis of problems?", True)
+            if reply:
+                ret=test.diagnostics()
+                test.write_diagnostics_results(ret)
+            else:
+                report("""Please run this command again and select what you 
want to do
+or read the quick help available through '-h' or '--help'.""")
+
+if __name__ == "__main__":
+    sys.exit(main())
diff --git a/src/api/python/speechd_config/paths.py.in 
b/src/api/python/speechd_config/paths.py.in
new file mode 100644
index 0000000..326e954
--- /dev/null
+++ b/src/api/python/speechd_config/paths.py.in
@@ -0,0 +1,4 @@
+SPD_CONF_ORIG_PATH="@spdconforigdir@"
+SPD_CONF_PATH="@spdconfdir@"
+SPD_SOUND_DATA_PATH="@snddatadir@"
+SPD_DESKTOP_CONF_PATH="@spddesktopconforigdir@"
diff --git a/src/api/python/speechd_config/spd-conf 
b/src/api/python/speechd_config/spd-conf
new file mode 100644
index 0000000..3cc90b5
--- /dev/null
+++ b/src/api/python/speechd_config/spd-conf
@@ -0,0 +1,10 @@
+#!/usr/bin/python
+
+# Helper script to be put in /usr/bin/ or a similar location
+# calling the appropriate python tool
+
+import speechd_config
+
+if __name__=='__main__':
+    import sys
+    sys.exit(speechd_config.main())
diff --git a/src/api/python/speechd_config/speechd.desktop 
b/src/api/python/speechd_config/speechd.desktop
new file mode 100644
index 0000000..4a9e8d5
--- /dev/null
+++ b/src/api/python/speechd_config/speechd.desktop
@@ -0,0 +1,11 @@
+
+[Desktop Entry]
+Type=Application
+Encoding=UTF-8
+Version=1.0
+Name=Speech Dispatcher
+Comment=Interface to Text to Speech services
+TryExec=speech-dispatcher
+Exec=speech-dispatcher
+X-GNOME-Autostart-enabled=true
+X-GNOME-Autostart-Phase=Initialization
diff --git a/src/api/python/speechd_config/test.wav 
b/src/api/python/speechd_config/test.wav
new file mode 100644
index 
0000000000000000000000000000000000000000..1c49b4abdd29f5dab872f96691d2c67d2ecb545a
GIT binary patch
literal 17410
zcmW+;1$0wO*PXc%Ph*u-ptQKVJLTa#+~MKw?(XjHZVz{VxVu|{QmS!J?wy(ceE-T?
z2}yJB%pBQ!pEDEMH*eA;l7>*1hMoT!G;address@hidden;d
zM@>--UBvZf>BPkqr;TwF+ at Ji#9U$Y`DSS;{jr*b%Xa`Qi%XL?kry|P8NcW=rx1k{U
zN(SiSqUvyQxRk=k*`&VcJHLo+l1t(5^2x9$)X_aOIyEDd=lOX7s~dSr1QdZ*!CrJd
zJuU4BRUpsR)address@hidden<uth<H6`gsb}L}2p^PD%2LE6uVb}YD8Pc%
z&@)v at qtP^5KbtEaYGi+$?ar^|`V?w`dkN2R0W?v#N?tpUd*=A|=b_yGwlTRj+d<q!
zzr at fpxn!|HF$?s5!yMHGVUzN-da_Ue?ZuDyx4KrQ6~=Yy015g$*(-jLUmvsA2PX2*
z^~%^KF+}%R>TCNa=U!$obF59{9_M~3*_Fc-&7w{gJen}scs_c(;SVNgfuLtUf~O+0
z!zbxZZMOcUCY5g|&C5^wHv9XjjB|DkHR)eiJ0up4<address@hidden&R;`Zat|GfYBEul1F
zo4UScTEgJMEn;7r%UNXcC at RO77fRFjk;0Lg{t5J!`hu>jYA|;*oR+!cWAD$;e>Qb)
z!40A<1^+HkJ?0L!x*q4I{Q3B2hrOQXxVu?oyke=MU(|+_1<8}l529nEzM>esPtind
z$EKih(wxW#p}uCRY88s31AJY6Pxw_n`=~QTKB9dSKOkv}^^^W*xVH0weX*^tbDr<G
zx2X3SdB)lKr7>et8^(?`{ADP`m61NNX5uHjn8lED{;6^sMYh^5&Se86v;E|+F&Vw{
z_65dspN#brM<lec?By=HFWHUuCHd!^&%KMB0k4QkaJ97i3k6b=V)A0nM8%;`q$J-~
zn8gGZ4o?o3<5E at e+Odi}+&BCnuYX3fj2^a}kVklJDUvwN>efl&#m-jtK;AyvEB7du
z(orRRkgKNP;@6g#SfG9E{pcQw1k#!I;EUjnlqVg6ufrMiw(wMRp`&z>zeDcq-#v2A
z`YW<d`bP=gq$sPP8sabGoM5Y!YqZz&=pDOUugD4Rv$lImTH#f(y<*1eTjE5z6F1^-
z5Ra at address@hidden|e?Ivv|fNTWY93*T=LsAuHjA`3-92OL0kgdvi)VX1Mk^
zh6KN%&f>5bUtx7pY^*)Hin=QbvO?llyqKIOKZ7(>7&TTs)!b9PQudL9wj;k$md!m!
zTBB?p{V?7b-%_iMBzxZHM`bO^Y3zJypX}Ns8}KUS{RA#~qot!st=)!3${DN|-;q8h
zv%+V5U&F_7hAN;E)mS_f5OUR-t8D#)6H%uqPu$nU0&xy;N2rFoOz!k7y}h7&zN>!t
z1is3 at Hg!lXU%(#o%raN=0~cZqgu2`?a#JoGIPK4tjtiSq!<7ovblS#Q>rd~jCGNDy
z01=z_#GSUb*O!$4_Fl@@WU|bj`Q!52I%2{H=`pdB^-}V%xa{bLhAHAob_m}TU*gfY
zA88UgAsIMHwLv{ovrsu9GRj^w+v*q^x`!6(m&F{2Zxg3e&JPdpB;@|}`)Kyrd_Mn?
zXO~<N71nPnxG6C<address@hidden>-^B{98+wl1;hEulI!ZjHdZsL<+K<|K$K({v`RaCs
zhH%^UZ_H0)TI+j|#r|W??b%hbi`%npyPWeP9yVAJ8-KS at vUN;MU1K%H3Px~mMK}Ji
zPysazpOLoWXw?tZZS_T^MgGe%G3!8nH($DRR%tb?ur#n_36(;7y~}Jr|HwJTY&G&W
zyS|6_l6{)4N&h9}M5`=0nq%A at HbJZ`Hs`PLTP1g>F}cp)Ri033HSPI&fq!%JvdTMG
z1}>p;x}xU1SZb(&gwPsK<GhkNTkX^AryYGm>2Ss1SaYEX)~Ye at jrEi-*h=oRf^zS8
zLPrGu3Ww=j(W=y`vy{!qWoNIf)44C*&BMjTRJ~;WVkxc|9lq=>WV`vNP;PO%Eq|Kl
zm$a1D)if>eE$LxQ>F9F$AioLSSL{;U6qqndE*q{$=J7q16IHJ?H^h74knLB_SLeXM
zcy>hH*^m at -%Fq^-4^DM=&25)8I{%!lxTAWoz5Jf(O~sQI#oRXkGF(*dWD!(Jv6nwB
z5VR}YIFihW&|KkFI+XviQ=Yjw`uriDpP`d{G3`rJO3WH{SY972<TmH+%s=T2InH>u
zN+*e15w>!P=9saTolzwe<q#FTVmINZaE+)UTjY)05yfid2z9DBG7 at dKWS6q9@)nho
z6=ig5ECr1&ye>S at x7{`}H)yvxemSM!c{$7~8}B8ai#=!2no>2J at f=)5LHV#S1uuxq
zkA!GZ at qnVcs<Wy(s^%rx4Rgo3T!B?sp>`P_SZ=7s$(rB^S9<P{{C>_Wj<Md_QhhR6
zQP`RvUm|*s`IUZxc$&=+`iejJ9zqB5B-~f-z@;gYlvsUE(83J+We>2Q^A?xCi*K}g
z%L2m at ydpf-_tEw=x2+ at 1S=^Nvx+_y=Gn7fJ7~8^f!uU%)7ca(13J0Gr^v4?_$0Jr&
zSlpm!psJ)QgNA!&=e*3#bTtbe!ASkeFxIkEwNS1fjB at wO%gcY|Eam*+ohA(<+Z4~^
z`ozDov^8(j_ZDBU-9j(%C(LjHQAAeDW4HzijZ#uw6$(Vg+Qpooc8hP2{7Ss2eP%9Y
z*oe=D&-?1y+vL4+Tz0N=^$R)V!swOZWWueOka?i-q<SLWiS>#MK2PY5FGt=*O0WcR
zwjx!fQx!vdy;4rEye94y!CUx;YPCUasjpft4-9s2f6eP|OLi at A*6<ybmXQOBk#VoB
zy)9X$M*1 at 1OSVj?EWY7u3d2c>$VqtwS3r at ac%#}WBt(we7vwZ^wD)a-87|X~F`tVX
zh#!Z4_?Fx6<<)kYT)$oGLo&>8ogpEiZp>CQZ|tk?gg0Y{_=JBaG{W~Hjz}G*7kers
z<tHVNE_sLN{><C%ej0p)FRPjwR+_!a4f3?$GI!JbTei`zbmt7;18FbWqd;-htakGP
zlTW7-U$e1-QoO{+2t!Ey$US)iCyAF8=Tr*?bHs0t&OPT??K>mi6#Hr8%<ZF^;!ojd
zf4049{yyh0R~7fIkeXCL{}`6V{})}}e85mfT?enlZ^d)`O`#nA9<fM`m|du&c&*%~
z%wylYpK}N2OKxN6BVMeEM5US!DL2ZygOA(~@@v_TxJtOb_;MgqPALw>?ueUhE@;}J
address@hidden;)lZ0xG<0mrE$sZ at dn=z7>uK+qvh|5LFWlH)
z&9N_^cRg~gar;9>NNrTqAY0R-pP14NPE`rK3f~ZS^E(9t&WTi#+OlUt0mTtzPh|#+
z^)=7?p5NNjHe|!2RF|U8n+7WP%FlypPbu3eyTZM|Rno7K?~r4Pim at y<!F<!0rn at Di
address@hidden|{PJY(t~g%NLsdnvM3y>Y@|HT2{fHb9P1^pZ8Tt^S;mQ8B4zsPd
ztFYVSE*!2v8l#_4L#)><y-ePyb1FSvhtG(U_yvLw{fcaq{8TM+in)q$s&cH4cVvD&
z+i-7O=rrD;e5;>qs-*ZKZw^2AY_{JDO%0#7agHf at 366`rV7X9mbD{C(*LtU>4?Tjf
zstO1$L`lbBdT671c+3+EF><ODPwbB=={W0f{_W5kVYD(<-9_ip_~iLPgO{W?{IT`-
z*dOa6osFZ7nWa}&?Uwj9&K;93RHx%O5gm-=awF9hwbk at RHJ|xjp>$VUcY-U{zSRD=
zyRg?HpW!``!>o-M>u#M at address@hidden>Q+W?PdJw}J at G(v4PBxlRyoTO
zi2Y_r7uI+>address@hidden|ur)Yn^U<AQjG>^7Y=g*}vX8o<~~X>gwVu52~h3jY>gD
address@hidden|{A|R|>guveRS!bhbSSR?_5K(~|$S?pJ?{cpP_s
zP5i3MIGY_6XsnrUTv?=0<q-uw8&0S?`%5|d`TDvC*vC0%d#ACLmV?P#66WY at 1PlMx
zr3Zhj!dne}3;I%eMfWBTY{m0!xkDVu;f=lmo)rIHcN8D8_KK}yU6<6-a!l7yb&jM3
z$~)#}XS?sn2~w)GAu`L^!#OFEOFOG7TZ^Zt3-qw|)7A~dcyjC)bDO);Jgvf<!mM^%
z42ACKw at address@hidden)kV#qL at 
zs(^kr85q8UT+$QQ5&M?R8t-d=Dw6Zk-&?=G)V2yGi(iN-
zM7O(F*iJgz1eW^h`En!U<yPv7MJ5!^N;sZqRHp`=p0&>L?%Up5fvQ|V)0>2~mYtmJ
zKAL{|)uDH#|73e_2xp?F$8=S1;)e-u$nMBIx-4jSq>(#HYKSiJSK$HXYsQX>s%VyC
zkD7?zWs_sXpB(%2Fh{3yJ-HO=v*(~=i at RyKhj37%&?R%ueD9w=x$m>u`_*D&JW=(-
zkP;m!oSIrZ;d$H_?R~VL3bd2FoNkrXa<-sT*Tg@)=kgx@;y$;_=pU%3yq<Wmh&OSR
address@hidden|kpM%Sc&i>5o$QKk8omW!yk2;SEF at s1`+i
zjJlycBdPz)`mFl)HP=Gg8j2OTn>ZlK!<F)`%{cI at Q%2{n`~KAPv<$S at KS(@p{vP`?
zshUaF8%!%SJ#dF`wQv)*NtLF%p}2|df$Mp9bI1B><K~*<QJ=Im#h;-nj)nFl+Y!%R
zCP!ul8%Vn%lN9%ihqT?4+1!44Bgqzq7<yS+X)6dH#Rr-URifs!7SS{I&zXmE>iVh*
zJ7a``2MRpZ<@rlw?s!w=ZPy<oG6#9Ka#sD8WUgra*tfc!+(Ea-RXf-?ustM4J_od%
z)p{bSVnPw?5A{k<&+O?Q6=|qC65T#_M>address@hidden
zNu>*<>%PhVNmoK`JbN57Y>yoOgw}B76>C&BU6e2&fFgh64DpNhQ?xVQr at KiWdADTM
z%-EQ(a&_`S#ViJOs at P2JAw`~YA*z5|YYfJl#_Nh&p*g-vp;uue>B~xouH>J{jL8j$
zp6Tnw?<>%&&|b at Q!ubw47v{{d5!?FQ!=B6G)#{9bMU&UZ|Fq2H;(aNBD$-6;6Mv=c
z&?K!_|6WyEp`y3)ykFP+n36NhJ3 at GA7!cPXK2iT3mkR&u)I!AXbwo)cStCugq~8hM
zEGd?0S~IUxHBuMm*GQ?(G<$k*8uqF7=|j3V>_Gm{KkM_UdxT_Ftk*wLjtdX>N;X68
z1&I9(zG5_$+pZW9U$4-cxbZRXbvM{691>qC5|t{{OumlhaSPE>ya!(ne#rObm-g2{
zjnrH8Ii}(Isel~C^SEER8G+n!`6v99 at j-Q5;^LHt)=kk%wFtN8cPgS4u|iL|OK>Hb
zB-T-#(KJ^Z<R-Z-GtzQrdolW=-5IkeuDQCQBzYF*9M4*u`zZI0yF};(sci};7PUsl
zH;xunOgy6Mt;iCx(fNo#uL%<rS<1J{{_KbIQci+nyx&b4h_U*j#$9~-a4&z1-D}(7
zGC2l%uY`xm2K|Kix0YyAqo|GiT)alvQ)N*$;address@hidden>V
zqg1IT+47HKWvGs4R&Hv}E_*k}L7zt+flLNhLbsR{&@j8W0jw#X!xs^HqxX?Tw4*p*
z)j{)7oq~CH&75%ld+&2{S at 9`KGDoY%NtFZh?5e!2cEPsHRVaK#Ua32iXtf at V{>Ri$
zEQuEJQG9c51ltmN8(xfmihWckGz*30zS4PLZLhr#<dcd)hBua3>M>Fef39s`uHZ~{
z4)-pVx{$r<S8?B>t)>%(X^IzktfIBDwOAj&3U?0=V_AG{#b-r3T+cf==T&|||62N0
z88Y08UZ*K17YP1z6wABi_}kIVT_UoKG}BB<SZbBcvf;PT2skWJ7%yaUOXZL98}6P+
address@hidden|t{IVQ!bE-Jn8Hz&m_F=woz83EsNpQ&nHZT$%&KD6;c at address@hidden
z*YFdexTxi|XnB~15>cMGMYUQ}Nx=uZ<+jW{>C}a~adu55Q;address@hidden)!NN@
zrASF~L^05M-|923F_lr(MV<M>Vk7Y^UzqHTOlAUqPk5wQ#}5v6%%77V<t-x}<Sp7(
zP!~6oC4V*N=^UlKq%+S|P#VjYDKA^o5~hKE*sI=+xASkr<-%63v78VYg)WOxsvhbp
zV#naCoXgo!&Q_tuyhZ1;@WxW;Qt+MYeNJlrS^Fo4KhRa$&Nqy?7hfsnx}}`19A8Jc
zBQ6tE!aFi5a)osk{#F!GHCB9!#Ms~EO>@l)Mxk`&Tf-K84>Tfd^rhIZIet5*I6np2
zN7kWEW at B8uX`6AK<|$q+B&u#Ij*8RSqsV)@M;N2Lp?a)nFRiep<=%F-50&B8X+D`6
z7~E`Ppqe|address@hidden
zm7hEM=e={z3jTw}su~-+8Ef$kBXRzIwn%;f$3}ZYf2?!?l`{8E(8bI&m)0G|^HGrd
ziz~-<C7VL=q#r*=;a9&^KW5e3tMW6QTLSfvM^)SCG;ZZ<hdcT%+N#^*+%8v2FkhNa
zhv`qn-Y~T>R?s{7Zv0P0yf}y7K-Yu>sRbS{hzg^k9!+#9@>{qUgxce!>bb_srqhBw
zq6 at sUf49ZCrZ^Y++sPW#$gm~;y#*O-XiazlJIHqxUI at c+f4L6zaJ9r1(Aye9t~h7p
zJhZ*>wWMv8D~xX}4&@#BY%td`)Ryl0;@a--BHyHab>HINTZWtFM%kcaI6 at Hk9e6fv
z5xyzqaW51#)ic%Qu+_6Tx0&svCn&uU5_DSQ0EJaL6rAh+;Mn1*=<)fZ<W97pZisbt
zw952BUs^bZ?h9$6M{wd|QVl7<BHU<ktfCHH=S#DlcfR!(Ac^81ZL(pnSS- at RALH1Y
zUm3J^#Xt#4nNJ(GHjG(address@hidden&yUs%G+sJ+xm9?Nx8q$|fNH=<dds=4<3Hr{l(
zv7%j+-ZEG%%DV#l94vQ^Bic#aDUqsVsOoOqgt*`4Q^rrq08SJB6^;tMxq|Xt=_gt)
z{HuspZRCT2d$xJ at C!S;B6fQ>address@hidden|c{v{kGYz0z{Ta3sp0
zJjFFtyi>^HOFmytkz(address@hidden at tb9wTYx*B at U
z`Wni6$z(Aqdb`D^H|xKPg;;5>mGFUI#aCjzNM~-g;)+sImKO?yci0=-YkE^7*SWtn
zkBv#X(d>9w at G5O~yXgGsl0)h8EOC6y^0-ANt6{csH+v6!QxCe$H>Jjr-R!W?OjTd=
zRIyI#;hb(?>8TlM&DYe7Hm2yl(qp0J-V63wt~DO)?Gx at TmBG2jCed3B+YLX|FSx-%
zRdEcj=XiNRXeOD>jTCw)jtk2phn<C-i+uy7*ZdGozTu}X1BJqeeVO(;&Q5Nhds=t^
zY0Y0T7mJ- at 5cNfsXIKS1TR11I5*W*rvS=K?MW`mW;7yUU_M-V!-Sa{_ at J7u8(+WcY
zewcLKuXEgWUiVD#lnY;!V{k*G9AhxOGdMNvxU(4X>v2b1kr+VlZWq=l!>V?Q?s9i$
zB(ELxUP`deiUs<O`fS`<svYtG9vXaAy|Y5c<-Yi*p=+$uxH>9Y^9gIY65>UnozRJ8
zgf(&=`pLURySS7d@|<*x at th70Vuci$+UmNl_-p8fZ<yn?<A6u-wTv92I_{uhaqKH&
zEyF8q4wr%32>p3Azlu$h2GY;GN-;sPPN*wS0Uw`r=|j^{E!Cl at B~fX7t;kA$dq=e6
zl)Jh6XrPzef&J1gij_<g3}bY8e0%(nuPB`3hoW~<adHa}7FsJ>Dte=9{<F?wZjb+n
ze2l-VUZ%?s27-omd&j$N-Xw43fGskcoKQv#3-vp-aT=#EnC~r?5C;lYTu=T+x^eA=
z{h~>{z~%+cxHtOxhZi#}epl^OXF?6VEmYrk$y+J-Jh&(F9~n+-E1K!MX$Gkb%940C
zYt0?t4)Nvr`fL}|^J9cF!Y=4ubPu=meexF!+lZBascfgQiVJ9W$ry<BHuMw!p3o$+
zhHY1Lj8f at ltL`W!;7*XaXVEy+f<@$QqzpbG)KCP(e6En37bqRv60y at 4Tn|OAauEN6
z)Rh;7zXqM*oN%{DYk8IY9dA(eQjJ%(QZ^QNPRsSf$B~+;<&JU|?TN179o#q6jMyUe
zrN*QP`pVrCx+zRTJGPL-NdJX=;p351`3rr^2J#n_ at roM!YHkIp%%X5jZZEf)^RYg3
z5-SUx<rFl4*`;dX`jLuq4mI&dp?h>(_<address@hidden|qhVn{1^QXaHHojp7iYvG5o7
zofT($XeO=8PSbx_Dn8C3-i{lgU4%upM{H6bl1Ja5p4=(?9gW0)As=nQRBR-z4I`%F
zVtgU~3?6_#pfyO3``|address@hidden<_KDV{t7&1 at address@hidden;8{q
zv<~`%((odP;i~*gZalY+TZzx3wkR5vLd#HRWI;br9lRdRVx8z9vQ}1;Q?xaT=3MYi
z15RTTNl{rr4Dw)k3-b{z9mCBQ9txWj<address@hidden(LLK`FFi6d;4pDT0K#gulQ
zkm*6AW4OJe`(8Lnr7?Up{i{8pc at TZUaG4v(^^TgV$?=wSRgPQ<8r?^I8^c9|JA62h
z7I`UG4v!7>rAj(eI!#WZcgjT5!&sj_QLReclyphhBHz_E(HR0kNBOW7x(u)Xtjm3B
zYw29=J1Eyz*o7#$v1EcZ{D)Tx3EID6z9d{WZs#%#V+$Cx%1C`N(X^La9oPVx^ltc3
z-u2wlwyL(Nu8+aOu+w!_>gr4JwhCxThCG+{(5#M*HMU{T6iJ2dSOe6Hc=ICFA>R;b
zF6=?w1Qk3a&yXLo&-G5HV^o+k`kC7t{7qZqLR>f9g!r_0lh~Rrh~1d at gFOgL)0Q at I
zG(CJ()k$^Ed-hM~KZ-xOS%vLwf|rHyigKi4c&U_#SMkMAS#gFX4Ap*!b})@e*`v~W
zI}7V#M{DNF$zmH_ at yNT3$?5)#mDxteX8%guSvi=#4R#4HVS-`__laezc3Tpn9P(0e
zLBUm)>;7hufu`$*LdeSnqQXLp{53zfX3oz0<~|kr$eq%aR63;r!6w0zk~Lh;GcH_8
z<21bD47 at YxYw{>A5{zi8TP#8td82wnC5L>u6Y?JAHL)M?%!<qq`-twybzhF>fWLfj
ztyc(*RjcC;>address@hidden|t19}S&mUV)XUA1_3oXOYfV^_K&uqW#pPak=m4!koUN-oL
z`m6y(sJ#EDzdk=Q`lU(9ztK-mZ4lig{F`-&USYf~Y}WR+wu(yehw^a#=A1&=zTB8V
zPb&G7oWq<8pu;#YwAlY%PS;g5wdRK?swQg-rHj2#QcTB$WxD5@<+1;oqr$ziM`ex6
zE}s1<XM}GKw#cvCrCnv5uiYJdXWWWF2?aL$)YpW@@dJu=HHUF$Q=jCf(OWb=OUd|3
zVtwbd{A>CD<nq~p{12h+;oYu_j<(J!o;QK2{!+ftY=EJgZaS)@PftmTtA`}z+r(ON
zf;vrK(b`>S^2OUGI2PN^W-rN|7HmSw`1ZQ0xs~2JAryWew9_2JhUk%sL&{4 at laq?@
z!>Q4{D0aGfozfqDB07z(bKJErwtvn!lC{U3D~W+y&X118u7vPKk{&53>(t5SSg|jC
zWGRx;E2<bPqhDs-tLw&1)}ArNqcXO~*)wuFWiQBj=d47_k{thUuiMT1h2?G1ok+A$
z%&d)if=z~UMMfn27DB2M)-};oe5cBa?y6G-mgb+yTbHxx_k}+PJ&D25?h(!e*A(B;
zNWT19KF*aiKa9Df#G2m)O$7!EgU}fB;MfYP4#E`U at Tja%E87EmhVzbnvh9iQc_iAW
zb3!OOdjuVF42?w>^nCm^-Bi9~%--aX`jd27TQ9DzPQ|%3mCQ4^Dz0VuukyvbzyB!m
zKKk$YU%Ip1X78TxDpVQ6-ld{_^i$nCsGRN=C}WAB!s?OMSj%Xkiy~m$plsn?mUk$(
zLf*lg7Wqws9i{Vu1m73eY0u=yRJvWx#l6jsEjKvAAB}Gx-%0q3H$}gWovAc&gQ9%;
z>k+}Z$<ftW-aaRPp>L72Bar4z at _0N$Lit2R_mQERW6=lIA>JJ4DfCcZ77x|cj{c(B
zNcM;yv<AXEZ`z?l?y2Ki>}xI`3T^gQ^Bi+846G!v>|eQ?f{%?Dt-`~oO$Cn{qvcs#
zs_D4?HNGv*H!?*%--rA=dAIW)=M2dE<r^O;<(0e#y|V%`ea7EskGNW9ZFIC)S6L<T
zSNsA|!%r}+vs4s|qXnANs+3T1#}r$p<GdqilYQkQ%>tR;w(cn|zyE@)lyl`P+U?Pq
zs-Il9=-~xq-4K3dlqV)yqeY)pmthUZybT;address@hidden@&>yfMoL6H!BhT~9^m&dmRJb$
z<4vjhW?WL#+vM6Yzqo_S%9h`{KCB||(address@hidden|E%#
z7g#a6gu8FV<_CNYv4fSy{=rEsA?ld%z7XWA8<y$Sbh!JLy`Za|V~wq-ziT+xzu&jP
zQ_<TnQWTeDvxrqw-O^5Vl$#jSGuf{jk49^znN}#uQ>3(MOQ5Tse0v+0&Yk37-e(eu
z+zhVwxAs~B$E3DICuQ>=Oqsg7=#Zv$!e-+mJW>@K^Vygn<cTW%XJNFzsC|vSp7S4D
zEvG5GN0P(0g4KNg_-VK}`6<;y6%1v~TZCtdGYP%on~Kx9Q&A_QdLt`os;a0`OAp+$
z-DiDg-5s2#0_I5bz<address@hidden
zn#s-ZcCuBmmvn5*f9T#8xg0(fDCbRfSMhI`C$a<*7W$i~>ho}kC{uFJ=#_k3<!93}
z{cQYDxT3!yo)35&gB*Xm3OSUnX`!g_JO51|@qF_Ylgy|Cxk at YRT1QPn2e`jt8^rby
z+X>@Lx1w9B_Vc;A`<e{tj{CDS-CfdE&SCQ(l6r^B2N(Hl-sIq>h$s9qqEhWO^BP&0
z8Z#IOdL$jDJRMb6oFSXUr5Y8Q;!pH!_AT;nbWis$k&i at DgD-tvk1^nvd$5WmR;+IB
zps$W*s$KCNjjz}@;kfCW{w8YAm(|@DHU+jiw%JA3Lc7&@DNLmjp)!Hp-jJ`loQYqv
zBV2dGXX78xO{c8et(6rexP`hbeRU3_7_CR+BOAOvM-}HqyV6$Bha&5P!vZILO?-iH
zBUFQN)T?qDe=B%A#PlPfs`fJOs7sE{)SSfQR0p&s*3Luija)0;|2WJ0%aY%btboq9
z(_PtjHQY~X5P8crGaii6iVdS?6p+jnu}4rDH)|g;hIN`k!m6Og-PY5~|H3`f{XL|L
zd<zWr*Y$l3lqQrdmlbTjc4X8SE{ji#T^sv}?}4vHF=HVyforLqsrgQZdzG$n?vc(N
z_Dg<yBsP>9nB-0K_yXPNIM$a5+W6=>nxWiMW0Uy8>Lb*wYGiOInzMLi8-0Lp8XV&8
z=icK|I97WnN+xMq=%v4=uVs+PDz-$P#|_uNQ>D;Y)jR7lQ-t58?qqT5C*r}}ZuM;b
zZa{J#ab5MO-0!>|$b)K;q+puwqkm=O4tXREqxZGMU=_D3x>(!AE#`UFTeDB+#k<&9
z^=tJOS$4aecRl;v^<Dqd0Os(xKs$fg-~nj{%498R3)Kh{QSIh*ro!>7)M1KLI-^y!
zoB6~nbqo^y&address@hidden<7y3%;DCSs37#i`dw840-sVMA~
z`3*I6LqK=?v at H~C!ks<KT&-P_?YQG<&>k5X-W6&W+!8z)xj>wedh$<I1)UDx<C;ZB
z$6iy$Dxyud%}W)RaAW9XVsh8}+;!I at xv#pigI>9P<V&Ew_q``I*iyF3^T|V1M^g#a
zMm*oJEAE)8I6bW>81-G;MK#KF?Nxjy at W;K<d)hC0zXn<nP8t at R;5YbZg(}mJthrnT
z-_>2$G{lLTh4E_h3!Km0)Xh=H(<IDmZU}S2!#)4Goxa1K#h#={De3RvEq^axOn^#P
zP!;wPGyM%?d2y>?ioRkY+*Gt%yDaL3(1qi)<<-;V)1J4E94F^2=m`2pOARAUBB4;3
zP&X-><&n2?FU7&AZHjc3sy`FkRa2LnuFW%1RTI`jSf|2B7d+{m>CgAybRYH|iu4Y5
z4qo;T at C^-yrS0SfSt^W(YOgEHw^h%Mon{z;fAY7rvQo<i;l3)JP$Y8Ad&<+pKhihT
ze?T5VE%Ntp>EMZAed#%=A-l)~rA1qszrr^(ud(zKXJ9AP{%yJL=$0~5`H~I`5?_nJ
zReyco!O&Q#O{i30ivMt+l=KUo;Vj%NWrD7bn8N;1jWK)|53>v6OwD;kO|GY+lX^N=
zGjcF+ConGX(l<W%R_Y_?OG6~96fYknZ2+(5(oTxkVqtVf>|`M7|Ii`6y84-74pQM$
z;(V^8TsHDBGD<oRXHU+-PG_d<mGUC7(lq%n(GxSv6w9loag*>address@hidden
zHk^Bg?UFCJB6u#WlrBb=lK)T|Dnm15hrFGfWNsG6>hn(&<@qZ}Qk2z}5*_ReuEoD+
zO-W^ZKxo7%m{aZ}HHwT6%?bUEbO79F9Z8Yq$<vTRsLW3n0?Pej3~tPiSJhVJLS+>r
zjO3T2i+HY3hZ{|XN3Mpm!kOXG(hgb?{lz3QkA&oJ@){D6yO0Iw2i^_G1kH*rilbaA
z7ZS#ZU$_Sl>HlB~^_zoiqob&ae3CIqBUeaA+LBd(gN5Jdd=jP{AYcpjFJ8nS$Lm-(
z+?ijCwMd8Wpa$$F9Yl+<>F5T##FW^FDxu}95>#{_NNZYw&StS3<`-~Jxn=w#+>DA)
z7p|r6$aJ;|_vf74X&h#g86&Udmt-C-N*|J`B$EteyYL36eaG;_xi)MY?TG*5hTuDR
z4u6*OvSQ4F4zTTX9yu*PlS|3p<*!T!hapQtHCi4eqX^r~(&-=SVb9oKY$IOFAI0xj
z7 at 4>h_$4aMIk-&R77d~=NKcY3^_EwVDEftF(_^eF9*B#f*6cRZzz#?mJd4W^lKB^m
zL(}kcREv#<$5Jv)-Y$<N?^$zv0;{>xD2c5j>address@hidden at 40|P<VkR
zvoy3Hoo6O?7~R7S at j^5YR%9g=rAkr{*+9;cRrDErryU|- at 44tMK8QqS!704J)#UE;
z2lzDZB(maSTt)nq{iN$iQ`sjCA!_y?)Z3+5ahger)address@hidden>
z=2mho at jWc@)%XCM37yScbOcSKRoOMxiCv*?dY1Xw3ATp*A)9Dv7Q<SjZ+s;&n;U?O
address@hidden;8pAr?GM)uMh55^R71(!M?4st__cgBG at Cd`
zQ+6J#=*C0&zIZdMLMO`x`MGpddLb_*`-l^I10zsH+ at 0g#ejoS-d}mw)JpK=N7l8ud
ze&D_A1l__`u^03XeL_D|MjY}ea*OmL>q$Af9K2PE`DhW8%C+GFXbj54YdI0_ at stlh
z|F;0lGlBaX&1X|+H8M_)mwOWh6VW4d9o=I&v=u!eGl`O=>>?|LmUHh!Eb6(!+;mQX
z+S4m+A#_?Q(9Yy1`N)address@hidden(nIw
zh(V01`LnnT`bF1KiOeK>$Vf7joFH)&u?)5dwMTDQNnDw0hkN12yj{q`QHaMyP$gQD
zUWe117g-)1%1WSgh|kY7mIdj5OkzXOU^I={sF!+~39m${YziBPda~y<3m*}9A%TC&
z-N8#)C$dfU$hAmN-bC)uGH4I3i|-*9DvOk?AuY<1aY;;ALtI}dDXf8<nTlt!dGbs7
z9p%_j8pV!)PcO3etOm=ZOX*os1F~`o%SKhXw|FyGj318Os2|vPH2%rXu$`<KTf?T|
zo?I?6vbJQlJYBvh-zPS((sf#iR40?chErJ`R2qNdqPUsZ$#)Xh at ZWG8m%<rw0#ajv
z8;ET5HN8v|XhG79EG4hx>Lh^{VVhBP+!8FQVPn`U8bc7Bf at YvG><+3btP;QSY5ZqC
z4_9INRA5Q$J-th+(30#13xYEK1nyl$#>iLY&a4COf+ujRg|b2w9HDyFhn<CJva&tw
zH--KfGNXc61=vv*XF at ca*mUrehwVgTQ5DF#mFOBRhH7)&aY^JxfAD+sopypeF|!UZ
z<Dq0UNg_MRMwSG9EFIfRkJ1gy0cbm&)AN0~1bh`w<=gNz at c=Xl4Q8#Nvvv>{<eKAt
zXgh62o=EQ^wdE8tm at KA7Rv#7N%5Zsr7X(d13)x<_AL4ol+Q~L>J%!I)5$+AQ7?*>}
zGMc<0cPXX6*$UJfaz#VC5<BTihm#bD8V53St2iB;j+Oa4=nHy|2c!RJ0<8EMWdCq_
address@hidden&{(address@hidden|u#1?ZixlL#?bPPA+DQE-gf_vgk5JxB2
zV%mfhC1yIBuAv=iNAgH6Kw41^dVr7dw}m$Rbo>b(GuS5D9nC{cAeM4bCO4M*1HHeE
z>;y!~W%7~Av;buHMD`eEpoYL6dzq3QA|1#$=EYBORh-246~=Ru;F?*eAsa!Kk%n{^
z-Nsf!*YG at AfcCMn%*9%um#jUFrlk-=>rf0gRXESbpn3E-yAR{nWSt=1U(kUho`hl4
z7qks~#qwA`c9li{Z;u;K0Lui?Pt4(p_z(AsV}OzYl#AXm18d8Av6J)=czZdZWkEKN
zu7JF1FTa(>$!*CPn$K!N-)u8fKYO?~{4hQp--q+(J2@>b$_TrF>tn{YfW?_?kg7|F
z6r%N6AH?A(TouKE9Tt#xaBltuDb5DqnOs?JD7Q`U2~D`Iz{;QTS$2pvq#dB2`-l!=
z4_Q0boSMmWau)iy<sd`50v}!jl%0nS+yzvPePwr1M;6O=V9dn>KFp&{XfxImSh_f_
zgr<O><5(f|6U|0NAzq%a>+A;`z|address@hidden at Ua|u8m)w}%WJ}>>eh+423(!qq&#7!7
z%^+^#A=l|vc8ZNbwYby#8on_12gh)$A#;bb)tKOPh at TD|k41KkP}wHO$m1k4DMNLP
zpiX!wF3eTN^VmG#z&mIG`$3nW9Gry~q4Qj- at CNS#e0vP}^O^2o-B1>r1jw05>X4(L
zG5;e)fay*_o)*D%xySekvT_EY2R|7+RvCX}>*z3c1^tGqp(dFj-;%BLH7kPm;*0n!
z`WLwCH89?I`knq_YmkkN$Fd*`gSqGUB-SB6-OFMDzwa?Ua7}-<lXd~rUQa5>A*rO?
zfRtc!&>KuSGrxg*fu^$Ws3Rze+khw?xLEEcR6?J*a=0OIdnML|79$q&oOGe(*ke`|
zqN+dYOxuw0(AmEY+UPE>!B at wPz_KH8UtAn5MEmeI6w4^{qVXse9R<5rV6)hEHiV6Y
zxH$r7QkZ>1CGaA)mJP$d at fYZ)$8+tt?Fg~%>^5B at E966RP)?y|SPp8#t>+fviRcCM
zvEFDZ+JySzanMxhjq<s3d=ZYI!zhszBDG0lCLu3+0@(YExyci`uRKehBToXXY)v-M
z_b7=wz?p<O!U?VuUct5HF*gqoDS$^}EBXe0+k=v5SZ)UyS%xep)address@hidden
zJCH$1mPRs*L!WUoK8LFY$U2t0$am-bcp6t0_X3_tVJlfjwx2#CwMcJLfo9QrtOWj_
zN;A?MG at 6;|eOei>=I-NPs0TNn-;ZO^Sz!75l%rMX0eYAQX*X0A$K$Jru_vG#JA)>O
zVzZEpWqbrr=5k=}F`y7uvl?_YDFbmg6Cc7gaUt9hO{5C?AMHvD(2v9bI698iMIp3@
zn*ci_hXMJ2;(VNfzu+1CI_?590v<MH{pcF<0)Bt69klUwRuO$+sptYb$v9jGrvj=m
address@hidden>&RBwu}wL!>|_b=9=&>address@hidden)pIkf)PxB!eu49hpb$FfPJ1f|VU%
z%g{>r{f at vL1+DiRbp}o>hYzyetQMO`ih*y=lP3_rH{ewKGIWs50%l!6)>AF}- at Z^D
zAf?ES1Ab`F^EeOA?rcM#>!^=i04$SOSM-`4BSqw0GDn&d=#$YV;address@hidden>
z6+{JLcV-su%gy2U at +PhwM9MgP0F-NCc82DX_MlNOQwu1OKG2n%OrHYB?qzON0o2-a
zdX&uvG;2wlv$Bw%J#j6rp-_y!iSDv>address@hidden|VEqOY)mZcsBEpbcQp
ztuCL%tN3o*T09qxpyfzyI*cmGXL$!XL{rcjJcVn`{f(1B$#r6X*hc6MoP#RkDb7U^
z^qbqs{brBoV^#_F?FO;VI1_wv1GJch_9gq|ko<~lA%wJHn?QNxp>t>sS^{V6 at 55*k
zp3n8gH_$<Ro3rC7Y#(jKnuDgbgI_8Fw~rznL2EvgOOTgjHZ26o{4OhwA93#?es+PX
z>W6!QR_D00+%nK{r?_6+LBQ2EbS3z>1ME>&VFy?<)EkXu0{}zKv^i-G>Wk5NtPZzD
zkoZ>|<>qj(7sfub=BN}~OUeSH9tP!C8UKq%p?vxT6n8Uf0K~43D{|?$B}xEgvjjgv
z|F9yEzpntnM}v~siI;<QUb1xdFCg7cdLHV&SQ<mOf||U<j?>NTF)+kX+zEE<ck at 2f
z02pXEIz*?_r7R3c^NuQ!2|HmI?+GZrG1LW~yZ|`A6Xmk!aO%G+{tZa<5cu>8<mn$I
zLq6KLt=t><d at VUAuO+L<UUHw-0NnY5P66^fLswBXw2K`B1y>1nLNib|{u!5#D{-HI
zvF4D2Bo}nrVo(p$SOV})6uSpCiyHX4KGZQQVGlllD{z_I0B$ULfJ*Uxt^xiD8o3ej
zf|uSRC4SGU)6=9haOVf8$Tvc5x`_57lH8sINl#iFR8uy0376u|2rHqkJ_7ek<(dI{
zJwb{1A!tb#T?E-Rl->i5Sts9?50PiI2MXe3Za(@9YIQ4A!s)atTE!Z%zaVDn2xIu7
z{0{y*)FqcGqrKUGkVgV2o2HP1CqP$qV5g{uB+*rDD;k9M<address@hidden(P`xx^
z6IlS%$9i at address@hidden&GU$Fy8s0mcS15qEyyq2sk
zRA_#3kmk@>`ib^JVNd`K*;#r7u)iRxf_4G6?!abj<h+2I^PpPjjQ+5Ab`<#6gpZ&+
zsG4um3nWW!O4gB!q!)G4JoXHC<0 at f0`Ww#z?eG)&HbwA$U>-F_oD;C2FjpLV=|N!O
zbF at 6$4QuOwtWdrFLlfya+67osrYqPeB%{K3BcKQ3V)0qP at o8uUn+Xpcn*m(~M$Pb=
zLD#am>@=va2&kZss3lqqF&hun at K3;jU$`sYi?rN*!0imCg83Ih4*)sdf^|32#h}3|
zvAc91*tj;iOKyOVkE1X*h%dp-1szfvTUi at 69_*P7n0y%OwU+oFxPu-gvx%S@@6oq(
zH)yTqz=nTe3VJgQU1hat9OPGhyaTkyEtq#D*o*FqcAz_OO&NNZRsf6Sp%17v%3!TQ
zGrHJZP%Jw at 7iwS!`x7gSuX1~FF4Lk_r~q2YWcCU){v)~>P-iU}MMi+iN=7Oqp!w)K
zsMcoqEnGhacfvK%cBJ4Ag06mz&f?biJo^Jm{3R&rt+XRVTpM&BMmYt2k`g4Ev?H&G
z2b8jdZQ&{kcc8LW at address@hidden)P<33)$arTA)1G=nWZ2HS9QRh)Sat
zs3OXsKj|O9^Dgu at s{}k)0Pnzm1GcWk%Ww*Gvx)&{O at X|Kg}Sm7`pF8hI`j=`OPjLl
z=x<Qq<?vcm4s37*MiNj_ at OUnI40^INsJIM>gCX=PC6LvtAy2I+oqc0>m=l<x9(1A(
z!9BLJTkHuo^U0vF-RLCxLbn3KH-TE$0UEJBoUW}6>Z~aAQaaLUbPjz=$FN0gHE7yY
z=mw+$mrjLhu?P!5JX`T4l!Y8fgpSNcIutqtLug%k61?1s831uc!QXsPXO}~_(NVOX
address@hidden|I9d&>*v+;9YrhAj-x_qwD9Gpy^cyIK7&Ha^rGiR#B8>4H
zJq6Y90=35yTyun(QDt-;address@hidden)3a2G#%+TqV$PHy{>UKyH6RN4Y9o
zJak4T;n8RU+t2=n(Oa-Yz<~td<wY=qY+%^yL__D%?yNRii|&C^nSmR_SSI`ql!Y6r
z at A`0(C=u7fakv7g(6NC0>sSgP_7VCOx;8!83+UC=MTbG*A7edWr7uBEErrfn58zBa
z(m at address@hidden>e)YayEedVeeXz^b7ls1A%?7ByqT*-Xf!%IJR at XgD5<
zo<XILnU>address@hidden&rLEfZ-jqWfjT8wYuH|R1-M+ER`K3xJ9
address@hidden|address@hidden at E5z)F{(
z%Df2GYhj4LOJFfG+~pSiO~(S3EMiaDV$=xElwf=t$KVw77sQtu at UsDKhxY>>ECU8U
z4p&tLuDMA!0TMK2cD5gWKHUVJWsd;iPe8AsH&lJ2&address@hidden
zpfGQ-o9F<V0K9gFMKLEt+B&uy4aY8Y3|8JAcSkdzOVbZcgzt`oQ!w?>KvW(51Cg{3
z)X!P)+5h at address@hidden(siCSv~`ehuWz+R7K74bwt4vF9A2}0CLv?^qawM0=lO|
z?wo~Bud&LYIfkRcs1{iKE#%k{1bT|ihMHChr)id;1Y8zh0sD1fRUjv`Xj?WOxT8NC
z2i&{~Sb00lsuijUnf8gT1Pcs>_56T1n+Y+ZMtfK;sIsHbAz2I_FAkhk2XyXqu+Try
zfjI{nsuU7&F}xH#1r&3_te2yFv=m)}zh;1LJ`dcM0g*Ko>=VnXvx-nZPJtC%XNMt^
address@hidden;3#z?<{nip|hd8V`F{D(H8$Wgq_^f&SMK
zX#+aP#>${^V4weKzS^h<(n6e@@j&?f`w_MQl=>q;fHzP<wTFAySWSq_qF|w;tSi{l
z4V9J-KZaa&06NS9##j$$ma>3T1AsO@;G*T|address@hidden)7p&$$7r<Y~
zLDfwHUIDH|eb6T0;4-W-#APLTo(7||15c%c6;hz0`w8_(L(I at t<b;ml3Yf`0SjAFg
zhidjLo5Kdfe6zqRcJOm!sEH4QTJ{0{=K>z~0-P<1Z=vF-0x;4)=p)n{2VlfhbOc4=
zXTYAH!OLMl&jO${U6AKt81*bvnh$_wmw?qyg0{QLPNLpe#J|x{K>Xt1_nJrveI+YI
zb}6v&JW!NV04LXjy at mqsM}T|gq4%)address@hidden(VX8K>dv{3PQgC
z;ZMRE8UfyQfDQ?0O_<SK$btKSHVVkbHvjA0LDeRp?Qq3!mJKTMHpG5;uq*+4Ux5DM
z8F>B#bJqislz|?2XPDo6=s`N!zfkp8L<7Lb)1cea8WhhS$btC~BijM*g0KgW1poDc
z5+y?JN254Ewd#<w*MO5I!(HkDXU&CCw!>XAL0_JM*QYSn|6=4ZSp6%^<Ox_Tz^Z_C
zhXB${f($5%7DMir1itJDck{3u-~tWwK^B3B_Q85z!>m<+p8o=pO$F>+0c*YiBTj)4
z=Ku?&gZ8V7dZK<Xn`DU36sX3}!8pHRJsF^;R{=lwgpB$ZFrX=DoVxIhLV&L;!3GwH
zm%Ctx2{7{!=nybhbC`bybeP|Q-EP8Md=Ob5AnUW>`7S(ipbm(EbAb(^E1Cusw+P-T
z1pV#DjEB6v3)lXy5BdY%JAog{gN-PBmdh~MzZ4)re^7;2p-yiMHY^Li-3gKK7;Jl+
zEdW)!7?js1h$ESmM<(F-yWs6}><dJN1Ti}hBD6VL54bfNkVgaew!`0IVa>_FnOR_~
zix4LZ0VPL6HZBA0=!DMBSQv8%<YZ~Ep%U`GGI|cSX^fh|d<Fr2m4_;8Bjo=Hu$31^
zDFl6~gD{gNfGqFe{vl8ZRUro|fp0eh(wBhPSPIuh0CDZm(cA-%(||+kV8lC+?-CPW
zZ8hP0K3F$`IB~=0Dwum^xXW_D`w^hrc(6+j)He^<cZiEOU?U&I>MO{HNs!r7Aitgg
zhs}WcaSBv)t6<%)*?Z{sS^;VGfb?yFJ1JN-2!4435rt3yB031!1c!hj`UQAq at GcDR
s#sB|bI~4E=Ed%h=|Hh8||Kop%^S}2T{6zw*!{Gq<E^OKT|J9WJA2^N;-T(jq

literal 0
HcmV?d00001

diff --git a/src/python/ChangeLog b/src/python/ChangeLog
deleted file mode 100644
index 419f6b2..0000000
--- a/src/python/ChangeLog
+++ /dev/null
@@ -1,474 +0,0 @@
-2008-12-17  Hynek Hanke  <hanke at mach>
-
-       * Makefile.in: Create conf/desktop/ directory for
-       installation.
-
-2008-12-10  Hynek Hanke  <hanke at mach>
-
-       * speechd_config/config.py (Tests.diagnostics.decide_to_test): Set port 
in
-       ~/.profile and place speechd.desktop in ~/.config/autostart
-
-       * Makefile.in (all): Handle speechd.desktop.
-
-2008-11-26  Hynek Hanke  <hanke at mach>
-
-       * Makefile.in (maintainer-clean): Maintainer-clean does clean.
-
-2008-10-15  Hynek Hanke  <hanke at mach>
-
-       * Makefile.in: Respect ${DESTDIR}. 
-
-2008-08-11  Hynek Hanke  <hanke at brailcom.org>
-
-       * speechd_config/config.py (Tests.audio_try_play): Use proper 
os.path.join
-       for constructing path to the testing wav file.
-
-2008-07-31  Hynek Hanke  <hanke at brailcom.org>
-
-       * speechd_config/config.py (Tests.diagnostics): Only try hearing
-       test if Speech Dispatcher was started successfuly.
-       (Tests.diagnostics.decide_to_test): Do not ask whether to
-       start/restart but first try to stop and then subsequently
-       start via /etc/init.d/ (this covers both cases).
-
-2008-07-14  Hynek Hanke  <hanke at brailcom.org>
-
-       * Makefile.in (clean): Delete speechd_config/paths.py
-       (install): Include prefix correctly.
-       (sysconfdir): Define sysconfdir.
-
-2008-07-12  Hynek Hanke  <hanke at brailcom.org>
-
-       * speechd_config/config.py (Tests.diagnostics.decide_to_test):
-       AudioOutput method is the proper parameter name, not
-       DefaultAudioOutput.
-
-2008-07-11  Hynek Hanke  <hanke at brailcom.org>
-
-       * speechd_config/config.py (Options.__init__): Added basic
-       description into help message.
-
-       * Makefile.in (all): Typo in directory paths.
-
-       * speechd_config/config.py (Options.__init__): Include summary
-       message into help.
-
-2008-07-10  Hynek Hanke  <hanke at brailcom.org>
-
-       * speechd_config/config.py (Options): Restructured.
-       test_spd_say: New test.
-       Handle SPEECHD_PORT correctly.
-       (Tests.write_diagnostics_results): New method. 
-       Use TMPDIR correctly.
-       (Configuration.
-       (Configure.speechd_start_system): Allow also restart.
-       Bugfixes.
-
-2008-07-09  Hynek Hanke  <hanke at brailcom.org>
-
-       * speechd_config/config.py (Tests.diagnostics.decide_to_test):
-       Also include configuration into debugging archive.
-
-       * speechd_config/spd-conf: Do not call main() since it will
-       be called automatically on import.
-
-       * speechd_config/config.py: Typo.
-
-       * Makefile.in (all): speechd_config/paths.py generation moved
-       from install.
-
-       * setup.py (speechd_config) New module.
-
-       * Makefile.in (speechd_config): New module.
-       Write necessary paths into speech_config/conf_path.py
-
-2008-06-27  Hynek Hanke  <hanke at brailcom.org>
-
-       * speechd/client.py (SSIPClient.set_debug): New method.
-       (SSIPClient.set_debug_destination): New method.
-       (SSIPClient.set_debug): New method.
-       (SSIPClient.set_debug_destination): New method.
-
-2008-02-19  Tomas Cerha  <cerha at brailcom.org>
-
-       * README: New file.
-
-       * speechd/client.py (SSIPClient.__init__): Docstring improved.
-
-2008-02-04  Hynek Hanke  <hanke at mach>
-
-       * Makefile.in: New file. Propagate $prefix correctly.
-
-2008-01-29  Tomas Cerha  <cerha at brailcom.org>
-
-       * speechd/client.py (SSIPClient.__init__): Use the environment
-       variable `SPEECHD_HOST' if defined.
-
-2007-11-25  Tomas Cerha  <cerha at brailcom.org>
-
-       * speechd/client.py: Handle TypeError while SPEECHD_PORT value
-       conversion.
-
-2007-11-22  Tomas Cerha  <cerha at brailcom.org>
-
-       * speechd/client.py (SSIPClient.__init__): Use the environment
-       variable `SPEECHD_PORT' if defined.
-
-2007-07-11  Tomas Cerha  <cerha at brailcom.org>
-
-       * speechd/client.py (SSIPClient.list_synthesis_voices.split):
-       Convert empty strings to `None'.  Docstring improved.
-
-2007-07-10  Tomas Cerha  <cerha at brailcom.org>
-
-       * speechd/_test.py (AutomaticTest.test_callbacks): Test also the
-       `END' callback, which doesn't currently work with Flite.
-
-2007-07-04  Tomas Cerha  <cerha at brailcom.org>
-
-       * speechd/client.py (SSIPClient.resume, SSIPClient.pause): Send
-       the right SSIP commands.
-
-2007-07-03  Tomas Cerha  <cerha at brailcom.org>
-
-       * speechd/client.py (_SSIP_Connection._recv_response): Raise
-       exception if the communication thread is not alive.
-
-2007-07-02  Tomas Cerha  <cerha at brailcom.org>
-
-       * speechd/client.py (SSIPCommunicationError): New class.
-       (_SSIP_Connection._recv_response): Quit if the communication
-       thread is not alive.
-       (_SSIP_Connection.send_command, _SSIP_Connection.send_data): Raise
-       `SSIPCommunicationError' on socket error.
-
-2007-07-02  Hynek Hanke  <hanke at syrr.buchal.name>
-
-       * speechd/_test.py: Voice list test uncommented.
-
-2007-06-26  Tomas Cerha  <cerha at brailcom.org>
-
-       * speechd/_test.py (VoiceTest.test_lists): New test.
-
-       * speechd/client.py (SSIPClient.list_output_modules)
-       (SSIPClient.list_synthesis_voices, SSIPClient.set_output_module)
-       (SSIPClient.set_synthesis_voice): New methods.
-
-2007-05-03  Hynek Hanke  <hanke at brailcom.org>
-
-       * Makefile (clean): Remove build.
-
-2007-02-21  Tomas Cerha  <cerha at brailcom.org>
-
-       * speechd/_test.py (AutomaticTest.test_callbacks): Added warning.
-
-2007-02-17  Hynek Hanke  <hanke at brailcom.org>
-
-       * speechd/_test.py (AutomaticTest.test_callbacks): Removed comment
-       about Scope.SELF not working.
-       Added TODO comment about fixing this test.
-
-2007-02-05  Tomas Cerha  <cerha at brailcom.org>
-
-       * speechd/client.py (_SSIP_Connection.__init__): Thread name
-       changed.
-       (SSIPClient.__init__): Allocate lock.
-       (SSIPClient._callback_handler): Lock before accessing
-       `self._callbacks'.
-       (SSIPClient.speak): Added more doc.  Lock before accessing
-       `self._callbacks'.
-
-2007-01-29  Tomas Cerha  <cerha at brailcom.org>
-
-       * speechd/client.py (SSIPClient._callback_handler)
-       (SSIPClient.speak): Removed prints.
-
-       * speechd/_test.py (SSIPClientTest.check_callbacks): Wait for
-       callbacks after canceling messages.
-       (TestSuite): Class removed.
-       (tests): Instance removed.
-       (SSIPClientTest): Class split into `AutomaticTest' and `VoiceTest'.
-       (_SSIPClientTest, AutomaticTest, VoiceTest): New classes.
-       (SpeakerTest): Class removed.
-       (get_tests): Function removed.
-
-2007-01-26  Tomas Cerha  <cerha at brailcom.org>
-
-       * speechd/_test.py (SSIPClientTest.check_callbacks): New test.
-       (SSIPClientTest.check_notification): Temporarily commented out.
-
-       * speechd/client.py
-       (_SSIP_Connection._CALLBACK_TYPE_MAP): New constant.
-       (_SSIP_Connection.__init__): Initialize `self._callback' instead
-       of `self._callbacks'.
-       (_SSIP_Connection._communication): Docstring reformatted.  The
-       whole event dispatching rewritten to use `_CALLBACK_TYPE_MAP' and
-       use a single callback function.
-       (_SSIP_Connection.send_command): Docstring typo fixed.
-       (_SSIP_Connection.send_data): Docstring typo fixed.
-       (_SSIP_Connection.send_data): Return also server response data.
-       (_SSIP_Connection.set_callback): Argument `events' removed.
-       Docstring updated and extended.
-       (SSIPClient.__init__): Find out and store the client id.  Register
-       callback and turn on notifications for all supported event types.
-       (SSIPClient._callback_handler): New method.
-       (SSIPClient.speak): New keyword arguments `callback' and
-       `event_types'.  Docstring extended.  Convert `text' to `utf-8' if
-       it is a unicode instance.
-       (SSIPClient.char): Convert `char' to `utf-8' if it is a unicode
-       instance.
-       (SSIPClient.set_notification): Method removed.
-       (SSIPClient.close): Only operate on `self._conn' if it is defined.
-
-2006-11-05  Hynek Hanke  <hanke at brailcom.org>
-
-       * speechd/client.py: IMPORTANT: On initialization of the
-       connection, new lateral thread is started to handle the
-       communication. This thread is terminated when the connection is
-       closed.
-       (_SSIP_Connection._com_buffer): New attribute.
-       (_SSIP_Connection._callbacks): New attribute.
-       (_SSIP_Connection._ssip_reply_semaphore): New attribute.
-       (_SSIP_Connection._communication_thread): New attribute.
-       (_SSIP_Connection.send_command): 'or isinstance(args[0], int)'
-       added back again. This is valid SSIP.
-       (SSIPClient.set_notification): New public API function.
-
-       * speechd/_test.py
-       (SSIPClientTest.check_notification.my_callback): New test.
-
-       * speechd/client.py (_SSIP_Connection.__init__): Start the
-       self._communication method in a new thread.
-       (_SSIP_Connection._recv_response): 1->True
-       (_SSIP_Connection._recv_message): Renamed from _recv_response.
-       (SSIPClient.__del__): New destructor.
-
-2006-08-09  Hynek Hanke  <hanke at brailcom.org>
-
-       * setup.py: Use /usr/bin/env instead of /usr/bin/python
-
-       * Makefile (install): Install with correct prefix.
-
-2006-07-13  Hynek Hanke  <hanke at brailcom.org>
-
-       * Makefile: Only attempt to use distutils if python is installed.
-
-2006-07-11  Hynek Hanke  <hanke at chopin>
-
-       * speechd/client.py: Typos in docstrings.
-       (Speaker): Docstring clarification.
-       Method say() removed.
-
-2006-07-11  Tomas Cerha  <cerha at brailcom.org>
-
-       * speechd/_test.py: `Client' -> `SSIPClient'.
-       (ClientTest): -> `SSIPClientTest'.
-       (SSIPClientTest.check_escapes)
-       (SSIPClientTest.check_voice_properties) 
-       (SSIPClientTest.check_other_commands): `say' -> `speak'.
-       (SpeakerTest): New test class.
-
-       * speechd/client.py (Module): Docstring updated.
-       (Client): Class renamed to `SSIPClient'.
-       (SSIPClient): Docstring improved.
-       (SSIPClient.__init__): Don't initialize `self._current_priority'.
-       (SSIPClient.set_priority): Added docstring.  Always send the
-       command.  Don't check `self._current_priority'.
-       (SSIPClient.say): Method renamed to `speak'.
-       (SSIPClient.speak, SSIPClient.char, SSIPClient.key)
-       (SSIPClient.sound_icon): The arguent `priority' removed.  Don't
-       set the priority here.
-       (Speaker): New class.
-       (Client): New class.
-
-2006-07-10  Tomas Cerha  <cerha at brailcom.org>
-
-       * speechd/_test.py: Import `speechd' not `client'.
-       (Client): Renamed to `ClientTest'.
-       (ClientTest._client): New method.
-       (ClientTest.check_escapes, ClientTest.check_voice_properties) 
-       (ClientTest.check_other_commands): New methods.
-       (ClientTest.check_it): Method split into the above new methods.
-
-       * speechd/client.py: Don't import `string'.
-       (SSIPCommandError, SSIPDataError): Docstrings improved.
-       (_SSIP_Connection.NEWLINE): Renamed to `_NEWLINE'.
-       (_SSIP_Connection.END_OF_DATA_SINGLE): Renamed to
-       `_END_OF_DATA_MARKER'.
-       (_SSIP_Connection.END_OF_DATA_ESCAPED_SINGLE): Renamed to
-       `_END_OF_DATA_MARKER_ESCAPED'.
-       (_SSIP_Connection.END_OF_DATA_BEGIN)
-       (_SSIP_Connection.END_OF_DATA_ESCAPED_BEGIN): Constants removed.
-       (_SSIP_Connection.END_OF_DATA): Renamed to `_END_OF_DATA'.
-       (_SSIP_Connection.END_OF_DATA_ESCAPED): Renamed to
-       `_END_OF_DATA_ESCAPED'.
-       (_SSIP_Connection._readline): Docstring improved.  `self.NEWLINE'
-       -> `self._NEWLINE'.
-       (_SSIP_Connection.send_command): `self.NEWLINE' ->
-       `self._NEWLINE'.
-       (_SSIP_Connection.send_data): Use new constant names.
-       (Client.__init__): Initialize the `_priority' attribute to None.
-       (Client._set_priority): Only set the priority if it is different
-       than the last priority stored in the `_priority' attribute.  Set
-       this attribute on change.
-       (Client.char): Replace the space by `space' as required by SSIP.
-       (Client.__init__): `self._priority' renamed to
-       `self._current_priority'.
-       (Client._set_priority): Renamed to `_set_priority'.
-       (Client.set_priority): `self._priority' ->
-       `self._current_priority'.
-       (Client.char, Client.key, Client.sound_icon, Client.say):
-       `self._set_priority' -> `self.set_priority'.
-       (Client.pause): Improved docstring formatting.
-
-       * speechd/util.py: File removed.
-
-2006-06-28  Tomas Cerha  <cerha at brailcom.org>
-
-       * speechd/client.py (SSIPCommandError)
-       (_CommunicationError): Renamed to `SSIPError'.
-       (CommandError): Renamed to `SSIPCommandError'.
-       (SendDataError): Renamed to `SSIPDataError'.
-       (_SSIP_Connection.send_command): Added an assertion on the 'scope'
-       argument for certain commands.
-       (_SSIP_Connection.send_command): `CommandError' ->
-       `SSIPCommandError'.
-       (_SSIP_Connection.send_data): `SendDataError' -> `SSIPDataError'.
-       (Scope, Priority): New classes.
-       (Client): Derive from `object'.  Some doc added.
-       (Client.__init__): The `port' default value set to `None'.
-       (Client.__set_priority): Renamed to `_set_priority()'.
-       (Client._set_priority): Use the `Priority' constants for
-       assertion.
-       (__check_scope): Method removed.
-       (Client.say, Client.char, Client.key, Client.sound_icon): Use
-       `Priority' constants for default values.  `__set_priority()' ->
-       `_set_priority()'.  Docstrings updated.
-       (Client.char): Don't replace space by "space".
-       (Client.cancel, Client.stop, Client.resume, Client.set_language)
-       (Client.set_pitch, Client.set_rate, Client.set_volume)
-       (Client.set_punctuation, Client.set_spelling)
-       (Client.set_cap_let_recogn, Client.set_voice)
-       (Client.set_pause_context): Use `Scope' constants for default
-       values.  Don't call `__check_scope()'.  Docstrings updated.
-       (Client.say): Only set the priority if it's not a 'MESSAGE'.
-       (Client.set_rate, _SSIP_Connection.send_command): Use the `Scope'
-       constants for assertions.
-       (_SSIP_Connection.close): Unset the `_socket' attribute.
-       (PunctuationMode): New class.
-       (Client.__init__, Client._set_priority): Use the `Scope'
-       constants.
-       (Client.say): Don't set the priority if it is 'MESSAGE'.
-       (Client.set_pitch, Client.set_rate, Client.set_volume)
-       (Client.set_voice, Client.set_pause_context): Use `isinstance'
-       instead of comparint types.
-       (Client.set_punctuation): Use the 'PunctuationMode' constants for
-       assertions.
-
-2006-06-27  Tomas Cerha  <cerha at brailcom.org>
-
-       * speechd/client.py (_SSIP_Connection.__init__): Initialize
-       the `_buffer' attribute.
-       (_SSIP_Connection._readline): Read data from the socket using a
-       buffer, not character by character...
-       (Client.__init__): Require the `name' argument.  Changed the
-       default value of `user' to `unknown' and `component' to `default'.
-       (Client.pause): Cosmetical change.
-
-2003-11-20  Tomas Cerha  <cerha at freebsoft.org>
-
-       * speechd/client.py (Client): Changed the port number.
-
-       * speechd/_test.py (get_tests): Don't set the language.
-
-2003-07-22  Tomas Cerha  <cerha at freebsoft.org>
-
-       * speechd/_test.py (Client.check_it): Added tests for `set_rate()'
-       and `set_pitch()' methods.
-       (Client.check_it): Added test for Czech language.
-
-       * speechd/client.py: `Speech Daemon' changed to `Speech
-       Dispatcher'.
-       (_SSIP_Connection): New Class.
-       (Client.RECV_BUFFER_SIZE, Client.SSIP_NEWLINE)
-       (Client._SSIP_END_OF_DATA, Client._SSIP_END_OF_DATA_ESCAPED):
-       Constants removed.
-       (_Socket): Class removed.
-       (Client.__init__): Use `_SSIP_Conection' instead of plain socket.
-       (Client._send_command, Client._send_data, Client._recv_response):
-       Methods removed.
-       (Client.close): Close `self._conn' instead of `self._socket'.
-       (Client.say, Client.stop): Use `self._conn.send_command()' instead
-       of `self._send_command()'.
-       (Client.set_language): New method.
-       (Client.set_pitch): New method.
-       (Client.set_pitch): New method.
-       (Client.get_client_list): Use `self._conn.send_command()' instead
-       of `self._send_command()'.
-
-2003-07-17  Tomas Cerha  <cerha at freebsoft.org>
-
-       * speechd/_test.py (Client.check_it): Pass a new `user' argument
-       to `Client' constructor.
-
-       * speechd/client.py (Client.__init__._Socket): New class.
-       (Client.__init__): Use `_Socket' instead of `socket.socket'.
-       (Client._recv_response): Use `_Socket.readline()'.
-       (module): The commented out C library code removed.
-       (Client.say): Use new priority names.
-       (Client.__init__): Arguments `client_name' and `connection_name'
-       replaced by `user', `client' and `component'.  Send `self' in the
-       'SET self CLIENT_NAME' command.
-
-2003-03-30  Tomas Cerha  <cerha at brailcom.org>
-
-       * speechd/client.py (Client.SPEECH_PORT): Updated docstring.
-       (Client.RECV_BUFFER_SIZE, Client.SSIP_NEWLINE)
-       (Client._SSIP_END_OF_DATA, Client._SSIP_END_OF_DATA_ESCAPED): New
-       constants.
-       (Client._send_command, Client._send_data, Client._recv_response):
-       Use them.
-       (Client._send_data, Client._recv_response): Rewritten, to handle
-       multiline responses.  Return response data as third item of
-       returned tuple.
-       (Client.close): Don't send `BYE' command.
-       (Client.say): Don't return server response (isolate client from
-       those details). 
-       (Client.get_client_list): New method.
-
-2003-03-29  Tomas Cerha  <cerha at freebsoft.org>
-
-       * speechd/client.py (SPEECH_PORT, RECV_BUFFER_SIZE): Moved to
-       class `Client'.
-       (Client): Documentation added.
-       (Client.SPEECH_PORT, Client.RECV_BUFFER_SIZE): New constants.
-       (Client.__init__): `SPEECH_PORT' -> `self.SPEECH_PORT'
-       (Client._send_command): Cosmetic changes.
-       (Client._send_data): Cosmetic changes.
-       (Client._recv_response): Commant added. `RECV_BUFFER_SIZE' ->
-       `self.RECV_BUFFER_SIZE'.
-       (Client.close): Documentation added.
-       (Client.stop): New keyword argument `all'.
-       (Client.say): Documentation added.  Return the value of respose
-       code and message.
-
-2003-03-27  Tomas Cerha  <cerha at freebsoft.org>
-
-       * speechd/client.py: Import `string' module.
-       (SPEECH_PORT): Added docstring.
-       (RECV_BUFFER_SIZE): New constant.
-       (_CommunicationError): New class.
-       (CommandError): New class.
-       (SendDataError.data): New class.
-       (Client.__init__): Make `client_name' and `conn_name' keyword
-       args.
-       (Client._send_command): Convert `args' to strings.  Handle server
-       response.  Return resonse code and message.
-       (Client._send_data): New method.
-       (Client._recv_response): New method.
-       (Client.close): Before closing socket send a `BYE' command.
-       (Client.stop): New method.
-       (Client.say): New method.
-
-       * speechd/_test.py (Client.check_it): Test the `say()' method.
-
diff --git a/src/python/Makefile.am b/src/python/Makefile.am
deleted file mode 100644
index d54489f..0000000
--- a/src/python/Makefile.am
+++ /dev/null
@@ -1,2 +0,0 @@
-## Process this file with automake to produce Makefile.in
-SUBDIRS = speechd speechd_config
diff --git a/src/python/README b/src/python/README
deleted file mode 100644
index 39d74a3..0000000
--- a/src/python/README
+++ /dev/null
@@ -1,10 +0,0 @@
-This is a Python interface to SSIP.
-
-Full range of SSIP commands is implemented including callback handling.  See
-the section "Python API" in Speech Dispatcher documentation for more
-information.
-
-If you have any questions, suggestions, etc., feel free to contact us at the
-mailing list <speechd at lists.freebsoft.org>.
-
--- Tomas Cerha <cerha at freebsoft.org>
diff --git a/src/python/speechd/Makefile.am b/src/python/speechd/Makefile.am
deleted file mode 100644
index 59a7afe..0000000
--- a/src/python/speechd/Makefile.am
+++ /dev/null
@@ -1,21 +0,0 @@
-## Process this file with automake to produce Makefile.in
-
-speechd_pythondir = $(pyexecdir)/speechd
-speechd_python_PYTHON = __init__.py _test.py client.py
-
-nodist_speechd_python_PYTHON = paths.py
-
-edit = sed  \
-       -e 's:@address@hidden:$(bindir):g'
-
-paths.py: Makefile
-       rm -f $@
-       srcdir=; \
-       test -f ./address@hidden || srcdir=$(srcdir)/; \
-       $(edit) address@hidden > $@
-
-paths.py: $(srcdir)/paths.py.in
-
-CLEANFILES = paths.py
-
-EXTRA_DIST = paths.py.in
diff --git a/src/python/speechd/__init__.py b/src/python/speechd/__init__.py
deleted file mode 100644
index 2bb2923..0000000
--- a/src/python/speechd/__init__.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# Copyright (C) 2001, 2002 Brailcom, o.p.s.
-#
-# 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 of the License, 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
-from client import *
-
diff --git a/src/python/speechd/_test.py b/src/python/speechd/_test.py
deleted file mode 100644
index d503e81..0000000
--- a/src/python/speechd/_test.py
+++ /dev/null
@@ -1,136 +0,0 @@
-#!/usr/bin/env python
-
-# Copyright (C) 2003, 2006, 2007 Brailcom, o.p.s.
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public Licensex1 as published by
-# the Free Software Foundation; either version 2 of the License, 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
-import unittest
-import time
-
-from client import PunctuationMode, CallbackType, SSIPClient, Scope, Speaker
-
-
-class _SSIPClientTest(unittest.TestCase):
-        
-    def setUp(self):
-        self._client = SSIPClient('test')
-        self._client.set_language('en')
-        self._client.set_rate(30)
-
-    def tearDown(self):
-        self._client.close()
-
-class AutomaticTest(_SSIPClientTest):
-    """A set of tests which may be evaluated automatically.
-
-    Please put all tests which require a user to listen to their output to the
-    VoiceTest below.
-
-    """
-    def test_callbacks(self):
-        # TODO: This needs to be fixed. There is no guarantee that
-        # the message will start in one second nor is there any
-        # guarantee that it will start at all. It can be interrupted
-        # by other applications etc. Also there is no guarantee that
-        # the cancel will arrive on time and the end callback will be
-        # received on time. Also the combination cancel/end does not have
-        # to work as expected and SD and the interface can still be ok.
-        # -- Hynek Hanke
-        self._client.set_output_module('flite')
-        called = {CallbackType.BEGIN: [],
-                  CallbackType.CANCEL: [],
-                  CallbackType.END: []}
-        self._client.speak("This message should get interrupted.  It is "
-                           "hopefully long enough to last more than 1 second.",
-                           callback=lambda type: called[type].append('msg1'))
-        self._client.speak("This second message should not be spoken at all.",
-                           callback=lambda type: called[type].append('msg2'))
-        time.sleep(1)
-        self._client.cancel()
-        self._client.speak("Hi.",
-                           callback=lambda type: called[type].append('msg3'))
-        # Wait for pending events...
-        time.sleep(3)
-        started, canceled, ended = [called[t] for t in (CallbackType.BEGIN,
-                                                        CallbackType.CANCEL,
-                                                        CallbackType.END)]
-        assert started == ['msg1', 'msg3'] and ended == ['msg3'] and \
-               'msg1' in canceled and 'msg2' in canceled and \
-               'msg3' not in canceled, \
-               (called,
-                "This failure only indicates a possible error.  The test "
-                "depends on proper timing and results may warry depending "
-                "on the used output module and other conditions.  See the "
-                "code of this test method if you want to investigate "
-                "further.")
-
-    
-
-class VoiceTest(_SSIPClientTest):
-    """This set of tests requires a user to listen to it.
-
-    The success or failure of the tests defined here can not be detected
-    automatically.
-
-    """
-    
-    def test_escapes(self):
-        c = self._client
-        c.speak("Testing data escapes:")
-        c.set_punctuation(PunctuationMode.ALL)
-        c.speak(".")
-        c.speak("Marker at the end.\r\n.\r\n")
-        c.speak(".\r\nMarker at the beginning.")
-    
-    def test_voice_properties(self):
-        c = self._client
-        c.speak("Testing voice properties:")
-        c.set_pitch(-100)
-        c.speak("I am fat Billy")
-        c.set_pitch(100)
-        c.speak("I am slim Willy")
-        c.set_pitch(0)
-        c.set_rate(100)
-        c.speak("I am quick Dick.")
-        c.set_rate(-80)
-        c.speak("I am slow Joe.")
-        c.set_rate(0)
-        c.set_pitch(100)
-        c.set_volume(-50)
-        c.speak("I am quiet Mariette.")
-        c.set_volume(100)
-        c.speak("I am noisy Daisy.")
-
-    def test_other_commands(self):
-        c = self._client
-        c.speak("Testing other commands:")
-        c.char("a")
-        c.key("shift_b")
-        c.sound_icon("empty")
-        
-    def test_lists(self):
-         c = self._client
-         for module in  c.list_output_modules():
-             c.set_output_module(module)
-             print "**", module
-             c.speak(module +"using default voice")
-             for name, lang, dialect in c.list_synthesis_voices():
-                 print " -", module, name, lang, dialect
-                 c.set_synthesis_voice(name)
-                 c.speak(module +" using voice "+ name)
-        
-
-if __name__ == '__main__':
-    unittest.main()
diff --git a/src/python/speechd/client.py b/src/python/speechd/client.py
deleted file mode 100644
index 13a9c7e..0000000
--- a/src/python/speechd/client.py
+++ /dev/null
@@ -1,1125 +0,0 @@
-# Copyright (C) 2003-2008 Brailcom, o.p.s.
-#
-# 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 of the License, 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
-"""Python API to Speech Dispatcher
-
-Basic Python client API to Speech Dispatcher is provided by the 'SSIPClient'
-class.  This interface maps directly to available SSIP commands and logic.
-
-A more convenient interface is provided by the 'Speaker' class.
-
-"""
-
-#TODO: Blocking variants for speak, char, key, sound_icon.
-
-import socket, sys, os, subprocess, time, tempfile
-
-try:
-    import threading
-except:
-    import dummy_threading as threading
-
-import paths
-    
-class CallbackType(object):
-    """Constants describing the available types of callbacks"""
-    INDEX_MARK = 'index_marks'
-    """Index mark events are reported when the place they were
-    included into the text by the client application is reached
-    when speaking them"""
-    BEGIN = 'begin'
-    """The begin event is reported when Speech Dispatcher starts
-    actually speaking the message."""
-    END = 'end'
-    """The end event is reported after the message has terminated and
-    there is no longer any sound from it being produced"""
-    CANCEL = 'cancel'
-    """The cancel event is reported when a message is canceled either
-    on request of the user, because of prioritization of messages or
-    due to an error"""
-    PAUSE = 'pause'
-    """The pause event is reported after speaking of a message
-    was paused. It no longer produces any audio."""
-    RESUME = 'resume'
-    """The resume event is reported right after speaking of a message
-    was resumed after previous pause."""
-
-class SSIPError(Exception):
-    """Common base class for exceptions during SSIP communication."""
-    
-class SSIPCommunicationError(SSIPError):
-    """Exception raised when trying to operate on a closed connection."""
-
-    _additional_exception = None
-
-    def __init__(self, description=None, original_exception=None, **kwargs):
-        self._original_exception = original_exception
-        self._description = description
-        super(SSIPError, self).__init__(**kwargs)
-
-    def original_exception(self):
-        """Return the original exception if any
-
-        If this exception is secondary, being caused by a lower
-        level exception, return this original exception, otherwise
-        None"""
-        return self._original_exception
-
-    def set_additional_exception(self, exception):
-        """Set an additional exception
-        
-        See method additional_exception().
-        """
-        self._additional_exception = exception
-
-    def additional_exception(self):
-        """Return an additional exception
-        
-        Additional exceptions araise from failed attempts to resolve
-        the former problem"""
-        return self._additional_exception
-
-    def description(self):
-        """Return error description"""
-        return self._description
-
-    def __str__(self):
-        msgs = []
-        if self.description():
-            msgs.append(self.description())
-        if self.original_exception:
-            msgs.append("Original error: " + str(self.original_exception()))
-        if self.additional_exception:
-            msgs.append("Additional error: " + 
str(self.additional_exception()))
-        return "\n".join(msgs)
-
-class SSIPResponseError(Exception):
-    def __init__(self, code, msg, data):
-        Exception.__init__(self, "%s: %s" % (code, msg))
-        self._code = code
-        self._msg = msg
-        self._data = data
-
-    def code(self):
-        """Return the server response error code as integer number."""
-        return self._code
-        
-    def msg(self):
-        """Return server response error message as string."""
-        return self._msg
-
-
-class SSIPCommandError(SSIPResponseError):
-    """Exception raised on error response after sending command."""
-
-    def command(self):
-        """Return the command string which resulted in this error."""
-        return self._data
-
-    
-class SSIPDataError(SSIPResponseError):
-    """Exception raised on error response after sending data."""
-
-    def data(self):
-        """Return the data which resulted in this error."""
-        return self._data
-
-    
-class SpawnError(Exception):
-    """Indicates failure in server autospawn."""
-
-class CommunicationMethod(object):
-    """Constants describing the possible methods of connection to server."""
-    UNIX_SOCKET = 'unix_socket'
-    """Unix socket communication using a filesystem path"""
-    INET_SOCKET = 'inet_socket'
-    """Inet socket communication using a host and port"""
-
-class _SSIP_Connection(object):
-    """Implemantation of low level SSIP communication."""
-    
-    _NEWLINE = "\r\n"
-    _END_OF_DATA_MARKER = '.'
-    _END_OF_DATA_MARKER_ESCAPED = '..'
-    _END_OF_DATA = _NEWLINE + _END_OF_DATA_MARKER + _NEWLINE
-    _END_OF_DATA_ESCAPED = _NEWLINE + _END_OF_DATA_MARKER_ESCAPED + _NEWLINE
-    # Constants representing \r\n. and \r\n..
-    _RAW_DOTLINE = _NEWLINE + _END_OF_DATA_MARKER
-    _ESCAPED_DOTLINE = _NEWLINE + _END_OF_DATA_MARKER_ESCAPED
-
-    _CALLBACK_TYPE_MAP = {700: CallbackType.INDEX_MARK,
-                          701: CallbackType.BEGIN,
-                          702: CallbackType.END,
-                          703: CallbackType.CANCEL,
-                          704: CallbackType.PAUSE,
-                          705: CallbackType.RESUME,
-                          }
-
-    def __init__(self, communication_method, socket_path, host, port):
-        """Init connection: open the socket to server,
-        initialize buffers, launch a communication handling
-        thread.
-        """
-
-        if communication_method == CommunicationMethod.UNIX_SOCKET:
-            socket_family = socket.AF_UNIX
-            socket_connect_args = socket_path
-        elif communication_method == CommunicationMethod.INET_SOCKET:
-            assert host and port
-            socket_family = socket.AF_INET
-            socket_connect_args = (socket.gethostbyname(host), port)
-        else:
-            raise ValueError("Unsupported communication method")
-
-        try:
-            self._socket = socket.socket(socket_family, socket.SOCK_STREAM)
-            self._socket.connect(socket_connect_args)
-        except socket.error, ex:
-            raise SSIPCommunicationError("Can't open socket using method "
-                                         + communication_method,
-                                         original_exception = ex)
-
-        self._buffer = ""
-        self._com_buffer = []
-        self._callback = None
-        self._ssip_reply_semaphore = threading.Semaphore(0)
-        self._communication_thread = \
-                threading.Thread(target=self._communication, kwargs={},
-                                 name="SSIP client communication thread")
-        self._communication_thread.start()
-    
-    def close(self):
-        """Close the server connection, destroy the communication thread."""
-        # Read-write shutdown here is necessary, otherwise the socket.recv()
-        # function in the other thread won't return at last on some platforms.
-        try:
-            self._socket.shutdown(socket.SHUT_RDWR)
-        except socket.error:
-            pass
-        self._socket.close()
-        # Wait for the other thread to terminate
-        self._communication_thread.join()
-        
-    def _communication(self):
-        """Handle incomming socket communication.
-
-        Listens for all incomming communication on the socket, dispatches
-        events and puts all other replies into self._com_buffer list in the
-        already parsed form as (code, msg, data).  Each time a new item is
-        appended to the _com_buffer list, the corresponding semaphore
-        'self._ssip_reply_semaphore' is incremented.
-
-        This method is designed to run in a separate thread.  The thread can be
-        interrupted by closing the socket on which it is listening for
-        reading."""
-
-        while True:
-            try:
-                code, msg, data = self._recv_message()
-            except IOError:
-                # If the socket has been closed, exit the thread
-                sys.exit()
-            if code/100 != 7:
-                # This is not an index mark nor an event
-                self._com_buffer.append((code, msg, data))
-                self._ssip_reply_semaphore.release()
-                continue
-            # Ignore the event if no callback function has been registered.
-            if self._callback is not None:
-                type = self._CALLBACK_TYPE_MAP[code]
-                if type == CallbackType.INDEX_MARK:
-                    kwargs = {'index_mark': data[2]}
-                else:
-                    kwargs = {}
-                # Get message and client ID of the event
-                msg_id, client_id = map(int, data[:2])
-                self._callback(msg_id, client_id, type, **kwargs)
-                
-                
-    def _readline(self):
-        """Read one whole line from the socket.
-
-        Blocks until the line delimiter ('_NEWLINE') is read.
-        
-        """
-        pointer = self._buffer.find(self._NEWLINE)
-        while pointer == -1:
-            try:
-                d = self._socket.recv(1024)
-            except:
-                raise IOError
-            if len(d) == 0:
-                raise IOError
-            self._buffer += d
-            pointer = self._buffer.find(self._NEWLINE)
-        line = self._buffer[:pointer]
-        self._buffer = self._buffer[pointer+len(self._NEWLINE):]
-        return line
-
-    def _recv_message(self):
-        """Read server response or a callback
-        and return the triplet (code, msg, data)."""
-        data = []
-        c = None
-        while True:
-            line = self._readline()
-            assert len(line) >= 4, "Malformed data received from server!"
-            code, sep, text = line[:3], line[3], line[4:]
-            assert code.isalnum() and (c is None or code == c) and \
-                   sep in ('-', ' '), "Malformed data received from server!"
-            if sep == ' ':
-                msg = text
-                return int(code), msg, tuple(data)
-            data.append(text)
-
-    def _recv_response(self):
-        """Read server response from the communication thread
-        and return the triplet (code, msg, data)."""
-        # TODO: This check is dumb but seems to work.  The main thread
-        # hangs without it, when the Speech Dispatcher connection is lost.
-        if not self._communication_thread.isAlive():
-            raise SSIPCommunicationError
-        self._ssip_reply_semaphore.acquire()
-        # The list is sorted, read the first item
-        response = self._com_buffer[0]
-        del self._com_buffer[0]
-        return response
-
-    def send_command(self, command, *args):
-        """Send SSIP command with given arguments and read server response.
-
-        Arguments can be of any data type -- they are all stringified before
-        being sent to the server.
-
-        Returns a triplet (code, msg, data), where 'code' is a numeric SSIP
-        response code as an integer, 'msg' is an SSIP rsponse message as string
-        and 'data' is a tuple of strings (all lines of response data) when a
-        response contains some data.
-        
-        'SSIPCommandError' is raised in case of non 2xx return code.  See SSIP
-        documentation for more information about server responses and codes.
-
-        'IOError' is raised when the socket was closed by the remote side.
-        
-        """
-        if __debug__:
-            if command in ('SET', 'CANCEL', 'STOP',):
-                assert args[0] in (Scope.SELF, Scope.ALL) \
-                       or isinstance(args[0], int)
-        cmd = ' '.join((command,) + tuple(map(str, args)))
-        try:
-            self._socket.send(cmd + self._NEWLINE)
-        except socket.error:
-            raise SSIPCommunicationError("Speech Dispatcher connection lost.")
-        code, msg, data = self._recv_response()
-        if code/100 != 2:
-            raise SSIPCommandError(code, msg, cmd)
-        return code, msg, data
-        
-    def send_data(self, data):
-        """Send multiline data and read server response.
-
-        Returned value is the same as for 'send_command()' method.
-
-        'SSIPDataError' is raised in case of non 2xx return code. See SSIP
-        documentation for more information about server responses and codes.
-        
-        'IOError' is raised when the socket was closed by the remote side.
-        
-        """
-        # Escape the end-of-data marker even if present at the beginning
-        # The start of the string is also the start of a line.
-        if data.startswith(self._END_OF_DATA_MARKER):
-            l = len(self._END_OF_DATA_MARKER)
-            data = self._END_OF_DATA_MARKER_ESCAPED + data[l:]
-
-        # Escape the end of data marker at the start of each subsequent
-        # line.  We can do that by simply replacing \r\n. with \r\n..,
-        # since the start of a line is immediately preceded by \r\n,
-        # when the line is not the beginning of the string.
-        data = data.replace(self._RAW_DOTLINE, self._ESCAPED_DOTLINE)
-
-        try:
-            self._socket.send(data + self._END_OF_DATA)
-        except socket.error:
-            raise SSIPCommunicationError("Speech Dispatcher connection lost.")
-        code, msg, response_data = self._recv_response()
-        if code/100 != 2:
-            raise SSIPDataError(code, msg, data)
-        return code, msg, response_data
-
-    def set_callback(self, callback):
-        """Register a callback function for handling asynchronous events.
-
-        Arguments:
-          callback -- a callable object (function) which will be called to
-            handle asynchronous events (arguments described below).  Passing
-            `None' results in removing the callback function and ignoring
-            events.  Just one callback may be registered.  Attempts to register
-            a second callback will result in the former callback being
-            replaced.
-
-        The callback function must accept three positional arguments
-        ('message_id', 'client_id', 'event_type') and an optional keyword
-        argument 'index_mark' (when INDEX_MARK events are turned on).
-
-        Note, that setting the callback function doesn't turn the events on.
-        The user is responsible to turn them on by sending the appropriate `SET
-        NOTIFICATION' command.
-
-        """
-        self._callback = callback
-
-class _CallbackHandler(object):
-    """Internal object which handles callbacks."""
-
-    def __init__(self, client_id):
-        self._client_id = client_id
-        self._callbacks = {}
-        self._lock = threading.Lock()
-
-    def __call__(self, msg_id, client_id, type, **kwargs):
-        if client_id != self._client_id:
-            # TODO: does that ever happen?
-            return
-        self._lock.acquire()
-        try:
-            try:
-                callback, event_types = self._callbacks[msg_id]
-            except KeyError:
-                pass
-            else:
-                if event_types is None or type in event_types:
-                    callback(type, **kwargs)
-                if type in (CallbackType.END, CallbackType.CANCEL):
-                    del self._callbacks[msg_id]
-        finally:
-            self._lock.release()
-
-    def add_callback(self, msg_id,  callback, event_types):
-        self._lock.acquire()
-        try:
-            self._callbacks[msg_id] = (callback, event_types)
-        finally:
-            self._lock.release()
-
-class Scope(object):
-    """An enumeration of valid SSIP command scopes.
-
-    The constants of this class should be used to specify the 'scope' argument
-    for the 'Client' methods.
-
-    """    
-    SELF = 'self'
-    """The command (mostly a setting) applies to current connection only."""
-    ALL = 'all'
-    """The command applies to all current Speech Dispatcher connections."""
-
-    
-class Priority(object):
-    """An enumeration of valid SSIP message priorities.
-
-    The constants of this class should be used to specify the 'priority'
-    argument for the 'Client' methods.  For more information about message
-    priorities and their interaction, see the SSIP documentation.
-    
-    """
-    IMPORTANT = 'important'
-    TEXT = 'text'
-    MESSAGE = 'message'
-    NOTIFICATION = 'notification'
-    PROGRESS = 'progress'
-
-    
-class PunctuationMode(object):
-    """Constants for selecting a punctuation mode.
-
-    The mode determines which characters should be read.
-
-    """
-    ALL = 'all'
-    """Read all punctuation characters."""
-    NONE = 'none'
-    """Don't read any punctuation character at all."""
-    SOME = 'some'
-    """Only the user-defined punctuation characters are read.
-
-    The set of characters is specified in Speech Dispatcher configuration.
-
-    """
-
-class DataMode(object):
-    """Constants specifying the type of data contained within messages
-    to be spoken.
-
-    """
-    TEXT = 'text'
-    """Data is plain text."""
-    SSML = 'ssml'
-    """Data is SSML (Speech Synthesis Markup Language)."""
-
-
-class SSIPClient(object):
-    """Basic Speech Dispatcher client interface.
-
-    This class provides a Python interface to Speech Dispatcher functionality
-    over an SSIP connection.  The API maps directly to available SSIP commands.
-    Each connection to Speech Dispatcher is represented by one instance of this
-    class.
-    
-    Many commands take the 'scope' argument, thus it is shortly documented
-    here.  It is either one of 'Scope' constants or a number of connection.  By
-    specifying the connection number, you are applying the command to a
-    particular connection.  This feature is only meant to be used by Speech
-    Dispatcher control application, however.  More datails can be found in
-    Speech Dispatcher documentation.
-
-    """
-    
-    DEFAULT_HOST = '127.0.0.1'
-    """Default host for server connections."""
-    DEFAULT_PORT = 6560
-    """Default port number for server connections."""
-    DEFAULT_SOCKET_PATH = "~/.speech-dispatcher/speechd.sock"
-    """Default name of the communication unix socket"""
-    
-    def __init__(self, name, component='default', user='unknown', address=None,
-                 autospawn=None,
-                 # Deprecated ->
-                 host=None, port=None, method=None, socket_path=None):
-        """Initialize the instance and connect to the server.
-
-        Arguments:
-          name -- client identification string
-          component -- connection identification string.  When one client opens
-            multiple connections, this can be used to identify each of them.
-          user -- user identification string (user name).  When multi-user
-            acces is expected, this can be used to identify their connections.
-          address -- server address as specified in Speech Dispatcher
-            documentation (e.g. 
"unix:/home/joe/.speech-dispatcher/speechd.sock"
-            or "inet:192.168.0.85:6561")
-          autospawn -- a flag to specify whether the library should
-            try to start the server if it determines its not already
-            running or not
-
-        Deprecated arguments:
-          method -- communication method to use, one of the constants defined 
in class
-            CommunicationMethod
-          socket_path -- for CommunicationMethod.UNIX_SOCKET, socket
-            path in filesystem. By default, this is 
~/.speech-dispatcher/speechd.sock
-            where `~' is the users home directory as determined from the system
-            defaults and from the $HOMEDIR environment variable.
-          host -- for CommunicationMethod.INET_SOCKET, server hostname
-            or IP address as a string.  If None, the default value is
-            taken from SPEECHD_HOST environment variable (if it
-            exists) or from the DEFAULT_HOST attribute of this class.
-          port -- for CommunicationMethod.INET_SOCKET method, server
-            port as number or None.  If None, the default value is
-            taken from SPEECHD_PORT environment variable (if it
-            exists) or from the DEFAULT_PORT attribute of this class.
-         
-        For more information on client identification strings see Speech
-        Dispatcher documentation.
-        """
-
-        # Resolve connection parameters:
-        connection_args = {'communication_method': 
CommunicationMethod.UNIX_SOCKET,
-                           'socket_path': 
os.path.expanduser(self.DEFAULT_SOCKET_PATH),
-                           'host': self.DEFAULT_HOST,
-                           'port': self.DEFAULT_PORT,
-                           }
-        # Respect address method argument and SPEECHD_ADDRESS environemt 
variable
-        _address = address or os.environ.get("SPEECHD_ADDRESS")        
-
-        if _address:
-            
connection_args.update(self._connection_arguments_from_address(_address))
-        # Respect the old (deprecated) key arguments and environment variables
-        # TODO: Remove this section in 0.8 release
-        else:
-            # Read the environment variables
-            env_speechd_host = os.environ.get("SPEECHD_HOST")
-            try:
-                env_speechd_port = int(os.environ.get("SPEECHD_PORT"))
-            except:
-                env_speechd_port = None
-            env_speechd_socket_path = os.environ.get("SPEECHD_SOCKET")
-            # Prefer old (deprecated) function arguments, but if
-            # not specified and old (deprecated) environment variable
-            # is set, use the value of the environment variable
-            if method:
-                connection_args['method'] = method
-            if port:
-                connection_args['port'] = port
-            elif env_speechd_port:
-                connection_args['port'] = env_speechd_port
-            if socket_path:
-                connection_args['socket_path'] = socket_path
-            elif env_speechd_socket_path:
-                connection_args['socket_path'] = env_speechd_socket_path
-        self._connect_with_autospawn(connection_args, autospawn)
-        self._initialize_connection(user, name, component)
-
-    def _connect_with_autospawn(self, connection_args, autospawn):
-        """Establish new connection (and/or autospawn server)"""
-        try:
-            self._conn = _SSIP_Connection(**connection_args)
-        except SSIPCommunicationError, ce:
-            # Suppose server might not be running, try the autospawn mechanism
-            if autospawn != False:
-                # Autospawn is however not guaranteed to start the server. The 
server
-                # will decide, based on it's configuration, whether to honor 
the request.
-                try:
-                    self._server_spawn(connection_args)
-                except SpawnError, se:
-                    ce.set_additional_exception(se)
-                    raise ce
-                self._conn = _SSIP_Connection(**connection_args)
-            else:
-                raise
-
-    def _initialize_connection(self, user, name, component):
-        """Initialize connection -- Set client name, get id, register 
callbacks etc."""
-        full_name = '%s:%s:%s' % (user, name, component)
-        self._conn.send_command('SET', Scope.SELF, 'CLIENT_NAME', full_name)
-        code, msg, data = self._conn.send_command('HISTORY', 'GET', 
'CLIENT_ID')
-        self._client_id = int(data[0])
-        self._callback_handler = _CallbackHandler(self._client_id)
-        self._conn.set_callback(self._callback_handler)
-        for event in (CallbackType.INDEX_MARK,
-                      CallbackType.BEGIN,
-                      CallbackType.END,
-                      CallbackType.CANCEL,
-                      CallbackType.PAUSE,
-                      CallbackType.RESUME):
-            self._conn.send_command('SET', 'self', 'NOTIFICATION', event, 'on')
-
-    def _connection_arguments_from_address(self, address):
-        """Parse a Speech Dispatcher address line and return a dictionary
-        of connection arguments"""
-        connection_args = {}
-        address_params = address.split(":")
-        try:
-            _method = address_params[0]
-        except:
-            raise SSIPCommunicationErrror("Wrong format of server address")
-        connection_args['communication_method'] = _method
-        if _method == CommunicationMethod.UNIX_SOCKET:
-            try:
-                connection_args['socket_path'] = address_params[1]
-            except IndexError:
-                pass # The additional parameters was not set, let's stay with 
defaults
-        elif _method == CommunicationMethod.INET_SOCKET:
-            try:
-                connection_args['host'] = address_params[1]
-                connection_args['port'] = int(address_params[2])
-            except ValueError: # Failed conversion to int
-                raise SSIPCommunicationError("Third parameter of inet_socket 
address must be a port number")
-            except IndexError:
-                pass # The additional parameters was not set, let's stay with 
defaults
-        else:
-            raise SSIPCommunicationError("Unknown communication method in 
address.");
-        return connection_args
-    
-    def __del__(self):
-        """Close the connection"""
-        self.close()
-
-    def _server_spawn(self, connection_args):
-        """Attempts to spawn the speech-dispatcher server."""
-        # Check whether we are not connecting to a remote host
-        # TODO: This is a hack. inet sockets specific code should
-        # belong to _SSIPConnection. We do not however have an _SSIPConnection
-        # yet.
-        if connection_args['communication_method'] == 'inet_socket':
-            addrinfos = socket.getaddrinfo(connection_args['host'],
-                                           connection_args['port'])
-            # Check resolved addrinfos for presence of localhost
-            ip_addresses = [addrinfo[4][0] for addrinfo in addrinfos]
-            localhost=False
-            for ip in ip_addresses:
-                if ip.startswith("127.") or ip == "::1":
-                    connection_args['host'] = ip
-                    localhost=True
-            if not localhost:
-                # The hostname didn't resolve on localhost in neither case,
-                # do not spawn server on localhost...
-                raise SpawnError(
-                    "Can't start server automatically (autospawn), requested 
address %s "
-                    "resolves on %s which seems to be a remote host. You must 
start the "
-                    "server manually or choose another connection address." % 
(connection_args['host'],
-                                                                               
str(ip_addresses),))
-        if os.path.exists(paths.SPD_SPAWN_CMD):
-            connection_params = []
-            for param, value in connection_args.items():
-                if param not in ["host",]:
-                    connection_params += ["--"+param.replace("_","-"), 
str(value)]
-
-            server = subprocess.Popen([paths.SPD_SPAWN_CMD, 
"--spawn"]+connection_params,
-                                      stdin=None, stdout=subprocess.PIPE, 
stderr=subprocess.PIPE)
-            stdout_reply, stderr_reply = server.communicate()
-            retcode = server.wait()
-            if retcode != 0:
-                raise SpawnError("Server refused to autospawn, stating this 
reason: %s" % (stderr_reply,))
-            return server.pid
-        else:
-            raise SpawnError("Can't find Speech Dispatcher spawn command %s"
-                                         % (paths.SPD_SPAWN_CMD,))
-
-    def set_priority(self, priority):
-        """Set the priority category for the following messages.
-
-        Arguments:
-          priority -- one of the 'Priority' constants.
-
-        """
-        assert priority in (Priority.IMPORTANT, Priority.MESSAGE,
-                            Priority.TEXT, Priority.NOTIFICATION,
-                            Priority.PROGRESS), priority
-        self._conn.send_command('SET', Scope.SELF, 'PRIORITY', priority)
-
-    def set_data_mode(self, value):
-        """Set the data mode for further speech commands.
-
-        Arguments:
-          value - one of the constants defined by the DataMode class.
-
-        """
-        if value == DataMode.SSML:
-            ssip_val = 'on'
-        elif value == DataMode.TEXT:
-            ssip_val = 'off'
-        else:
-            raise ValueError(
-                'Value "%s" is not one of the constants from the DataMode 
class.' % \
-                    value)
-        self._conn.send_command('SET', Scope.SELF, 'SSML_MODE', ssip_val)
-
-    def speak(self, text, callback=None, event_types=None):
-        """Say given message.
-
-        Arguments:
-          text -- message text to be spoken.  This may be either a UTF-8
-            encoded byte string or a Python unicode string.
-          callback -- a callback handler for asynchronous event notifications.
-            A callable object (function) which accepts one positional argument
-            `type' and one keyword argument `index_mark'.  See below for more
-            details.
-          event_types -- a tuple of event types for which the callback should
-            be called.  Each item must be one of `CallbackType' constants.
-            None (the default value) means to handle all event types.  This
-            argument is irrelevant when `callback' is not used.
-
-        The callback function will be called whenever one of the events occurs.
-        The event type will be passed as argument.  Its value is one of the
-        `CallbackType' constants.  In case of an index mark event, additional
-        keyword argument `index_mark' will be passed and will contain the index
-        mark identifier as specified within the text.
-
-        The callback function should not perform anything complicated and is
-        not allowed to issue any further SSIP client commands.  An attempt to
-        do so would lead to a deadlock in SSIP communication.
-
-        This method is non-blocking;  it just sends the command, given
-        message is queued on the server and the method returns immediately.
-
-        """
-        self._conn.send_command('SPEAK')
-        if isinstance(text, unicode):
-            text = text.encode('utf-8')
-        result = self._conn.send_data(text)
-        if callback:
-            msg_id = int(result[2][0])
-            # TODO: Here we risk, that the callback arrives earlier, than we
-            # add the item to `self._callback_handler'.  Such a situation will
-            # lead to the callback being ignored.
-            self._callback_handler.add_callback(msg_id, callback, event_types)
-        return result
-
-    def char(self, char):
-        """Say given character.
-
-        Arguments:
-          char -- a character to be spoken.  Either a Python unicode string or
-            a UTF-8 encoded byte string.
-
-        This method is non-blocking;  it just sends the command, given
-        message is queued on the server and the method returns immediately.
-
-        """
-        if isinstance(char, unicode):
-            char = char.encode('utf-8')
-        self._conn.send_command('CHAR', char.replace(' ', 'space'))
-        
-    def key(self, key):
-        """Say given key name.
-
-        Arguments:
-          key -- the key name (as defined in SSIP); string.
-
-        This method is non-blocking;  it just sends the command, given
-        message is queued on the server and the method returns immediately.
-
-        """
-        self._conn.send_command('KEY', key)
-
-    def sound_icon(self, sound_icon):
-        """Output given sound_icon.
-
-        Arguments:
-          sound_icon -- the name of the sound icon as defined by SSIP; string.
-
-        This method is non-blocking; it just sends the command, given message
-        is queued on the server and the method returns immediately.
-
-        """        
-        self._conn.send_command('SOUND_ICON', sound_icon)
-                    
-    def cancel(self, scope=Scope.SELF):
-        """Immediately stop speaking and discard messages in queues.
-
-        Arguments:
-          scope -- see the documentation of this class.
-            
-        """
-        self._conn.send_command('CANCEL', scope)
-
-
-    def stop(self, scope=Scope.SELF):
-        """Immediately stop speaking the currently spoken message.
-
-        Arguments:
-          scope -- see the documentation of this class.
-        
-        """
-        self._conn.send_command('STOP', scope)
-
-    def pause(self, scope=Scope.SELF):
-        """Pause speaking and postpone other messages until resume.
-
-        This method is non-blocking.  However, speaking can continue for a
-        short while even after it's called (typically to the end of the
-        sentence).
-
-        Arguments:
-          scope -- see the documentation of this class.
-        
-        """
-        self._conn.send_command('PAUSE', scope)
-
-    def resume(self, scope=Scope.SELF):
-        """Resume speaking of the currently paused messages.
-
-        This method is non-blocking.  However, speaking can continue for a
-        short while even after it's called (typically to the end of the
-        sentence).
-
-        Arguments:
-          scope -- see the documentation of this class.
-        
-        """
-        self._conn.send_command('RESUME', scope)
-
-    def list_output_modules(self):
-        """Return names of all active output modules as a tuple of strings."""
-        code, msg, data = self._conn.send_command('LIST', 'OUTPUT_MODULES')
-        return data
-
-    def list_synthesis_voices(self):
-        """Return names of all available voices for the current output module.
-
-        Returns a tuple of tripplets (name, language, dialect).
-
-        'name' is a string, 'language' is an ISO 639-1 Alpha-2 language code
-        and 'dialect' is a string.  Language and dialect may be None.
-
-        """
-        try:
-            code, msg, data = self._conn.send_command('LIST', 
'SYNTHESIS_VOICES')
-        except SSIPCommandError:
-            return ()
-        def split(item):
-            name, lang, dialect = tuple(item.rsplit(' ', 3))
-            return (name, lang or None, dialect or None)
-        return tuple([split(item) for item in data])
-
-    def set_language(self, language, scope=Scope.SELF):
-        """Switch to a particular language for further speech commands.
-
-        Arguments:
-          language -- two letter language code according to RFC 1776 as string.
-          scope -- see the documentation of this class.
-            
-        """
-        assert isinstance(language, str) and len(language) == 2
-        self._conn.send_command('SET', scope, 'LANGUAGE', language)
-
-    def set_output_module(self, name, scope=Scope.SELF):
-        """Switch to a particular output module.
-
-        Arguments:
-          name -- module (string) as returned by 'list_output_modules()'.
-          scope -- see the documentation of this class.
-        
-        """
-        self._conn.send_command('SET', scope, 'OUTPUT_MODULE', name)
-
-    def set_pitch(self, value, scope=Scope.SELF):
-        """Set the pitch for further speech commands.
-
-        Arguments:
-          value -- integer value within the range from -100 to 100, with 0
-            corresponding to the default pitch of the current speech synthesis
-            output module, lower values meaning lower pitch and higher values
-            meaning higher pitch.
-          scope -- see the documentation of this class.
-          
-        """
-        assert isinstance(value, int) and -100 <= value <= 100, value
-        self._conn.send_command('SET', scope, 'PITCH', value)
-
-    def set_rate(self, value, scope=Scope.SELF):
-        """Set the speech rate (speed) for further speech commands.
-
-        Arguments:
-          value -- integer value within the range from -100 to 100, with 0
-            corresponding to the default speech rate of the current speech
-            synthesis output module, lower values meaning slower speech and
-            higher values meaning faster speech.
-          scope -- see the documentation of this class.
-            
-        """
-        assert isinstance(value, int) and -100 <= value <= 100
-        self._conn.send_command('SET', scope, 'RATE', value)
-
-    def set_volume(self, value, scope=Scope.SELF):
-        """Set the speech volume for further speech commands.
-
-        Arguments:
-          value -- integer value within the range from -100 to 100, with 100
-            corresponding to the default speech volume of the current speech
-            synthesis output module, lower values meaning softer speech.
-          scope -- see the documentation of this class.
-            
-        """
-        assert isinstance(value, int) and -100 <= value <= 100
-        self._conn.send_command('SET', scope, 'VOLUME', value)
-
-    def set_punctuation(self, value, scope=Scope.SELF):
-        """Set the punctuation pronounciation level.
-
-        Arguments:
-          value -- one of the 'PunctuationMode' constants.
-          scope -- see the documentation of this class.
-            
-        """
-        assert value in (PunctuationMode.ALL, PunctuationMode.SOME,
-                         PunctuationMode.NONE), value
-        self._conn.send_command('SET', scope, 'PUNCTUATION', value)
-
-    def set_spelling(self, value, scope=Scope.SELF):
-        """Toogle the spelling mode or on off.
-
-        Arguments:
-          value -- if 'True', all incomming messages will be spelled
-            instead of being read as normal words. 'False' switches
-            this behavior off.
-          scope -- see the documentation of this class.
-            
-        """
-        assert value in [True, False]
-        if value == True:
-            self._conn.send_command('SET', scope, 'SPELLING', "on")
-        else:
-            self._conn.send_command('SET', scope, 'SPELLING', "off")
-
-    def set_cap_let_recogn(self, value, scope=Scope.SELF):
-        """Set capital letter recognition mode.
-
-        Arguments:
-          value -- one of 'none', 'spell', 'icon'. None means no signalization
-            of capital letters, 'spell' means capital letters will be spelled
-            with a syntetic voice and 'icon' means that the capital-letter icon
-            will be prepended before each capital letter.
-          scope -- see the documentation of this class.
-            
-        """
-        assert value in ("none", "spell", "icon")
-        self._conn.send_command('SET', scope, 'CAP_LET_RECOGN', value)
-
-    def set_voice(self, value, scope=Scope.SELF):
-        """Set voice by a symbolic name.
-
-        Arguments:
-          value -- one of the SSIP symbolic voice names: 'MALE1' .. 'MALE3',
-            'FEMALE1' ... 'FEMALE3', 'CHILD_MALE', 'CHILD_FEMALE'
-          scope -- see the documentation of this class.
-
-        Symbolic voice names are mapped to real synthesizer voices in the
-        configuration of the output module.  Use the method
-        'set_synthesis_voice()' if you want to work with real voices.
-            
-        """
-        assert isinstance(value, str) and \
-               value.lower() in ("male1", "male2", "male3", "female1",
-                                 "female2", "female3", "child_male",
-                                 "child_female")
-        self._conn.send_command('SET', scope, 'VOICE', value)
-
-    def set_synthesis_voice(self, value, scope=Scope.SELF):
-        """Set voice by its real name.
-
-        Arguments:
-          value -- voice name as returned by 'list_synthesis_voices()'
-          scope -- see the documentation of this class.
-            
-        """
-        self._conn.send_command('SET', scope, 'SYNTHESIS_VOICE', value)
-        
-    def set_pause_context(self, value, scope=Scope.SELF):
-        """Set the amount of context when resuming a paused message.
-
-        Arguments:
-          value -- a positive or negative value meaning how many chunks of data
-            after or before the pause should be read when resume() is executed.
-          scope -- see the documentation of this class.
-            
-        """
-        assert isinstance(value, int)
-        self._conn.send_command('SET', scope, 'PAUSE_CONTEXT', value)
-
-    def set_debug(self, val):
-        """Switch debugging on and off. When switched on,
-        debugging files will be created in the chosen destination
-        (see set_debug_destination()) for Speech Dispatcher and all
-        its running modules. All logging information will then be
-        written into these files with maximal verbosity until switched
-        off. You should always first call set_debug_destination.
-
-        The intended use of this functionality is to switch debuging
-        on for a period of time while the user will repeat the behavior
-        and then send the logs to the appropriate bug-reporting place.
-
-        Arguments:
-          val -- a boolean value determining whether debugging
-                 is switched on or off
-          scope -- see the documentation of this class.
-        
-        """
-        assert isinstance(val, bool)
-        if val == True:
-            ssip_val = "ON"
-        else:
-            ssip_val = "OFF"
-
-        self._conn.send_command('SET', scope.ALL, 'DEBUG', ssip_val)
-
-
-    def set_debug_destination(self, path):
-        """Set debug destination.
-
-        Arguments:
-          path -- path (string) to the directory where debuging
-                  files will be created
-          scope -- see the documentation of this class.
-        
-        """
-        assert isinstance(val, string)
-
-        self._conn.send_command('SET', scope.ALL, 'DEBUG_DESTINATION', val)
-
-    def block_begin(self):
-        """Begin an SSIP block.
-
-        See SSIP documentation for more details about blocks.
-
-        """
-        self._conn.send_command('BLOCK', 'BEGIN')
-
-    def block_end(self):
-        """Close an SSIP block.
-
-        See SSIP documentation for more details about blocks.
-
-        """
-        self._conn.send_command('BLOCK', 'END')
-
-    def close(self):
-        """Close the connection to Speech Dispatcher."""
-        if hasattr(self, '_conn'):
-            self._conn.close()
-            del self._conn
-
-
-class Client(SSIPClient):
-    """A DEPRECATED backwards-compatible API.
-
-    This Class is provided only for backwards compatibility with the prevoius
-    unofficial API.  It will be removed in future versions.  Please use either
-    'SSIPClient' or 'Speaker' interface instead.  As deprecated, the API is no
-    longer documented.
-
-    """
-    def __init__(self, name=None, client=None, **kwargs):
-        name = name or client or 'python'
-        super(Client, self).__init__(name, **kwargs)
-        
-    def say(self, text, priority=Priority.MESSAGE):
-        self.set_priority(priority)
-        self.speak(text)
-
-    def char(self, char, priority=Priority.TEXT):
-        self.set_priority(priority)
-        super(Client, self).char(char)
-
-    def key(self, key, priority=Priority.TEXT):
-        self.set_priority(priority)
-        super(Client, self).key(key)
-
-    def sound_icon(self, sound_icon, priority=Priority.TEXT):
-        self.set_priority(priority)
-        super(Client, self).sound_icon(sound_icon)
-        
-
-class Speaker(SSIPClient):
-    """Extended Speech Dispatcher Interface.
-
-    This class provides an extended intercace to Speech Dispatcher
-    functionality and tries to hide most of the lower level details of SSIP
-    (such as a more sophisticated handling of blocks and priorities and
-    advanced event notifications) under a more convenient API.
-    
-    Please note that the API is not yet stabilized and thus is subject to
-    change!  Please contact the authors if you plan using it and/or if you have
-    any suggestions.
-
-    Well, in fact this class is currently not implemented at all.  It is just a
-    draft.  The intention is to hide the SSIP details and provide a generic
-    interface practical for screen readers.
-    
-    """
-
-
-# Deprecated but retained for backwards compatibility
-
-# This class was introduced in 0.7 but later renamed to CommunicationMethod
-class ConnectionMethod(object):
-    """Constants describing the possible methods of connection to server.
-
-    Retained for backwards compatibility but DEPRECATED. See 
CommunicationMethod."""
-    UNIX_SOCKET = 'unix_socket'
-    """Unix socket communication using a filesystem path"""
-    INET_SOCKET = 'inet_socket'
-    """Inet socket communication using a host and port"""
diff --git a/src/python/speechd/paths.py.in b/src/python/speechd/paths.py.in
deleted file mode 100644
index a2a9696..0000000
--- a/src/python/speechd/paths.py.in
+++ /dev/null
@@ -1 +0,0 @@
-SPD_SPAWN_CMD = "@bindir@/speech-dispatcher"
diff --git a/src/python/speechd_config/Makefile.am 
b/src/python/speechd_config/Makefile.am
deleted file mode 100644
index 8b57ad8..0000000
--- a/src/python/speechd_config/Makefile.am
+++ /dev/null
@@ -1,27 +0,0 @@
-## Process this file with automake to produce Makefile.in
-
-dist_snddata_DATA = test.wav
-
-dist_bin_SCRIPTS = spd-conf
-
-speechd_pythondir = $(pyexecdir)/speechd_config
-speechd_python_PYTHON = __init__.py config.py
-nodist_speechd_python_PYTHON = paths.py
-
-paths_edit = sed \
-       -e "s:address@hidden@]:$(spdconforigdir):" \
-       -e "s:address@hidden@]:$(spdconfdir):" \
-       -e "s:address@hidden@]:$(snddatadir):" \
-       -e "s:address@hidden@]:$(spddesktopconforigdir):"
-
-paths.py: Makefile
-       rm -f $@
-       srcdir=; \
-       test -f ./address@hidden || srcdir=$(srcdir)/; \
-       $(paths_edit) address@hidden > $@
-
-paths.py: $(srcdir)/paths.py.in
-
-CLEANFILES = paths.py
-
-EXTRA_DIST = paths.py.in
diff --git a/src/python/speechd_config/__init__.py 
b/src/python/speechd_config/__init__.py
deleted file mode 100644
index 6f7eef9..0000000
--- a/src/python/speechd_config/__init__.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# Copyright (C) 2008 Brailcom, o.p.s.
-#
-# 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 of the License, 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
-from config import *
-
diff --git a/src/python/speechd_config/config.py 
b/src/python/speechd_config/config.py
deleted file mode 100644
index 26bdccd..0000000
--- a/src/python/speechd_config/config.py
+++ /dev/null
@@ -1,924 +0,0 @@
-# config.py - A simple dialog based tool for basic configuration of
-#             Speech Dispatcher and problem diagnostics.
-#
-# Copyright (C) 2008, 2010 Brailcom, o.p.s.
-#
-# 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 of the License, 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
-import sys
-import os
-import shutil
-import fileinput
-import socket
-import time
-import datetime
-
-from optparse import OptionParser
-
-# Configuration and sound data paths
-import paths
-
-def report(msg):
-    """Output information messages for the user on stdout
-    and if desired, by espeak synthesis"""
-    print msg
-    if options.use_espeak_synthesis:
-        os.system("espeak \"" + msg + "\"")
-
-def input_audio_icon():
-    """Produce a sound for the event 'input requested' used in question()"""
-    if options.use_espeak_synthesis:
-        os.system("espeak \"Type in\"")
-
-def question(text, default):
-    """Ask a simple question and suggest the default value"""
-
-    while 1:
-        if isinstance(default, bool):
-            if default == True:
-                default_str = "yes"
-            else:
-                default_str = "no"
-        else:
-            default_str = str(default)
-        report(text + " ["+default_str+"] :")
-        input_audio_icon()
-
-        if not options.dont_ask:
-            str_inp = raw_input(">") 
-
-        # On plain enter, return default
-        if options.dont_ask or (len(str_inp) == 0):
-            return default
-        # If a value was typed, check it and convert it
-        elif isinstance(default, bool):
-            if str_inp in ["yes","y", "Y", "true","t", "1"]:
-                return True
-            elif str_inp in ["no", "n", "N", "false", "f", "0"]:
-                return False
-            else:
-                report ("Unknown answer (type 'yes' or 'no')")
-                continue
-        elif isinstance(default, int):
-            return int(str_inp)
-        elif isinstance(default, str):
-            return str_inp
-        else:
-            raise TypeError("Invalid type for the default value")
-
-def question_with_suggested_answers(text, default, suggest):
-    """Ask a question with suggested answers. If the answer typed is not
-    in 'suggest', the user is notified and given an opportunity to correct
-    his choice"""
-    
-    reply = question(text, default)
-    while reply not in suggest:
-        report("""The value you have chosen is not among the suggested values.
-You have chosen '%s'.""" % reply)
-        report("The suggested values are " + str(suggest))
-        correct = question("Do you want to correct your answer?", True)
-        if correct == True:
-            reply = question(text, default)
-        else:
-            return reply
-    return reply
-
-def question_with_required_answers(text, default, required):
-    """Ask a question and repeat it until the answer typed in is in 
'required'"""
-    
-    reply = question(text, default)
-    while reply not in required:
-        report("You have chosen '%s'. Please choose one of %s" % (reply, 
str(required)))
-        reply = question(text, default)
-    return reply
-
-class Options(object):
-    """Configuration for spdconf"""
-
-    _conf_options = \
-        {
-        'create_user_configuration':
-            {
-            'descr' : "Create Speech Dispatcher configuration for the given 
user",
-            'doc' : None,
-            'type' : bool,
-            'default' : False,
-            'command_line' : ('-u', '--create-user-conf'),
-            },
-        'config_basic_settings_user':
-            {
-            'descr' : "Configure basic settings in user configuration",
-            'doc' : None,
-            'type' : bool,
-            'default' : False,
-            'command_line' : ('-c', '--config-basic-settings-user'),
-            },
-        'config_basic_settings_system':
-            {
-            'descr' : "Configure basic settings in system-wide configuration",
-            'doc' : None,
-            'type' : bool,
-            'default' : False,
-            'command_line' : ('-C', '--config-basic-settings-system'),
-            },
-        'diagnostics':
-            {
-            'descr' : "Diagnose problems with the current setup",
-            'doc' : None,
-            'type' : bool,
-            'default' : False,
-            'command_line' : ('-d', '--diagnostics'),
-            },
-        'test_spd_say':
-            {
-            'descr' : "Test connection to Speech Dispatcher using spd-say",
-            'doc' : None,
-            'type' : bool,
-            'default' : False,
-            'command_line' : ('-s', '--test-spd-say'),
-            },
-        'test_festival':
-            {
-            'descr' : "Test whether Festival works as a server",
-            'doc' : None,
-            'type' : bool,
-            'default' : False,
-            'command_line' : ('', '--test-festival'),
-            },
-        'test_espeak':
-            {
-            'descr' : "Test whether Espeak works as a standalone binary",
-            'doc' : None,
-            'type' : bool,
-            'default' : False,
-            'command_line' : ('', '--test-espeak'),
-            },
-        'test_alsa':
-            {
-            'descr' : "Test ALSA audio",
-            'doc' : None,
-            'type' : bool,
-            'default' : False,
-            'command_line' : ('', '--test-alsa'),
-            },
-
-        'test_pulse':
-            {
-            'descr' : "Test Pulse Audio",
-            'doc' : None,
-            'type' : bool,
-            'default' : False,
-            'command_line' : ('', '--test-pulse'),
-            },
-
-        'use_espeak_synthesis':
-            {
-            'descr' : "Use espeak to synthesize messages",
-            'doc' : None,
-            'type' : bool,
-            'default' : False,
-            'command_line' : ('-e', '--espeak'),
-            },
-        'dont_ask':
-            {
-            'descr' : "Do not ask any questions, allways use default values",
-            'doc' : None,
-            'type' : bool,
-            'default' : False,
-            'command_line' : ('-n', '--dont-ask'),
-            },
-        'debug':
-            {
-            'descr' : "Debug a problem and generate a report",
-            'doc' : None,
-            'type' : bool,
-            'default' : False,
-            'command_line' : ('-D', '--debug'),
-            },
-        }
-
-    def __init__(self):
-        usage = """%prog [options]
-A simple dialog based tool for basic configuration of Speech Dispatcher
-and problem diagnostics."""
-        self.cmdline_parser = OptionParser(usage)
-
-        for option, definition in self._conf_options.iteritems():
-            # Set object attributes to default values
-            def_val = definition.get('default', None)
-            setattr(self, option, def_val)
-            
-            # Fill in the cmdline_parser object
-            if definition.has_key('command_line'):
-                descr = definition.get('descr', None)                
-                type = definition.get('type', None)
-                
-                if definition.has_key('arg_map'):
-                    type, map = definition['arg_map']
-                if type == str:
-                    type_str = 'string'
-                elif type == int:
-                    type_str = 'int'
-                elif type == float:
-                    type_str = 'float'
-                elif type == bool:
-                    type_str = None
-                else:
-                    raise TypeError("Unknown type")
-                
-                if type != bool:
-                    self.cmdline_parser.add_option(type=type_str, dest=option,
-                                                   help=descr,
-                                                   *definition['command_line'])
-                else: # type == bool
-                    self.cmdline_parser.add_option(action="store_true", 
dest=option,
-                                                   help=descr,
-                                                   *definition['command_line'])
-            
-        # Set options according to command line flags
-        (cmdline_options, args) = self.cmdline_parser.parse_args()
-
-        for option, definition in self._conf_options.iteritems():
-                val = getattr(cmdline_options, option, None)
-                if val != None:
-                    if definition.has_key('arg_map'):
-                        former_type, map = definition['arg_map']
-                        try:
-                            val = map[val]
-                        except KeyError:
-                            raise ValueError("Invalid option value: "  + 
str(val))
-                        
-                    setattr(self, option, val)
-        
-        #if len(args) != 0:
-           # raise ValueError("This command takes no positional arguments 
(without - or -- prefix)")
-
-class Tests:
-    """Tests of functionality of Speech Dispatcher and its dependencies
-    and methods for determination of proper paths"""
-
-    def __init__(self):
-        self.festival_socket = None
-
-    def user_speechd_dir(self):
-        """Return user Speech Dispatcher configuration and logging directory"""
-        return os.path.expanduser(os.path.join('~', '.speech-dispatcher'))
-
-    def user_speechd_dir_exists(self):
-        """Determine whether user speechd directory exists"""
-        return os.path.exists(self.user_speechd_dir())
-
-    def user_conf_dir(self):
-        """Return user configuration directory"""
-        return os.path.join(self.user_speechd_dir(), "conf")
-
-    def system_conf_dir(self):
-        """Determine system configuration directory"""
-        return paths.SPD_CONF_PATH
-
-    def user_conf_dir_exists(self):
-        """Determine whether user configuration directory exists"""
-        return os.path.exists(self.user_conf_dir())
-
-    def festival_connect(self, host="localhost", port=1314):
-        """
-        Try to connect to festival and determine whether it is possible.
-        On success self.festival_socket is initialized with the openned socket.
-        """
-        self.festival_socket = socket.socket(socket.AF_INET, 
socket.SOCK_STREAM)
-        try:
-            self.festival_socket.connect((socket.gethostbyname(host), port))
-        except socket.error, (num, reson):
-            report("""ERROR: It was not possible to connect to Festival on the
-given host and port. Connection failed with error %d : %s .""" % (num, reson))
-            report("""Hint: Most likely, your Festival server is not running 
now
-or not at the default port %d.
-
-Try /etc/init.d/festival start or run 'festival --server' from the command 
line.""" % port)
-            return False
-        return True
-        
-    def festival_with_freebsoft_utils(self):
-        """Test whether festival works and contains working 
festival-freebsoft-utils.
-        """
-        if not self.festival_socket:
-            if not self.festival_connect():
-                return False
-        self.festival_socket.send("(require 'speech-dispatcher)\n")
-        reply = self.festival_socket.recv(1024)
-        if "LP" in reply:
-            report("Festival contains freebsoft-utils.")
-            return True
-        else:
-            report("""ERROR: Your Festival server is working but it doesn't 
seem
-to load festival-freebsoft-utils. You need to install festival-freebsoft-utils
-to be able to use Festival with Speech Dispatcher.""")
-            return False
-
-    def python_speechd_in_path(self):
-        """Try whether python speechd library is importable"""
-        try:
-            import speechd
-        except:
-            report("""Python can't find the Speech Dispatcher library.
-Is it installed? This won't prevent Speech Dispatcher to work, but no
-Python applications like Orca will be able to use it.
-Search for package like python-speechd, download and install it""")
-            return False
-        return True
-
-    def audio_try_play(self, type):
-        """Try to play a sound through the standard playback utility for the
-        given audio method."""
-        wavfile = os.path.join(paths.SPD_SOUND_DATA_PATH,"test.wav")
-
-        if type == 'alsa':
-            cmd = "aplay" + " " + wavfile
-        elif type == 'pulse':
-            cmd = "paplay" + " " + wavfile
-        else:
-            raise NotImplementedError("Test for this audio system is not 
implemented")
-
-        try:
-            ret = os.system(cmd)
-        except:
-            report("""Can't execute the %s command, this audio output might 
not be available
-on your system, but it might also be a false warning. Please make
-sure your audio is working.""")
-            reply = question("Are you sure that %s audio is working?" % type, 
False)
-            return reply
-    
-        if ret:
-            report("Can't play audio via\n     %s" % cmd)
-            report("""Your audio doesn't seem to work, please fix audio first 
or choose
-a different method.""")
-            return False
-
-
-        reply = question("Did you hear the sound?", True)
-        
-        if not reply:
-            report("""Please examine the above output from the sound playback
-utility. If everything seems right, are you sure your audio is loud enough and
-not muted in the mixer? Please fix your audio system first or choose a 
different
-audio output method in configuration.""")
-            return False
-        else:
-            report("Audio output '%s' works" % type)
-            return True
-
-    def test_spd_say(self):
-        """Test Speech Dispatcher using spd_say"""
-
-        report("Testing Speech Dispatcher using spd_say")
-        
-        while True:
-            try:
-                ret = os.system("spd-say -P important \"Speech Dispatcher 
works\"")
-            except:
-                report("""Can't execute the spd-say binary,
-it is very likely that Speech Dispatcher is not installed.""")
-                return False
-            hearing_test = question("Did you hear the message about Speech 
Dispatcher working?", True)
-            if hearing_test:
-                report("Speech Dispatcher is installed and working!")
-                return True
-            else:
-                report("Speech Dispatcher is installed but there is some 
problem")
-                return False
-
-    def test_festival(self):
-        """Test whether Festival works as a server"""
-        report("Testing whether Festival works as a server")
-
-        ret = self.festival_with_freebsoft_utils()
-        if not ret:
-            report("Festival server is not working.")
-            return False
-        else:
-            report("Festival server seems to work correctly")
-            return True
-
-    def test_espeak(self):
-        """Test the espeak utility"""
-
-        report("Testing whether Espeak works")
-        
-        while True:
-            try:
-                os.system("espeak \"Espeak seems to work\"")
-            except:
-                report("""Can't execute the espeak binary, it is likely that 
espeak
-is not installed.""")
-                return False
-
-            report("Espeak is installed")
-            return True
-
-    def test_alsa(self):
-        """Test ALSA sound output"""
-        report("Testing ALSA sound output")
-        return self.audio_try_play(type='alsa')
-
-    def test_pulse(self):
-        """Test Pulse Audio sound output"""
-        report("Testing PULSE sound output")
-        return self.audio_try_play(type='pulse')
-
-    def diagnostics(self, speechd_running = True, output_modules=[], 
audio_output=[]):
-
-        """Perform a complete diagnostics"""
-        working_modules = []
-        working_audio = []
-
-        if speechd_running:
-            # Test whether Speech Dispatcher works
-            if self.test_spd_say():
-                spd_say_working = True
-                skip = question("Speech Dispatcher works. Do you want to skip 
other tests?",
-                                True)
-                if skip:
-                    return {'spd_say_working': True}
-            else:
-                spd_say_working = False
-        else:
-            spd_say_working = False
-
-        if not spd_say_working:
-            if not question("""
-Speech Dispatcher isn't running or we can't connect to it (see above),
-do you want to proceed with other tests? (They can help to determine
-what is wrong)""", True):
-                return {'spd_say_working': False}
-
-        def decide_to_test(identifier, name, listing):
-            """"Ask the user whether to test a specific capability"""
-            if ((identifier in listing)
-                or (not len(listing)
-                    and question("Do you want to test the %s now?" % name, 
True))):
-                return True
-            else:
-                return False
-
-        if decide_to_test('festival', "Festival synthesizer", output_modules): 
-            if self.test_festival():
-                working_modules += ["festival"]
-
-        if decide_to_test('espeak', "Espeak synthesizer", output_modules): 
-            if self.test_espeak():
-                working_modules += ["espeak"]
-
-        if decide_to_test('alsa', "ALSA sound system", audio_output): 
-            if self.test_alsa():
-                working_audio += ["alsa"]
-
-        if decide_to_test('pulse', "Pulse Audio sound system", audio_output): 
-            if self.test_pulse():
-                working_audio += ["pulse"]
-
-        report("Testing whether Python Speech Dispatcher library is in path 
and importable")
-        python_speechd_working = test.python_speechd_in_path()
-        
-        return  {'spd_say_working': spd_say_working,
-                 'audio': working_audio,
-                 'synthesizers': working_modules,
-                 'python_speechd' : python_speechd_working}
-
-    def write_diagnostics_results(self, results):
-        """Write out diagnostics results using report()"""
-
-        report("""
-
-Diagnostics results:""")
-        if results.has_key('spd_say_working'):
-            if results['spd_say_working']:
-                report("Speech Dispatcher is working")
-            else:
-                report("Speech Dispatcher not working through spd-say")
-        if results.has_key('synthesizers'):
-            report("Synthesizers that were tested and seem to work: %s" %
-                   str(results['synthesizers']))
-        if results.has_key('audio'):
-            report("Audio systems that were tested and seem to work: %s" %
-                   str(results['audio']))
-        if results.has_key('python_speechd'):
-            if(results['python_speechd']):
-                report("Python Speech Dispatcher module is importable")
-            else:
-                report("""Python Speech Dispatcher module not importable.
-Either not installed or not in path.""")
-        report("End of diagnostics results")
-
-    def user_configuration_seems_complete(self):
-        """Decide if the user configuration seems reasonably complete"""
-        if not os.path.exists(os.path.join(self.user_conf_dir(), 
"speechd.conf")):
-            return False
-
-        if not len(os.listdir(self.user_conf_dir())) > 2:
-            return False
-
-        if not os.path.exists(os.path.join(self.user_conf_dir(), "modules")):
-            return False
-
-        if not os.path.exists(os.path.join(self.user_conf_dir(), "clients")):
-            return False
-
-        return True
-
-    def debug_and_report(self, type = None):
-        """Start Speech Dispatcher in debugging mode, collect the debugging 
output
-        and offer to send it to the developers"""
-
-        report("Starting collecting debugging output, configuration and 
logfiles")
-
-        if not type:
-            type = question_with_required_answers("""
-Do you want to debug 'system' or  'user' Speech Dispatcher?""",
-                                                  'user', ['user', 'system'])
-
-        # Try to kill running Speech Dispatcher
-        reply = question("""It is necessary to kill the currently running 
Speech Dispatcher
-processes. Do you want to do it now?""", True)
-        if reply:
-            os.system("killall speech-dispatcher")
-        else:
-            report("""
-You decided not to kill running Speech Dispatcher processes.
-Please make sure your Speech Dispatcher is not running now.""")
-            reply = question("Is your Speech Dispatcher not running now?", 
True)
-            if not reply:
-                report("Can't continue, please stop your Speech Dispatcher and 
try again")
-
-        time.sleep(2)
-
-        # All debugging files are written to TMPDIR/speech-dispatcher/
-        if os.environ.has_key('TMPDIR'):
-            tmpdir = os.environ['TMPDIR']
-        else:
-            tmpdir = "/tmp/"
-        debugdir_path = os.path.join(tmpdir, "speechd-debug")
-        date = datetime.date.today()
-        debugarchive_path = os.path.join(tmpdir, 
"speechd-debug-%d-%d-%d.tar.gz" %
-                                         (date.day, date.month, date.year))
-
-        # Start Speech Dispatcher with debugging enabled
-        if type == 'user':
-            report("Speech Dispatcher will be started now in debugging mode")
-            speechd_started = not os.system("speech-dispatcher -D")
-            configure_directory = test.user_conf_dir()
-        else:
-            report("Warning: You must be root or under sudo to do this.")      
  
-            report("""
-Please start your system Speech Dispatcher now with parameter '-D'""")
-            reply = question("Is your Speech Dispatcher running now?", True)
-            if reply:
-                speechd_started = True
-            else:
-                report("Can't continue")
-            configure_directory = test.system_conf_dir()
-        time.sleep(2)
-
-        if not speechd_started:
-            reply = question("Speech Dispatcher failed to start, continuing 
anyway")
-
-        report("Trying to speak some messages")
-        ret = os.system("spd-say \"Speech Dispatcher debugging 1\"")
-        if not ret:
-            os.system("spd-say \"Speech Dispatcher debugging 2\"")
-            os.system("spd-say \"Speech Dispatcher debugging 3\"")
-        else:
-            report("Can't test Speech Dispatcher connection, can't connect")
-
-        report("Please wait (about 5 seconds)")
-        time.sleep(5)
-
-        report("Collecting debugging output and your configuration 
information") 
-
-        os.system("umask 077")
-        os.system("tar -cz %s %s > %s" % 
-                  (debugdir_path, configure_directory, debugarchive_path))   
-        os.system("killall speech-dispatcher")
-        os.system("rm -rf %s" % debugdir_path)
-
-        report("""
-Please send %s to speechd at bugs.freebsoft.org with
-a short description of what you did. We will get in touch with you soon
-and suggest a solution.""" % debugarchive_path)
-        
-test = Tests()
-
-class Configure:
-
-    """Setup user configuration and/or set basic options in user/system 
configuration"""
-
-    default_output_module = None
-    default_language = None
-    default_audio_method = None
-    
-    def remove_user_configuration(self):
-        """Remove user configuration tree"""
-        shutil.rmtree(test.user_conf_dir())
-
-    def options_substitute(self, configfile, options):
-        """Substitute the given options with given values.
-
-        Arguments:
-        configfile -- the file path of the configuration file as a string
-        options -- a list of tuples (option_name, value)"""
-
-        # Parse config file in-place and replace the desired options+values
-        for line in fileinput.input(configfile, inplace=True, backup=".bak"):
-            # Check if the current line contains any of the desired options
-            for opt, value in options.iteritems():
-                if opt in line:
-                    # Now count unknown words and try to judge if this is
-                    # real configuration or just a comment
-                    unknown = 0
-                    for word in line.split():
-                        if word =='#' or word == '\t':
-                            continue
-                        elif word == opt:
-                            # If a foreign word went before our option 
identifier,
-                            # we are not in code but in comments
-                            if unknown != 0:
-                                unknown = 2
-                                break
-                        else:
-                            unknown += 1
-
-                    # Only consider the line as the actual code when the 
keyword
-                    # is followed by exactly one word value. Otherwise 
consider this
-                    # line as plain comment and leave intact
-                    if unknown == 1:
-                        # Convert value into string representation in spd_val
-                        if isinstance(value, bool):
-                            if value == True:
-                                spd_val = "1"
-                            elif value == False:
-                                spd_val = "2"
-                        elif isinstance(value, int):
-                            spd_val = str(value)
-                        else:
-                            spd_val = str(value)
-                            
-                        print opt + "   " + spd_val
-                        break
-            
-            else:
-                print line,
-                
-    def create_user_configuration(self):
-        """Create user configuration in the standard location"""
-
-        # Ask before touching things that we do not have to!
-        if test.user_speechd_dir_exists():
-            if test.user_conf_dir_exists():
-                if test.user_configuration_seems_complete():
-                    reply = question(
-                        """User configuration already exists.
-Do you want to rewrite it with a new one?""", False)
-                    if reply == False:
-                        report("Keeping configuration intact and continuing 
with settings.")
-                        return
-                    else:
-                        self.remove_user_configuration()
-                else:
-                    reply = question(
-                        """User configuration already exists, but it seems to 
be incomplete.
-Do you want to keep it?""", False)
-                    if reply == False:
-                        self.remove_user_configuration()
-                    else:
-                        report("Keeping configuration intact and aborting.")
-                        return
-
-            # TODO: Check for permissions on logfiles and pid
-        else:
-            report("Creating " + test.user_speechd_dir())
-            os.mkdir(test.user_speechd_dir())
-
-        # Copy the original intact configuration files
-        # creating a conf/ subdirectory
-        shutil.copytree(paths.SPD_CONF_ORIG_PATH, test.user_conf_dir())
-        
-        report("User configuration created in %s" % test.user_conf_dir())
-
-    def configure_basic_settings(self, type='user'):
-        """Ask for basic settings and rewrite them in the configuration file"""
-
-        if type == 'user':
-            report("Configuring user settings for Speech Dispatcher")
-        elif type == 'system':
-            report("Warning: You must be root or under sudo to do this.")
-            report("Configuring system settings for Speech Dispatcher")
-        else:
-            raise ValueError("Invalid configuration type")
-
-        # Now determine the most important config option
-        self.default_output_module = question_with_suggested_answers(
-            "Default output module",
-            "espeak",
-            ["espeak", "flite", "festival", "cicero", "ibmtts"])
-
-        self.default_language = question(
-            "Default language (two-letter iso language code like \"en\" or 
\"cs\")",
-            "en")
-
-        self.default_audio_method = question_with_suggested_answers(
-            "Default audio output method",
-            "pulse",
-            ["pulse", "alsa", "oss", "pulse,alsa"])
-
-        self.default_speech_rate = question(
-            "Default speech rate (on the scale of -100..100, 0 is default, 50 
is faster, -50 is slower)",
-            "0")
-
-        self.default_speech_pitch = question(
-            "Default speech pitch (on the scale of -100..100, 0 is default, 50 
is higher, -50 is lower)",
-            "0")
-    
-        # Substitute given configuration options
-        if type == 'user':
-            configfile = os.path.join(test.user_conf_dir(), "speechd.conf")
-        elif type == 'system':
-            configfile = os.path.join(test.system_conf_dir(), "speechd.conf")
-
-        self.options_substitute(configfile, 
-                                {"DefaultModule": self.default_output_module,
-                                 "DefaultLanguage": self.default_language,
-                                 "AudioOutputMethod": 
self.default_audio_method,
-                                 "DefaultRate": self.default_speech_rate,
-                                 "DefaultPitch": self.default_speech_pitch,
-                                 "DefaultLanguage": self.default_language,
-                                 })
-        if type == 'user':
-            self.setup_autostart = question(
-                """Do you want to have Speech Dispatcher automatically started 
from ~/.config/autostart ?
-This is usually not necessary, most applications will start Speech Dispatcher 
automatically.""",
-                False)
-            if self.setup_autostart:
-                os.system("""cp %s ~/.config/autostart/""" % 
os.path.join(paths.SPD_DESKTOP_CONF_PATH,
-                                                                          
"speechd.desktop")) 
-                         
-                report("""
-Configuration written to %s
-Basic configuration now complete. You might still need to fine tune it by
-manually editing the configuration file above. Especially if you need to
-use special audio settings, non-standard synthesizer ports etc.""" % 
configfile)
-
-    def speechd_start_user(self):
-        """Start Speech Dispatcher in user-mode"""
-
-        report("Starting Speech Dispatcher in user-mode")
-
-        err = os.system("speech-dispatcher")
-        if err:
-            report("Can't start Speech Dispatcher. Exited with status %d" % 
err)
-            reply = question("""Perhaps this is because your Speech Dispatcher 
is already running.
-Do you want to kill all running Speech Dispatchers and try again?""", True)
-            if reply:
-                os.system("killall speech-dispatcher")
-                err = os.system("speech-dispatcher")
-                if err:
-                    report("Can't start Speech Dispatcher")
-                    return False
-            else:
-                return False
-        return True
-
-    def speechd_start_system(self):
-        """Start Speech Dispatcher in system-mode"""
-
-        report("Warning: You must be root or under sudo to do this.")        
-        report("Starting Speech Dispatcher in system-mode")
-        
-        reply = question("Is your system using an 
/etc/init.d/speech-dispatcher script?",
-                         True)
-        if reply:
-            report("Stopping Speech Dispatcher in case any is running already")
-            os.system("/etc/init.d/speech-dispatcher stop") 
-            report("Starting Speech Dispatcher via 
/etc/init.d/speech-dispatcher")
-            ret = os.system("/etc/init.d/speech-dispatcher start")
-            if ret:
-                report("Can't start Speech Dispatcher. Exited with status %d" 
% ret)
-                return False
-        else:
-            report("""Do not know how to start system Speech Dispatcher,
-you have to start it manually to continue.""")
-            reply = question("Have you started Speech Dispatcher now?", True)
-            if not reply:
-                report("Can't continue")
-                return False
-        return True
-
-    def complete_config(self):
-        """Create a complete configuration, run diagnosis and if necessary, 
debugging"""
-
-        speechd_type = question_with_required_answers(
-            "Do you want to create/setup a 'user' or 'system' configuration",
-            'user', ['user', 'system'])
-
-        if speechd_type == 'user':
-            self.create_user_configuration()
-            self.configure_basic_settings(type='user')
-        elif speechd_type == 'system':
-            self.configure_basic_settings(type='system')
-        else:
-            raise ValueError("Invalid configuration type")
-
-        reply = question("Do you want to start/restart Speech Dispatcher now 
and run some tests?", True)
-        if not reply:
-            report("Your configuration is now done but not tested")
-            return
-        else:
-            if speechd_type == 'user':
-                started = self.speechd_start_user()
-            elif speechd_type == 'system':
-                started = self.speechd_start_system()
-
-        if not started:
-            report("Your Speech Dispatcher is not running")
-            
-        result = test.diagnostics(speechd_running = started,
-                                  audio_output=[self.default_audio_method],
-                                  output_modules=[self.default_output_module])
-        test.write_diagnostics_results(result)
-
-        if not started:
-            reply = question("Do you want to run debugging now and send a 
request for help to the developers?",
-                             False)
-            if reply:
-                test.debug_and_report(type=speechd_type)
-
-
-# Basic objects
-options = Options()
-configure = Configure()
-test = Tests()
-
-
-def main():
-
-    report("\nSpeech Dispatcher configuration tool\n")
-    
-    if options.create_user_configuration:
-        # Check for and/or create basic user configuration
-        configure.create_user_configuration()
-        reply = question("Do you want to continue with basic settings?", True)
-        if reply:
-            configure.configure_basic_settings(type='user')
-    elif options.config_basic_settings_user:
-        configure.configure_basic_settings(type='user')
-
-    elif options.config_basic_settings_system:
-        configure.configure_basic_settings(type='system')
-
-    elif options.test_festival:
-        test.test_festival()
-
-    elif options.test_spd_say:
-        test.test_spd_say()
-
-    elif options.test_espeak:
-        test.test_espeak()
-
-    elif options.test_alsa:
-        test.audio_try_play(type='alsa')
-
-    elif options.test_pulse:
-        test.audio_try_play(type='pulse')
-
-    elif options.diagnostics:
-        ret = test.diagnostics()
-        test.write_diagnostics_results(ret)
-
-    elif options.debug:
-        test.debug_and_report()
-
-    else:
-        reply = question("Do you want to setup a completely new 
configuration?", True)
-        if reply:
-            configure.complete_config()
-        else:
-            reply = question("Do you want to run diagnosis of problems?", True)
-            if reply:
-                ret=test.diagnostics()
-                test.write_diagnostics_results(ret)
-            else:
-                report("""Please run this command again and select what you 
want to do
-or read the quick help available through '-h' or '--help'.""")
-
-if __name__ == "__main__":
-    sys.exit(main())
diff --git a/src/python/speechd_config/paths.py.in 
b/src/python/speechd_config/paths.py.in
deleted file mode 100644
index 326e954..0000000
--- a/src/python/speechd_config/paths.py.in
+++ /dev/null
@@ -1,4 +0,0 @@
-SPD_CONF_ORIG_PATH="@spdconforigdir@"
-SPD_CONF_PATH="@spdconfdir@"
-SPD_SOUND_DATA_PATH="@snddatadir@"
-SPD_DESKTOP_CONF_PATH="@spddesktopconforigdir@"
diff --git a/src/python/speechd_config/spd-conf 
b/src/python/speechd_config/spd-conf
deleted file mode 100644
index 3cc90b5..0000000
--- a/src/python/speechd_config/spd-conf
+++ /dev/null
@@ -1,10 +0,0 @@
-#!/usr/bin/python
-
-# Helper script to be put in /usr/bin/ or a similar location
-# calling the appropriate python tool
-
-import speechd_config
-
-if __name__=='__main__':
-    import sys
-    sys.exit(speechd_config.main())
diff --git a/src/python/speechd_config/speechd.desktop 
b/src/python/speechd_config/speechd.desktop
deleted file mode 100644
index 4a9e8d5..0000000
--- a/src/python/speechd_config/speechd.desktop
+++ /dev/null
@@ -1,11 +0,0 @@
-
-[Desktop Entry]
-Type=Application
-Encoding=UTF-8
-Version=1.0
-Name=Speech Dispatcher
-Comment=Interface to Text to Speech services
-TryExec=speech-dispatcher
-Exec=speech-dispatcher
-X-GNOME-Autostart-enabled=true
-X-GNOME-Autostart-Phase=Initialization
diff --git a/src/python/speechd_config/test.wav 
b/src/python/speechd_config/test.wav
deleted file mode 100644
index 
1c49b4abdd29f5dab872f96691d2c67d2ecb545a..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 17410
zcmW+;1$0wO*PXc%Ph*u-ptQKVJLTa#+~MKw?(XjHZVz{VxVu|{QmS!J?wy(ceE-T?
z2}yJB%pBQ!pEDEMH*eA;l7>*1hMoT!G;address@hidden;d
zM@>--UBvZf>BPkqr;TwF+ at Ji#9U$Y`DSS;{jr*b%Xa`Qi%XL?kry|P8NcW=rx1k{U
zN(SiSqUvyQxRk=k*`&VcJHLo+l1t(5^2x9$)X_aOIyEDd=lOX7s~dSr1QdZ*!CrJd
zJuU4BRUpsR)address@hidden<uth<H6`gsb}L}2p^PD%2LE6uVb}YD8Pc%
z&@)v at qtP^5KbtEaYGi+$?ar^|`V?w`dkN2R0W?v#N?tpUd*=A|=b_yGwlTRj+d<q!
zzr at fpxn!|HF$?s5!yMHGVUzN-da_Ue?ZuDyx4KrQ6~=Yy015g$*(-jLUmvsA2PX2*
z^~%^KF+}%R>TCNa=U!$obF59{9_M~3*_Fc-&7w{gJen}scs_c(;SVNgfuLtUf~O+0
z!zbxZZMOcUCY5g|&C5^wHv9XjjB|DkHR)eiJ0up4<address@hidden&R;`Zat|GfYBEul1F
zo4UScTEgJMEn;7r%UNXcC at RO77fRFjk;0Lg{t5J!`hu>jYA|;*oR+!cWAD$;e>Qb)
z!40A<1^+HkJ?0L!x*q4I{Q3B2hrOQXxVu?oyke=MU(|+_1<8}l529nEzM>esPtind
z$EKih(wxW#p}uCRY88s31AJY6Pxw_n`=~QTKB9dSKOkv}^^^W*xVH0weX*^tbDr<G
zx2X3SdB)lKr7>et8^(?`{ADP`m61NNX5uHjn8lED{;6^sMYh^5&Se86v;E|+F&Vw{
z_65dspN#brM<lec?By=HFWHUuCHd!^&%KMB0k4QkaJ97i3k6b=V)A0nM8%;`q$J-~
zn8gGZ4o?o3<5E at e+Odi}+&BCnuYX3fj2^a}kVklJDUvwN>efl&#m-jtK;AyvEB7du
z(orRRkgKNP;@6g#SfG9E{pcQw1k#!I;EUjnlqVg6ufrMiw(wMRp`&z>zeDcq-#v2A
z`YW<d`bP=gq$sPP8sabGoM5Y!YqZz&=pDOUugD4Rv$lImTH#f(y<*1eTjE5z6F1^-
z5Ra at address@hidden|e?Ivv|fNTWY93*T=LsAuHjA`3-92OL0kgdvi)VX1Mk^
zh6KN%&f>5bUtx7pY^*)Hin=QbvO?llyqKIOKZ7(>7&TTs)!b9PQudL9wj;k$md!m!
zTBB?p{V?7b-%_iMBzxZHM`bO^Y3zJypX}Ns8}KUS{RA#~qot!st=)!3${DN|-;q8h
zv%+V5U&F_7hAN;E)mS_f5OUR-t8D#)6H%uqPu$nU0&xy;N2rFoOz!k7y}h7&zN>!t
z1is3 at Hg!lXU%(#o%raN=0~cZqgu2`?a#JoGIPK4tjtiSq!<7ovblS#Q>rd~jCGNDy
z01=z_#GSUb*O!$4_Fl@@WU|bj`Q!52I%2{H=`pdB^-}V%xa{bLhAHAob_m}TU*gfY
zA88UgAsIMHwLv{ovrsu9GRj^w+v*q^x`!6(m&F{2Zxg3e&JPdpB;@|}`)Kyrd_Mn?
zXO~<N71nPnxG6C<address@hidden>-^B{98+wl1;hEulI!ZjHdZsL<+K<|K$K({v`RaCs
zhH%^UZ_H0)TI+j|#r|W??b%hbi`%npyPWeP9yVAJ8-KS at vUN;MU1K%H3Px~mMK}Ji
zPysazpOLoWXw?tZZS_T^MgGe%G3!8nH($DRR%tb?ur#n_36(;7y~}Jr|HwJTY&G&W
zyS|6_l6{)4N&h9}M5`=0nq%A at HbJZ`Hs`PLTP1g>F}cp)Ri033HSPI&fq!%JvdTMG
z1}>p;x}xU1SZb(&gwPsK<GhkNTkX^AryYGm>2Ss1SaYEX)~Ye at jrEi-*h=oRf^zS8
zLPrGu3Ww=j(W=y`vy{!qWoNIf)44C*&BMjTRJ~;WVkxc|9lq=>WV`vNP;PO%Eq|Kl
zm$a1D)if>eE$LxQ>F9F$AioLSSL{;U6qqndE*q{$=J7q16IHJ?H^h74knLB_SLeXM
zcy>hH*^m at -%Fq^-4^DM=&25)8I{%!lxTAWoz5Jf(O~sQI#oRXkGF(*dWD!(Jv6nwB
z5VR}YIFihW&|KkFI+XviQ=Yjw`uriDpP`d{G3`rJO3WH{SY972<TmH+%s=T2InH>u
zN+*e15w>!P=9saTolzwe<q#FTVmINZaE+)UTjY)05yfid2z9DBG7 at dKWS6q9@)nho
z6=ig5ECr1&ye>S at x7{`}H)yvxemSM!c{$7~8}B8ai#=!2no>2J at f=)5LHV#S1uuxq
zkA!GZ at qnVcs<Wy(s^%rx4Rgo3T!B?sp>`P_SZ=7s$(rB^S9<P{{C>_Wj<Md_QhhR6
zQP`RvUm|*s`IUZxc$&=+`iejJ9zqB5B-~f-z@;gYlvsUE(83J+We>2Q^A?xCi*K}g
z%L2m at ydpf-_tEw=x2+ at 1S=^Nvx+_y=Gn7fJ7~8^f!uU%)7ca(13J0Gr^v4?_$0Jr&
zSlpm!psJ)QgNA!&=e*3#bTtbe!ASkeFxIkEwNS1fjB at wO%gcY|Eam*+ohA(<+Z4~^
z`ozDov^8(j_ZDBU-9j(%C(LjHQAAeDW4HzijZ#uw6$(Vg+Qpooc8hP2{7Ss2eP%9Y
z*oe=D&-?1y+vL4+Tz0N=^$R)V!swOZWWueOka?i-q<SLWiS>#MK2PY5FGt=*O0WcR
zwjx!fQx!vdy;4rEye94y!CUx;YPCUasjpft4-9s2f6eP|OLi at A*6<ybmXQOBk#VoB
zy)9X$M*1 at 1OSVj?EWY7u3d2c>$VqtwS3r at ac%#}WBt(we7vwZ^wD)a-87|X~F`tVX
zh#!Z4_?Fx6<<)kYT)$oGLo&>8ogpEiZp>CQZ|tk?gg0Y{_=JBaG{W~Hjz}G*7kers
z<tHVNE_sLN{><C%ej0p)FRPjwR+_!a4f3?$GI!JbTei`zbmt7;18FbWqd;-htakGP
zlTW7-U$e1-QoO{+2t!Ey$US)iCyAF8=Tr*?bHs0t&OPT??K>mi6#Hr8%<ZF^;!ojd
zf4049{yyh0R~7fIkeXCL{}`6V{})}}e85mfT?enlZ^d)`O`#nA9<fM`m|du&c&*%~
z%wylYpK}N2OKxN6BVMeEM5US!DL2ZygOA(~@@v_TxJtOb_;MgqPALw>?ueUhE@;}J
address@hidden;)lZ0xG<0mrE$sZ at dn=z7>uK+qvh|5LFWlH)
z&9N_^cRg~gar;9>NNrTqAY0R-pP14NPE`rK3f~ZS^E(9t&WTi#+OlUt0mTtzPh|#+
z^)=7?p5NNjHe|!2RF|U8n+7WP%FlypPbu3eyTZM|Rno7K?~r4Pim at y<!F<!0rn at Di
address@hidden|{PJY(t~g%NLsdnvM3y>Y@|HT2{fHb9P1^pZ8Tt^S;mQ8B4zsPd
ztFYVSE*!2v8l#_4L#)><y-ePyb1FSvhtG(U_yvLw{fcaq{8TM+in)q$s&cH4cVvD&
z+i-7O=rrD;e5;>qs-*ZKZw^2AY_{JDO%0#7agHf at 366`rV7X9mbD{C(*LtU>4?Tjf
zstO1$L`lbBdT671c+3+EF><ODPwbB=={W0f{_W5kVYD(<-9_ip_~iLPgO{W?{IT`-
z*dOa6osFZ7nWa}&?Uwj9&K;93RHx%O5gm-=awF9hwbk at RHJ|xjp>$VUcY-U{zSRD=
zyRg?HpW!``!>o-M>u#M at address@hidden>Q+W?PdJw}J at G(v4PBxlRyoTO
zi2Y_r7uI+>address@hidden|ur)Yn^U<AQjG>^7Y=g*}vX8o<~~X>gwVu52~h3jY>gD
address@hidden|{A|R|>guveRS!bhbSSR?_5K(~|$S?pJ?{cpP_s
zP5i3MIGY_6XsnrUTv?=0<q-uw8&0S?`%5|d`TDvC*vC0%d#ACLmV?P#66WY at 1PlMx
zr3Zhj!dne}3;I%eMfWBTY{m0!xkDVu;f=lmo)rIHcN8D8_KK}yU6<6-a!l7yb&jM3
z$~)#}XS?sn2~w)GAu`L^!#OFEOFOG7TZ^Zt3-qw|)7A~dcyjC)bDO);Jgvf<!mM^%
z42ACKw at address@hidden)kV#qL at 
zs(^kr85q8UT+$QQ5&M?R8t-d=Dw6Zk-&?=G)V2yGi(iN-
zM7O(F*iJgz1eW^h`En!U<yPv7MJ5!^N;sZqRHp`=p0&>L?%Up5fvQ|V)0>2~mYtmJ
zKAL{|)uDH#|73e_2xp?F$8=S1;)e-u$nMBIx-4jSq>(#HYKSiJSK$HXYsQX>s%VyC
zkD7?zWs_sXpB(%2Fh{3yJ-HO=v*(~=i at RyKhj37%&?R%ueD9w=x$m>u`_*D&JW=(-
zkP;m!oSIrZ;d$H_?R~VL3bd2FoNkrXa<-sT*Tg@)=kgx@;y$;_=pU%3yq<Wmh&OSR
address@hidden|kpM%Sc&i>5o$QKk8omW!yk2;SEF at s1`+i
zjJlycBdPz)`mFl)HP=Gg8j2OTn>ZlK!<F)`%{cI at Q%2{n`~KAPv<$S at KS(@p{vP`?
zshUaF8%!%SJ#dF`wQv)*NtLF%p}2|df$Mp9bI1B><K~*<QJ=Im#h;-nj)nFl+Y!%R
zCP!ul8%Vn%lN9%ihqT?4+1!44Bgqzq7<yS+X)6dH#Rr-URifs!7SS{I&zXmE>iVh*
zJ7a``2MRpZ<@rlw?s!w=ZPy<oG6#9Ka#sD8WUgra*tfc!+(Ea-RXf-?ustM4J_od%
z)p{bSVnPw?5A{k<&+O?Q6=|qC65T#_M>address@hidden
zNu>*<>%PhVNmoK`JbN57Y>yoOgw}B76>C&BU6e2&fFgh64DpNhQ?xVQr at KiWdADTM
z%-EQ(a&_`S#ViJOs at P2JAw`~YA*z5|YYfJl#_Nh&p*g-vp;uue>B~xouH>J{jL8j$
zp6Tnw?<>%&&|b at Q!ubw47v{{d5!?FQ!=B6G)#{9bMU&UZ|Fq2H;(aNBD$-6;6Mv=c
z&?K!_|6WyEp`y3)ykFP+n36NhJ3 at GA7!cPXK2iT3mkR&u)I!AXbwo)cStCugq~8hM
zEGd?0S~IUxHBuMm*GQ?(G<$k*8uqF7=|j3V>_Gm{KkM_UdxT_Ftk*wLjtdX>N;X68
z1&I9(zG5_$+pZW9U$4-cxbZRXbvM{691>qC5|t{{OumlhaSPE>ya!(ne#rObm-g2{
zjnrH8Ii}(Isel~C^SEER8G+n!`6v99 at j-Q5;^LHt)=kk%wFtN8cPgS4u|iL|OK>Hb
zB-T-#(KJ^Z<R-Z-GtzQrdolW=-5IkeuDQCQBzYF*9M4*u`zZI0yF};(sci};7PUsl
zH;xunOgy6Mt;iCx(fNo#uL%<rS<1J{{_KbIQci+nyx&b4h_U*j#$9~-a4&z1-D}(7
zGC2l%uY`xm2K|Kix0YyAqo|GiT)alvQ)N*$;address@hidden>V
zqg1IT+47HKWvGs4R&Hv}E_*k}L7zt+flLNhLbsR{&@j8W0jw#X!xs^HqxX?Tw4*p*
z)j{)7oq~CH&75%ld+&2{S at 9`KGDoY%NtFZh?5e!2cEPsHRVaK#Ua32iXtf at V{>Ri$
zEQuEJQG9c51ltmN8(xfmihWckGz*30zS4PLZLhr#<dcd)hBua3>M>Fef39s`uHZ~{
z4)-pVx{$r<S8?B>t)>%(X^IzktfIBDwOAj&3U?0=V_AG{#b-r3T+cf==T&|||62N0
z88Y08UZ*K17YP1z6wABi_}kIVT_UoKG}BB<SZbBcvf;PT2skWJ7%yaUOXZL98}6P+
address@hidden|t{IVQ!bE-Jn8Hz&m_F=woz83EsNpQ&nHZT$%&KD6;c at address@hidden
z*YFdexTxi|XnB~15>cMGMYUQ}Nx=uZ<+jW{>C}a~adu55Q;address@hidden)!NN@
zrASF~L^05M-|923F_lr(MV<M>Vk7Y^UzqHTOlAUqPk5wQ#}5v6%%77V<t-x}<Sp7(
zP!~6oC4V*N=^UlKq%+S|P#VjYDKA^o5~hKE*sI=+xASkr<-%63v78VYg)WOxsvhbp
zV#naCoXgo!&Q_tuyhZ1;@WxW;Qt+MYeNJlrS^Fo4KhRa$&Nqy?7hfsnx}}`19A8Jc
zBQ6tE!aFi5a)osk{#F!GHCB9!#Ms~EO>@l)Mxk`&Tf-K84>Tfd^rhIZIet5*I6np2
zN7kWEW at B8uX`6AK<|$q+B&u#Ij*8RSqsV)@M;N2Lp?a)nFRiep<=%F-50&B8X+D`6
z7~E`Ppqe|address@hidden
zm7hEM=e={z3jTw}su~-+8Ef$kBXRzIwn%;f$3}ZYf2?!?l`{8E(8bI&m)0G|^HGrd
ziz~-<C7VL=q#r*=;a9&^KW5e3tMW6QTLSfvM^)SCG;ZZ<hdcT%+N#^*+%8v2FkhNa
zhv`qn-Y~T>R?s{7Zv0P0yf}y7K-Yu>sRbS{hzg^k9!+#9@>{qUgxce!>bb_srqhBw
zq6 at sUf49ZCrZ^Y++sPW#$gm~;y#*O-XiazlJIHqxUI at c+f4L6zaJ9r1(Aye9t~h7p
zJhZ*>wWMv8D~xX}4&@#BY%td`)Ryl0;@a--BHyHab>HINTZWtFM%kcaI6 at Hk9e6fv
z5xyzqaW51#)ic%Qu+_6Tx0&svCn&uU5_DSQ0EJaL6rAh+;Mn1*=<)fZ<W97pZisbt
zw952BUs^bZ?h9$6M{wd|QVl7<BHU<ktfCHH=S#DlcfR!(Ac^81ZL(pnSS- at RALH1Y
zUm3J^#Xt#4nNJ(GHjG(address@hidden&yUs%G+sJ+xm9?Nx8q$|fNH=<dds=4<3Hr{l(
zv7%j+-ZEG%%DV#l94vQ^Bic#aDUqsVsOoOqgt*`4Q^rrq08SJB6^;tMxq|Xt=_gt)
z{HuspZRCT2d$xJ at C!S;B6fQ>address@hidden|c{v{kGYz0z{Ta3sp0
zJjFFtyi>^HOFmytkz(address@hidden at tb9wTYx*B at U
z`Wni6$z(Aqdb`D^H|xKPg;;5>mGFUI#aCjzNM~-g;)+sImKO?yci0=-YkE^7*SWtn
zkBv#X(d>9w at G5O~yXgGsl0)h8EOC6y^0-ANt6{csH+v6!QxCe$H>Jjr-R!W?OjTd=
zRIyI#;hb(?>8TlM&DYe7Hm2yl(qp0J-V63wt~DO)?Gx at TmBG2jCed3B+YLX|FSx-%
zRdEcj=XiNRXeOD>jTCw)jtk2phn<C-i+uy7*ZdGozTu}X1BJqeeVO(;&Q5Nhds=t^
zY0Y0T7mJ- at 5cNfsXIKS1TR11I5*W*rvS=K?MW`mW;7yUU_M-V!-Sa{_ at J7u8(+WcY
zewcLKuXEgWUiVD#lnY;!V{k*G9AhxOGdMNvxU(4X>v2b1kr+VlZWq=l!>V?Q?s9i$
zB(ELxUP`deiUs<O`fS`<svYtG9vXaAy|Y5c<-Yi*p=+$uxH>9Y^9gIY65>UnozRJ8
zgf(&=`pLURySS7d@|<*x at th70Vuci$+UmNl_-p8fZ<yn?<A6u-wTv92I_{uhaqKH&
zEyF8q4wr%32>p3Azlu$h2GY;GN-;sPPN*wS0Uw`r=|j^{E!Cl at B~fX7t;kA$dq=e6
zl)Jh6XrPzef&J1gij_<g3}bY8e0%(nuPB`3hoW~<adHa}7FsJ>Dte=9{<F?wZjb+n
ze2l-VUZ%?s27-omd&j$N-Xw43fGskcoKQv#3-vp-aT=#EnC~r?5C;lYTu=T+x^eA=
z{h~>{z~%+cxHtOxhZi#}epl^OXF?6VEmYrk$y+J-Jh&(F9~n+-E1K!MX$Gkb%940C
zYt0?t4)Nvr`fL}|^J9cF!Y=4ubPu=meexF!+lZBascfgQiVJ9W$ry<BHuMw!p3o$+
zhHY1Lj8f at ltL`W!;7*XaXVEy+f<@$QqzpbG)KCP(e6En37bqRv60y at 4Tn|OAauEN6
z)Rh;7zXqM*oN%{DYk8IY9dA(eQjJ%(QZ^QNPRsSf$B~+;<&JU|?TN179o#q6jMyUe
zrN*QP`pVrCx+zRTJGPL-NdJX=;p351`3rr^2J#n_ at roM!YHkIp%%X5jZZEf)^RYg3
z5-SUx<rFl4*`;dX`jLuq4mI&dp?h>(_<address@hidden|qhVn{1^QXaHHojp7iYvG5o7
zofT($XeO=8PSbx_Dn8C3-i{lgU4%upM{H6bl1Ja5p4=(?9gW0)As=nQRBR-z4I`%F
zVtgU~3?6_#pfyO3``|address@hidden<_KDV{t7&1 at address@hidden;8{q
zv<~`%((odP;i~*gZalY+TZzx3wkR5vLd#HRWI;br9lRdRVx8z9vQ}1;Q?xaT=3MYi
z15RTTNl{rr4Dw)k3-b{z9mCBQ9txWj<address@hidden(LLK`FFi6d;4pDT0K#gulQ
zkm*6AW4OJe`(8Lnr7?Up{i{8pc at TZUaG4v(^^TgV$?=wSRgPQ<8r?^I8^c9|JA62h
z7I`UG4v!7>rAj(eI!#WZcgjT5!&sj_QLReclyphhBHz_E(HR0kNBOW7x(u)Xtjm3B
zYw29=J1Eyz*o7#$v1EcZ{D)Tx3EID6z9d{WZs#%#V+$Cx%1C`N(X^La9oPVx^ltc3
z-u2wlwyL(Nu8+aOu+w!_>gr4JwhCxThCG+{(5#M*HMU{T6iJ2dSOe6Hc=ICFA>R;b
zF6=?w1Qk3a&yXLo&-G5HV^o+k`kC7t{7qZqLR>f9g!r_0lh~Rrh~1d at gFOgL)0Q at I
zG(CJ()k$^Ed-hM~KZ-xOS%vLwf|rHyigKi4c&U_#SMkMAS#gFX4Ap*!b})@e*`v~W
zI}7V#M{DNF$zmH_ at yNT3$?5)#mDxteX8%guSvi=#4R#4HVS-`__laezc3Tpn9P(0e
zLBUm)>;7hufu`$*LdeSnqQXLp{53zfX3oz0<~|kr$eq%aR63;r!6w0zk~Lh;GcH_8
z<21bD47 at YxYw{>A5{zi8TP#8td82wnC5L>u6Y?JAHL)M?%!<qq`-twybzhF>fWLfj
ztyc(*RjcC;>address@hidden|t19}S&mUV)XUA1_3oXOYfV^_K&uqW#pPak=m4!koUN-oL
z`m6y(sJ#EDzdk=Q`lU(9ztK-mZ4lig{F`-&USYf~Y}WR+wu(yehw^a#=A1&=zTB8V
zPb&G7oWq<8pu;#YwAlY%PS;g5wdRK?swQg-rHj2#QcTB$WxD5@<+1;oqr$ziM`ex6
zE}s1<XM}GKw#cvCrCnv5uiYJdXWWWF2?aL$)YpW@@dJu=HHUF$Q=jCf(OWb=OUd|3
zVtwbd{A>CD<nq~p{12h+;oYu_j<(J!o;QK2{!+ftY=EJgZaS)@PftmTtA`}z+r(ON
zf;vrK(b`>S^2OUGI2PN^W-rN|7HmSw`1ZQ0xs~2JAryWew9_2JhUk%sL&{4 at laq?@
z!>Q4{D0aGfozfqDB07z(bKJErwtvn!lC{U3D~W+y&X118u7vPKk{&53>(t5SSg|jC
zWGRx;E2<bPqhDs-tLw&1)}ArNqcXO~*)wuFWiQBj=d47_k{thUuiMT1h2?G1ok+A$
z%&d)if=z~UMMfn27DB2M)-};oe5cBa?y6G-mgb+yTbHxx_k}+PJ&D25?h(!e*A(B;
zNWT19KF*aiKa9Df#G2m)O$7!EgU}fB;MfYP4#E`U at Tja%E87EmhVzbnvh9iQc_iAW
zb3!OOdjuVF42?w>^nCm^-Bi9~%--aX`jd27TQ9DzPQ|%3mCQ4^Dz0VuukyvbzyB!m
zKKk$YU%Ip1X78TxDpVQ6-ld{_^i$nCsGRN=C}WAB!s?OMSj%Xkiy~m$plsn?mUk$(
zLf*lg7Wqws9i{Vu1m73eY0u=yRJvWx#l6jsEjKvAAB}Gx-%0q3H$}gWovAc&gQ9%;
z>k+}Z$<ftW-aaRPp>L72Bar4z at _0N$Lit2R_mQERW6=lIA>JJ4DfCcZ77x|cj{c(B
zNcM;yv<AXEZ`z?l?y2Ki>}xI`3T^gQ^Bi+846G!v>|eQ?f{%?Dt-`~oO$Cn{qvcs#
zs_D4?HNGv*H!?*%--rA=dAIW)=M2dE<r^O;<(0e#y|V%`ea7EskGNW9ZFIC)S6L<T
zSNsA|!%r}+vs4s|qXnANs+3T1#}r$p<GdqilYQkQ%>tR;w(cn|zyE@)lyl`P+U?Pq
zs-Il9=-~xq-4K3dlqV)yqeY)pmthUZybT;address@hidden@&>yfMoL6H!BhT~9^m&dmRJb$
z<4vjhW?WL#+vM6Yzqo_S%9h`{KCB||(address@hidden|E%#
z7g#a6gu8FV<_CNYv4fSy{=rEsA?ld%z7XWA8<y$Sbh!JLy`Za|V~wq-ziT+xzu&jP
zQ_<TnQWTeDvxrqw-O^5Vl$#jSGuf{jk49^znN}#uQ>3(MOQ5Tse0v+0&Yk37-e(eu
z+zhVwxAs~B$E3DICuQ>=Oqsg7=#Zv$!e-+mJW>@K^Vygn<cTW%XJNFzsC|vSp7S4D
zEvG5GN0P(0g4KNg_-VK}`6<;y6%1v~TZCtdGYP%on~Kx9Q&A_QdLt`os;a0`OAp+$
z-DiDg-5s2#0_I5bz<address@hidden
zn#s-ZcCuBmmvn5*f9T#8xg0(fDCbRfSMhI`C$a<*7W$i~>ho}kC{uFJ=#_k3<!93}
z{cQYDxT3!yo)35&gB*Xm3OSUnX`!g_JO51|@qF_Ylgy|Cxk at YRT1QPn2e`jt8^rby
z+X>@Lx1w9B_Vc;A`<e{tj{CDS-CfdE&SCQ(l6r^B2N(Hl-sIq>h$s9qqEhWO^BP&0
z8Z#IOdL$jDJRMb6oFSXUr5Y8Q;!pH!_AT;nbWis$k&i at DgD-tvk1^nvd$5WmR;+IB
zps$W*s$KCNjjz}@;kfCW{w8YAm(|@DHU+jiw%JA3Lc7&@DNLmjp)!Hp-jJ`loQYqv
zBV2dGXX78xO{c8et(6rexP`hbeRU3_7_CR+BOAOvM-}HqyV6$Bha&5P!vZILO?-iH
zBUFQN)T?qDe=B%A#PlPfs`fJOs7sE{)SSfQR0p&s*3Luija)0;|2WJ0%aY%btboq9
z(_PtjHQY~X5P8crGaii6iVdS?6p+jnu}4rDH)|g;hIN`k!m6Og-PY5~|H3`f{XL|L
zd<zWr*Y$l3lqQrdmlbTjc4X8SE{ji#T^sv}?}4vHF=HVyforLqsrgQZdzG$n?vc(N
z_Dg<yBsP>9nB-0K_yXPNIM$a5+W6=>nxWiMW0Uy8>Lb*wYGiOInzMLi8-0Lp8XV&8
z=icK|I97WnN+xMq=%v4=uVs+PDz-$P#|_uNQ>D;Y)jR7lQ-t58?qqT5C*r}}ZuM;b
zZa{J#ab5MO-0!>|$b)K;q+puwqkm=O4tXREqxZGMU=_D3x>(!AE#`UFTeDB+#k<&9
z^=tJOS$4aecRl;v^<Dqd0Os(xKs$fg-~nj{%498R3)Kh{QSIh*ro!>7)M1KLI-^y!
zoB6~nbqo^y&address@hidden<7y3%;DCSs37#i`dw840-sVMA~
z`3*I6LqK=?v at H~C!ks<KT&-P_?YQG<&>k5X-W6&W+!8z)xj>wedh$<I1)UDx<C;ZB
z$6iy$Dxyud%}W)RaAW9XVsh8}+;!I at xv#pigI>9P<V&Ew_q``I*iyF3^T|V1M^g#a
zMm*oJEAE)8I6bW>81-G;MK#KF?Nxjy at W;K<d)hC0zXn<nP8t at R;5YbZg(}mJthrnT
z-_>2$G{lLTh4E_h3!Km0)Xh=H(<IDmZU}S2!#)4Goxa1K#h#={De3RvEq^axOn^#P
zP!;wPGyM%?d2y>?ioRkY+*Gt%yDaL3(1qi)<<-;V)1J4E94F^2=m`2pOARAUBB4;3
zP&X-><&n2?FU7&AZHjc3sy`FkRa2LnuFW%1RTI`jSf|2B7d+{m>CgAybRYH|iu4Y5
z4qo;T at C^-yrS0SfSt^W(YOgEHw^h%Mon{z;fAY7rvQo<i;l3)JP$Y8Ad&<+pKhihT
ze?T5VE%Ntp>EMZAed#%=A-l)~rA1qszrr^(ud(zKXJ9AP{%yJL=$0~5`H~I`5?_nJ
zReyco!O&Q#O{i30ivMt+l=KUo;Vj%NWrD7bn8N;1jWK)|53>v6OwD;kO|GY+lX^N=
zGjcF+ConGX(l<W%R_Y_?OG6~96fYknZ2+(5(oTxkVqtVf>|`M7|Ii`6y84-74pQM$
z;(V^8TsHDBGD<oRXHU+-PG_d<mGUC7(lq%n(GxSv6w9loag*>address@hidden
zHk^Bg?UFCJB6u#WlrBb=lK)T|Dnm15hrFGfWNsG6>hn(&<@qZ}Qk2z}5*_ReuEoD+
zO-W^ZKxo7%m{aZ}HHwT6%?bUEbO79F9Z8Yq$<vTRsLW3n0?Pej3~tPiSJhVJLS+>r
zjO3T2i+HY3hZ{|XN3Mpm!kOXG(hgb?{lz3QkA&oJ@){D6yO0Iw2i^_G1kH*rilbaA
z7ZS#ZU$_Sl>HlB~^_zoiqob&ae3CIqBUeaA+LBd(gN5Jdd=jP{AYcpjFJ8nS$Lm-(
z+?ijCwMd8Wpa$$F9Yl+<>F5T##FW^FDxu}95>#{_NNZYw&StS3<`-~Jxn=w#+>DA)
z7p|r6$aJ;|_vf74X&h#g86&Udmt-C-N*|J`B$EteyYL36eaG;_xi)MY?TG*5hTuDR
z4u6*OvSQ4F4zTTX9yu*PlS|3p<*!T!hapQtHCi4eqX^r~(&-=SVb9oKY$IOFAI0xj
z7 at 4>h_$4aMIk-&R77d~=NKcY3^_EwVDEftF(_^eF9*B#f*6cRZzz#?mJd4W^lKB^m
zL(}kcREv#<$5Jv)-Y$<N?^$zv0;{>xD2c5j>address@hidden at 40|P<VkR
zvoy3Hoo6O?7~R7S at j^5YR%9g=rAkr{*+9;cRrDErryU|- at 44tMK8QqS!704J)#UE;
z2lzDZB(maSTt)nq{iN$iQ`sjCA!_y?)Z3+5ahger)address@hidden>
z=2mho at jWc@)%XCM37yScbOcSKRoOMxiCv*?dY1Xw3ATp*A)9Dv7Q<SjZ+s;&n;U?O
address@hidden;8pAr?GM)uMh55^R71(!M?4st__cgBG at Cd`
zQ+6J#=*C0&zIZdMLMO`x`MGpddLb_*`-l^I10zsH+ at 0g#ejoS-d}mw)JpK=N7l8ud
ze&D_A1l__`u^03XeL_D|MjY}ea*OmL>q$Af9K2PE`DhW8%C+GFXbj54YdI0_ at stlh
z|F;0lGlBaX&1X|+H8M_)mwOWh6VW4d9o=I&v=u!eGl`O=>>?|LmUHh!Eb6(!+;mQX
z+S4m+A#_?Q(9Yy1`N)address@hidden(nIw
zh(V01`LnnT`bF1KiOeK>$Vf7joFH)&u?)5dwMTDQNnDw0hkN12yj{q`QHaMyP$gQD
zUWe117g-)1%1WSgh|kY7mIdj5OkzXOU^I={sF!+~39m${YziBPda~y<3m*}9A%TC&
z-N8#)C$dfU$hAmN-bC)uGH4I3i|-*9DvOk?AuY<1aY;;ALtI}dDXf8<nTlt!dGbs7
z9p%_j8pV!)PcO3etOm=ZOX*os1F~`o%SKhXw|FyGj318Os2|vPH2%rXu$`<KTf?T|
zo?I?6vbJQlJYBvh-zPS((sf#iR40?chErJ`R2qNdqPUsZ$#)Xh at ZWG8m%<rw0#ajv
z8;ET5HN8v|XhG79EG4hx>Lh^{VVhBP+!8FQVPn`U8bc7Bf at YvG><+3btP;QSY5ZqC
z4_9INRA5Q$J-th+(30#13xYEK1nyl$#>iLY&a4COf+ujRg|b2w9HDyFhn<CJva&tw
zH--KfGNXc61=vv*XF at ca*mUrehwVgTQ5DF#mFOBRhH7)&aY^JxfAD+sopypeF|!UZ
z<Dq0UNg_MRMwSG9EFIfRkJ1gy0cbm&)AN0~1bh`w<=gNz at c=Xl4Q8#Nvvv>{<eKAt
zXgh62o=EQ^wdE8tm at KA7Rv#7N%5Zsr7X(d13)x<_AL4ol+Q~L>J%!I)5$+AQ7?*>}
zGMc<0cPXX6*$UJfaz#VC5<BTihm#bD8V53St2iB;j+Oa4=nHy|2c!RJ0<8EMWdCq_
address@hidden&{(address@hidden|u#1?ZixlL#?bPPA+DQE-gf_vgk5JxB2
zV%mfhC1yIBuAv=iNAgH6Kw41^dVr7dw}m$Rbo>b(GuS5D9nC{cAeM4bCO4M*1HHeE
z>;y!~W%7~Av;buHMD`eEpoYL6dzq3QA|1#$=EYBORh-246~=Ru;F?*eAsa!Kk%n{^
z-Nsf!*YG at AfcCMn%*9%um#jUFrlk-=>rf0gRXESbpn3E-yAR{nWSt=1U(kUho`hl4
z7qks~#qwA`c9li{Z;u;K0Lui?Pt4(p_z(AsV}OzYl#AXm18d8Av6J)=czZdZWkEKN
zu7JF1FTa(>$!*CPn$K!N-)u8fKYO?~{4hQp--q+(J2@>b$_TrF>tn{YfW?_?kg7|F
z6r%N6AH?A(TouKE9Tt#xaBltuDb5DqnOs?JD7Q`U2~D`Iz{;QTS$2pvq#dB2`-l!=
z4_Q0boSMmWau)iy<sd`50v}!jl%0nS+yzvPePwr1M;6O=V9dn>KFp&{XfxImSh_f_
zgr<O><5(f|6U|0NAzq%a>+A;`z|address@hidden at Ua|u8m)w}%WJ}>>eh+423(!qq&#7!7
z%^+^#A=l|vc8ZNbwYby#8on_12gh)$A#;bb)tKOPh at TD|k41KkP}wHO$m1k4DMNLP
zpiX!wF3eTN^VmG#z&mIG`$3nW9Gry~q4Qj- at CNS#e0vP}^O^2o-B1>r1jw05>X4(L
zG5;e)fay*_o)*D%xySekvT_EY2R|7+RvCX}>*z3c1^tGqp(dFj-;%BLH7kPm;*0n!
z`WLwCH89?I`knq_YmkkN$Fd*`gSqGUB-SB6-OFMDzwa?Ua7}-<lXd~rUQa5>A*rO?
zfRtc!&>KuSGrxg*fu^$Ws3Rze+khw?xLEEcR6?J*a=0OIdnML|79$q&oOGe(*ke`|
zqN+dYOxuw0(AmEY+UPE>!B at wPz_KH8UtAn5MEmeI6w4^{qVXse9R<5rV6)hEHiV6Y
zxH$r7QkZ>1CGaA)mJP$d at fYZ)$8+tt?Fg~%>^5B at E966RP)?y|SPp8#t>+fviRcCM
zvEFDZ+JySzanMxhjq<s3d=ZYI!zhszBDG0lCLu3+0@(YExyci`uRKehBToXXY)v-M
z_b7=wz?p<O!U?VuUct5HF*gqoDS$^}EBXe0+k=v5SZ)UyS%xep)address@hidden
zJCH$1mPRs*L!WUoK8LFY$U2t0$am-bcp6t0_X3_tVJlfjwx2#CwMcJLfo9QrtOWj_
zN;A?MG at 6;|eOei>=I-NPs0TNn-;ZO^Sz!75l%rMX0eYAQX*X0A$K$Jru_vG#JA)>O
zVzZEpWqbrr=5k=}F`y7uvl?_YDFbmg6Cc7gaUt9hO{5C?AMHvD(2v9bI698iMIp3@
zn*ci_hXMJ2;(VNfzu+1CI_?590v<MH{pcF<0)Bt69klUwRuO$+sptYb$v9jGrvj=m
address@hidden>&RBwu}wL!>|_b=9=&>address@hidden)pIkf)PxB!eu49hpb$FfPJ1f|VU%
z%g{>r{f at vL1+DiRbp}o>hYzyetQMO`ih*y=lP3_rH{ewKGIWs50%l!6)>AF}- at Z^D
zAf?ES1Ab`F^EeOA?rcM#>!^=i04$SOSM-`4BSqw0GDn&d=#$YV;address@hidden>
z6+{JLcV-su%gy2U at +PhwM9MgP0F-NCc82DX_MlNOQwu1OKG2n%OrHYB?qzON0o2-a
zdX&uvG;2wlv$Bw%J#j6rp-_y!iSDv>address@hidden|VEqOY)mZcsBEpbcQp
ztuCL%tN3o*T09qxpyfzyI*cmGXL$!XL{rcjJcVn`{f(1B$#r6X*hc6MoP#RkDb7U^
z^qbqs{brBoV^#_F?FO;VI1_wv1GJch_9gq|ko<~lA%wJHn?QNxp>t>sS^{V6 at 55*k
zp3n8gH_$<Ro3rC7Y#(jKnuDgbgI_8Fw~rznL2EvgOOTgjHZ26o{4OhwA93#?es+PX
z>W6!QR_D00+%nK{r?_6+LBQ2EbS3z>1ME>&VFy?<)EkXu0{}zKv^i-G>Wk5NtPZzD
zkoZ>|<>qj(7sfub=BN}~OUeSH9tP!C8UKq%p?vxT6n8Uf0K~43D{|?$B}xEgvjjgv
z|F9yEzpntnM}v~siI;<QUb1xdFCg7cdLHV&SQ<mOf||U<j?>NTF)+kX+zEE<ck at 2f
z02pXEIz*?_r7R3c^NuQ!2|HmI?+GZrG1LW~yZ|`A6Xmk!aO%G+{tZa<5cu>8<mn$I
zLq6KLt=t><d at VUAuO+L<UUHw-0NnY5P66^fLswBXw2K`B1y>1nLNib|{u!5#D{-HI
zvF4D2Bo}nrVo(p$SOV})6uSpCiyHX4KGZQQVGlllD{z_I0B$ULfJ*Uxt^xiD8o3ej
zf|uSRC4SGU)6=9haOVf8$Tvc5x`_57lH8sINl#iFR8uy0376u|2rHqkJ_7ek<(dI{
zJwb{1A!tb#T?E-Rl->i5Sts9?50PiI2MXe3Za(@9YIQ4A!s)atTE!Z%zaVDn2xIu7
z{0{y*)FqcGqrKUGkVgV2o2HP1CqP$qV5g{uB+*rDD;k9M<address@hidden(P`xx^
z6IlS%$9i at address@hidden&GU$Fy8s0mcS15qEyyq2sk
zRA_#3kmk@>`ib^JVNd`K*;#r7u)iRxf_4G6?!abj<h+2I^PpPjjQ+5Ab`<#6gpZ&+
zsG4um3nWW!O4gB!q!)G4JoXHC<0 at f0`Ww#z?eG)&HbwA$U>-F_oD;C2FjpLV=|N!O
zbF at 6$4QuOwtWdrFLlfya+67osrYqPeB%{K3BcKQ3V)0qP at o8uUn+Xpcn*m(~M$Pb=
zLD#am>@=va2&kZss3lqqF&hun at K3;jU$`sYi?rN*!0imCg83Ih4*)sdf^|32#h}3|
zvAc91*tj;iOKyOVkE1X*h%dp-1szfvTUi at 69_*P7n0y%OwU+oFxPu-gvx%S@@6oq(
zH)yTqz=nTe3VJgQU1hat9OPGhyaTkyEtq#D*o*FqcAz_OO&NNZRsf6Sp%17v%3!TQ
zGrHJZP%Jw at 7iwS!`x7gSuX1~FF4Lk_r~q2YWcCU){v)~>P-iU}MMi+iN=7Oqp!w)K
zsMcoqEnGhacfvK%cBJ4Ag06mz&f?biJo^Jm{3R&rt+XRVTpM&BMmYt2k`g4Ev?H&G
z2b8jdZQ&{kcc8LW at address@hidden)P<33)$arTA)1G=nWZ2HS9QRh)Sat
zs3OXsKj|O9^Dgu at s{}k)0Pnzm1GcWk%Ww*Gvx)&{O at X|Kg}Sm7`pF8hI`j=`OPjLl
z=x<Qq<?vcm4s37*MiNj_ at OUnI40^INsJIM>gCX=PC6LvtAy2I+oqc0>m=l<x9(1A(
z!9BLJTkHuo^U0vF-RLCxLbn3KH-TE$0UEJBoUW}6>Z~aAQaaLUbPjz=$FN0gHE7yY
z=mw+$mrjLhu?P!5JX`T4l!Y8fgpSNcIutqtLug%k61?1s831uc!QXsPXO}~_(NVOX
address@hidden|I9d&>*v+;9YrhAj-x_qwD9Gpy^cyIK7&Ha^rGiR#B8>4H
zJq6Y90=35yTyun(QDt-;address@hidden)3a2G#%+TqV$PHy{>UKyH6RN4Y9o
zJak4T;n8RU+t2=n(Oa-Yz<~td<wY=qY+%^yL__D%?yNRii|&C^nSmR_SSI`ql!Y6r
z at A`0(C=u7fakv7g(6NC0>sSgP_7VCOx;8!83+UC=MTbG*A7edWr7uBEErrfn58zBa
z(m at address@hidden>e)YayEedVeeXz^b7ls1A%?7ByqT*-Xf!%IJR at XgD5<
zo<XILnU>address@hidden&rLEfZ-jqWfjT8wYuH|R1-M+ER`K3xJ9
address@hidden|address@hidden at E5z)F{(
z%Df2GYhj4LOJFfG+~pSiO~(S3EMiaDV$=xElwf=t$KVw77sQtu at UsDKhxY>>ECU8U
z4p&tLuDMA!0TMK2cD5gWKHUVJWsd;iPe8AsH&lJ2&address@hidden
zpfGQ-o9F<V0K9gFMKLEt+B&uy4aY8Y3|8JAcSkdzOVbZcgzt`oQ!w?>KvW(51Cg{3
z)X!P)+5h at address@hidden(siCSv~`ehuWz+R7K74bwt4vF9A2}0CLv?^qawM0=lO|
z?wo~Bud&LYIfkRcs1{iKE#%k{1bT|ihMHChr)id;1Y8zh0sD1fRUjv`Xj?WOxT8NC
z2i&{~Sb00lsuijUnf8gT1Pcs>_56T1n+Y+ZMtfK;sIsHbAz2I_FAkhk2XyXqu+Try
zfjI{nsuU7&F}xH#1r&3_te2yFv=m)}zh;1LJ`dcM0g*Ko>=VnXvx-nZPJtC%XNMt^
address@hidden;3#z?<{nip|hd8V`F{D(H8$Wgq_^f&SMK
zX#+aP#>${^V4weKzS^h<(n6e@@j&?f`w_MQl=>q;fHzP<wTFAySWSq_qF|w;tSi{l
z4V9J-KZaa&06NS9##j$$ma>3T1AsO@;G*T|address@hidden)7p&$$7r<Y~
zLDfwHUIDH|eb6T0;4-W-#APLTo(7||15c%c6;hz0`w8_(L(I at t<b;ml3Yf`0SjAFg
zhidjLo5Kdfe6zqRcJOm!sEH4QTJ{0{=K>z~0-P<1Z=vF-0x;4)=p)n{2VlfhbOc4=
zXTYAH!OLMl&jO${U6AKt81*bvnh$_wmw?qyg0{QLPNLpe#J|x{K>Xt1_nJrveI+YI
zb}6v&JW!NV04LXjy at mqsM}T|gq4%)address@hidden(VX8K>dv{3PQgC
z;ZMRE8UfyQfDQ?0O_<SK$btKSHVVkbHvjA0LDeRp?Qq3!mJKTMHpG5;uq*+4Ux5DM
z8F>B#bJqislz|?2XPDo6=s`N!zfkp8L<7Lb)1cea8WhhS$btC~BijM*g0KgW1poDc
z5+y?JN254Ewd#<w*MO5I!(HkDXU&CCw!>XAL0_JM*QYSn|6=4ZSp6%^<Ox_Tz^Z_C
zhXB${f($5%7DMir1itJDck{3u-~tWwK^B3B_Q85z!>m<+p8o=pO$F>+0c*YiBTj)4
z=Ku?&gZ8V7dZK<Xn`DU36sX3}!8pHRJsF^;R{=lwgpB$ZFrX=DoVxIhLV&L;!3GwH
zm%Ctx2{7{!=nybhbC`bybeP|Q-EP8Md=Ob5AnUW>`7S(ipbm(EbAb(^E1Cusw+P-T
z1pV#DjEB6v3)lXy5BdY%JAog{gN-PBmdh~MzZ4)re^7;2p-yiMHY^Li-3gKK7;Jl+
zEdW)!7?js1h$ESmM<(F-yWs6}><dJN1Ti}hBD6VL54bfNkVgaew!`0IVa>_FnOR_~
zix4LZ0VPL6HZBA0=!DMBSQv8%<YZ~Ep%U`GGI|cSX^fh|d<Fr2m4_;8Bjo=Hu$31^
zDFl6~gD{gNfGqFe{vl8ZRUro|fp0eh(wBhPSPIuh0CDZm(cA-%(||+kV8lC+?-CPW
zZ8hP0K3F$`IB~=0Dwum^xXW_D`w^hrc(6+j)He^<cZiEOU?U&I>MO{HNs!r7Aitgg
zhs}WcaSBv)t6<%)*?Z{sS^;VGfb?yFJ1JN-2!4435rt3yB031!1c!hj`UQAq at GcDR
s#sB|bI~4E=Ed%h=|Hh8||Kop%^S}2T{6zw*!{Gq<E^OKT|J9WJA2^N;-T(jq

-- 
1.7.2.2




reply via email to

[Prev in Thread] Current Thread [Next in Thread]