diff --git a/stardew-access/Features/ReadTile.cs b/stardew-access/Features/ReadTile.cs
index 8c2d547..55f743a 100644
--- a/stardew-access/Features/ReadTile.cs
+++ b/stardew-access/Features/ReadTile.cs
@@ -68,7 +68,7 @@ namespace stardew_access.Game
                         if (terrain != null)
                             toSpeak = terrain;
                     }
-                    else if ( Game1.currentLocation.getLargeTerrainFeatureAt(x, y) != null)
+                    else if ( Game1.currentLocation.getLargeTerrainFeatureAt(x, y) != null )
                     {
                         toSpeak = "Bush";
                     }
diff --git a/stardew-access/LinuxSpeech/libspeechd.py b/stardew-access/LinuxSpeech/libspeechd.py
new file mode 100644
index 0000000..048a5f8
--- /dev/null
+++ b/stardew-access/LinuxSpeech/libspeechd.py
@@ -0,0 +1,12 @@
+from multiprocessing.connection import wait
+from threading import Thread
+from time import time
+import speechd
+import time
+
+client = speechd.SSIPClient('test')
+client.speak("Hello World! this is yusuf")
+time.sleep(1)
+client.stop()
+client.speak("No this is shoaib")
+client.close()
\ No newline at end of file
diff --git a/stardew-access/LinuxSpeech/speechd/__init__.py b/stardew-access/LinuxSpeech/speechd/__init__.py
new file mode 100644
index 0000000..ee45936
--- /dev/null
+++ b/stardew-access/LinuxSpeech/speechd/__init__.py
@@ -0,0 +1,17 @@
+# 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 Lesser General Public License as published by
+# the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+from .client import *
+
diff --git a/stardew-access/LinuxSpeech/speechd/client.py b/stardew-access/LinuxSpeech/speechd/client.py
new file mode 100644
index 0000000..b009e3f
--- /dev/null
+++ b/stardew-access/LinuxSpeech/speechd/client.py
@@ -0,0 +1,1186 @@
+# 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 Lesser General Public License as published by
+# the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+"""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
+
+from . 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 = b"\r\n"
+    _END_OF_DATA_MARKER = b'.'
+    _END_OF_DATA_MARKER_ESCAPED = b'..'
+    _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 as ex:
+            raise SSIPCommunicationError("Can't open socket using method "
+                                         + communication_method,
+                                         original_exception = ex)
+
+        self._buffer = b""
+        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",
+                                 daemon=True)
+        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.decode('utf-8')
+
+    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.is_alive():
+            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.encode('utf-8') + 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.
+        
+        """
+        data = data.encode('utf-8')
+        # 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 some of the user-defined punctuation characters are read."""
+    MOST = 'most'
+    """Only most of 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:/run/user/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 $XDG_RUNTIME_DIR/speech-dispatcher/speechd.sock
+            where $XDG_RUNTIME_DIR is determined using the XDG Base Directory
+            Specification.
+          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.
+        """
+
+        _home = os.path.expanduser("~")
+        _runtime_dir = os.environ.get('XDG_RUNTIME_DIR', os.environ.get('XDG_CACHE_HOME', os.path.join(_home, '.cache')))
+        _sock_path = os.path.join(_runtime_dir, self.DEFAULT_SOCKET_PATH)
+        # Resolve connection parameters:
+        connection_args = {'communication_method': CommunicationMethod.UNIX_SOCKET,
+                           'socket_path': _sock_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 as 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 as 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),))
+        cmd = os.getenv("SPEECHD_CMD")
+        if not cmd:
+            cmd = paths.SPD_SPAWN_CMD
+        if os.path.exists(cmd):
+            connection_params = []
+            for param, value in connection_args.items():
+                if param not in ["host",]:
+                    connection_params += ["--"+param.replace("_","-"), str(value)]
+
+            server = subprocess.Popen([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"
+                                         % (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')
+        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.
+
+        """
+        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, variant).
+
+        'name' is a string, 'language' is an ISO 639-1 Alpha-2/3 language code
+        and 'variant' is a string.  Language and variant may be None.
+
+        """
+        try:
+            code, msg, data = self._conn.send_command('LIST', 'SYNTHESIS_VOICES')
+        except SSIPCommandError:
+            return ()
+        def split(item):
+            name, lang, variant = tuple(item.rsplit('\t', 3))
+            return (name, lang or None, variant 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/three letter language code according to RFC 1766 as string, possibly with a region qualification.
+          scope -- see the documentation of this class.
+            
+        """
+        assert isinstance(language, str)
+        self._conn.send_command('SET', scope, 'LANGUAGE', language)
+
+    def get_language(self):
+        """Get the current language."""
+        code, msg, data = self._conn.send_command('GET', 'LANGUAGE')
+        if data:
+            return data[0]
+        return None
+
+    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 get_output_module(self):
+        """Get the current output module."""
+        code, msg, data = self._conn.send_command('GET', 'OUTPUT_MODULE')
+        if data:
+            return data[0]
+        return None
+
+    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 get_pitch(self):
+        """Get the current pitch."""
+        code, msg, data = self._conn.send_command('GET', 'PITCH')
+        if data:
+            return data[0]
+        return None
+
+    def set_pitch_range(self, value, scope=Scope.SELF):
+        """Set the pitch range for further speech commands.
+
+        Arguments:
+          value -- integer value within the range from -100 to 100, with 0
+            corresponding to the default pitch range of the current speech synthesis
+            output module, lower values meaning lower pitch range and higher values
+            meaning higher pitch range.
+          scope -- see the documentation of this class.
+          
+        """
+        assert isinstance(value, int) and -100 <= value <= 100, value
+        self._conn.send_command('SET', scope, 'PITCH_RANGE', 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 get_rate(self):
+        """Get the current speech rate (speed)."""
+        code, msg, data = self._conn.send_command('GET', 'RATE')
+        if data:
+            return data[0]
+        return None
+
+    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 get_volume(self):
+        """Get the speech volume."""
+        code, msg, data = self._conn.send_command('GET', 'VOLUME')
+        if data:
+            return data[0]
+        return None
+
+    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.MOST,
+                         PunctuationMode.SOME, PunctuationMode.NONE), value
+        self._conn.send_command('SET', scope, 'PUNCTUATION', value)
+
+    def get_punctuation(self):
+        """Get the punctuation pronounciation level."""
+        code, msg, data = self._conn.send_command('GET', 'PUNCTUATION')
+        if data:
+            return data[0]
+        return None
+
+    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_TYPE', 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/stardew-access/LinuxSpeech/speechd/paths.py b/stardew-access/LinuxSpeech/speechd/paths.py
new file mode 100644
index 0000000..da8f18a
--- /dev/null
+++ b/stardew-access/LinuxSpeech/speechd/paths.py
@@ -0,0 +1 @@
+SPD_SPAWN_CMD = "/usr/local/bin/speech-dispatcher"