home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / usr / share / python-support / gnome-orca / orca / speech.py < prev    next >
Encoding:
Python Source  |  2009-04-13  |  11.9 KB  |  381 lines

  1. # Orca
  2. #
  3. # Copyright 2004-2008 Sun Microsystems Inc.
  4. #
  5. # This library is free software; you can redistribute it and/or
  6. # modify it under the terms of the GNU Library General Public
  7. # License as published by the Free Software Foundation; either
  8. # version 2 of the License, or (at your option) any later version.
  9. #
  10. # This library is distributed in the hope that it will be useful,
  11. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13. # Library General Public License for more details.
  14. #
  15. # You should have received a copy of the GNU Library General Public
  16. # License along with this library; if not, write to the
  17. # Free Software Foundation, Inc., Franklin Street, Fifth Floor,
  18. # Boston MA  02110-1301 USA.
  19.  
  20. """Manages the default speech server for orca.  A script can use this
  21. as its speech server, or it can feel free to create one of its own."""
  22.  
  23. __id__        = "$Id: speech.py 4469 2009-01-28 13:42:35Z wwalker $"
  24. __version__   = "$Revision: 4469 $"
  25. __date__      = "$Date: 2009-01-28 08:42:35 -0500 (Wed, 28 Jan 2009) $"
  26. __copyright__ = "Copyright (c) 2005-2008 Sun Microsystems Inc."
  27. __license__   = "LGPL"
  28.  
  29. import logging
  30. log = logging.getLogger("speech")
  31.  
  32. import re
  33. import time
  34.  
  35. import chnames
  36. import debug
  37. import keynames
  38. import orca
  39. import orca_state
  40. import settings
  41.  
  42. from acss import ACSS
  43. from orca_i18n import _           # for gettext support
  44.  
  45. # The speech server to use for all speech operations.
  46. #
  47. _speechserver = None
  48.  
  49. # regular expressions for multiCaseStrings
  50. #
  51. multiCaseReg1 = re.compile("([a-z]+)([A-Z])")
  52. multiCaseReg2 = re.compile("([A-Z][A-Z]+)([A-Z][a-z]+)")
  53. multiCaseReg3 = re.compile("([A-Z])([A-Z][a-z]+)")
  54.  
  55. def getSpeechServerFactories():
  56.     """Imports all known SpeechServer factory modules.  Returns a list
  57.     of modules that implement the getSpeechServers method, which
  58.     returns a list of speechserver.SpeechServer instances.
  59.     """
  60.  
  61.     factories = []
  62.  
  63.     moduleNames = settings.speechFactoryModules
  64.     for moduleName in moduleNames:
  65.         try:
  66.             module =  __import__(moduleName,
  67.                                  globals(),
  68.                                  locals(),
  69.                                  [''])
  70.             factories.append(module)
  71.         except:
  72.             debug.printException(debug.LEVEL_OFF)
  73.  
  74.     return factories
  75.  
  76. def init():
  77.  
  78.     global _speechserver
  79.  
  80.     if _speechserver:
  81.         return
  82.  
  83.     # First, find the factory module to use.  We will
  84.     # allow the user to give their own factory module,
  85.     # thus we look first in the global name space, and
  86.     # then we look in the orca namespace.
  87.     #
  88.     moduleName = settings.speechServerFactory
  89.  
  90.     if moduleName:
  91.         debug.println(debug.LEVEL_CONFIGURATION,
  92.                       "Using speech server factory: %s" % moduleName)
  93.     else:
  94.         debug.println(debug.LEVEL_CONFIGURATION,
  95.                       "Speech not available.")
  96.         return
  97.  
  98.     factory = None
  99.     try:
  100.         factory =  __import__(moduleName,
  101.                               globals(),
  102.                               locals(),
  103.                               [''])
  104.     except:
  105.         try:
  106.             moduleName = moduleName.replace("orca.", "", 1)
  107.             factory =  __import__(moduleName,
  108.                                   globals(),
  109.                                   locals(),
  110.                                   [''])
  111.         except:
  112.             debug.printException(debug.LEVEL_SEVERE)
  113.  
  114.     # Now, get the speech server we care about.
  115.     #
  116.     speechServerInfo = settings.speechServerInfo
  117.     if speechServerInfo:
  118.         _speechserver = factory.SpeechServer.getSpeechServer(speechServerInfo)
  119.     else:
  120.         _speechserver = factory.SpeechServer.getSpeechServer()
  121.  
  122. def __resolveACSS(acss=None):
  123.     if acss:
  124.         return acss
  125.     else:
  126.         voices = settings.voices
  127.         return voices[settings.DEFAULT_VOICE]
  128.  
  129. def sayAll(utteranceIterator, progressCallback):
  130.     if settings.silenceSpeech:
  131.         return
  132.     if _speechserver:
  133.         _speechserver.sayAll(utteranceIterator, progressCallback)
  134.     else:
  135.         for [context, acss] in utteranceIterator:
  136.             logLine = "SPEECH OUTPUT: '" + context.utterance + "'"
  137.             debug.println(debug.LEVEL_INFO, logLine)
  138.             log.info(logLine)
  139.  
  140. def speak(text, acss=None, interrupt=True):
  141.     """Speaks all queued text immediately.  If text is not None,
  142.     it is added to the queue before speaking.
  143.  
  144.     Arguments:
  145.     - text:      optional text to add to the queue before speaking
  146.     - acss:      acss.ACSS instance; if None,
  147.                  the default voice settings will be used.
  148.                  Otherwise, the acss settings will be
  149.                  used to augment/override the default
  150.                  voice settings.
  151.     - interrupt: if True, stops any speech in progress before
  152.                  speaking the text
  153.     """
  154.  
  155.     # We will not interrupt a key echo in progress.
  156.     #
  157.     if orca_state.lastKeyEchoTime:
  158.         interrupt = interrupt \
  159.             and ((time.time() - orca_state.lastKeyEchoTime) > 0.5)
  160.  
  161.     if settings.silenceSpeech:
  162.         return
  163.  
  164.     if settings.speakMultiCaseStringsAsWords:
  165.         text = _processMultiCaseString(text)
  166.     if orca_state.activeScript and orca_state.usePronunciationDictionary:
  167.         text = orca_state.activeScript.adjustForPronunciation(text)
  168.     if settings.speakMultiCaseStringsAsWords:
  169.         text = _processMultiCaseString(text)
  170.  
  171.     logLine = "SPEECH OUTPUT: '" + text + "'"
  172.     debug.println(debug.LEVEL_INFO, logLine)
  173.     log.info(logLine)
  174.  
  175.     if _speechserver:
  176.         _speechserver.speak(text, __resolveACSS(acss), interrupt)
  177.  
  178. def speakKeyEvent(event_string, eventType):
  179.     """Speaks a key event immediately.
  180.  
  181.     Arguments:
  182.     - event_string: string representing the key event as defined by
  183.                     input_event.KeyboardEvent.
  184.     - eventType:    key event type as one of orca.KeyEventType constants.
  185.  
  186.     """
  187.     if settings.silenceSpeech:
  188.         return
  189.  
  190.     if _speechserver:
  191.         _speechserver.speakKeyEvent(event_string, eventType)
  192.     else:
  193.         # Check to see if there are localized words to be spoken for
  194.         # this key event.
  195.         #
  196.         event_string = keynames.getKeyName(event_string)
  197.  
  198.         if eventType == orca.KeyEventType.LOCKING_LOCKED:
  199.             # Translators: this represents the state of a locking modifier
  200.             # key (e.g., Caps Lock)
  201.             #
  202.             event_string += " " + _("on")
  203.         elif eventType == orca.KeyEventType.LOCKING_UNLOCKED:
  204.             # Translators: this represents the state of a locking modifier
  205.             # key (e.g., Caps Lock)
  206.             #
  207.             event_string += " " + _("off")
  208.  
  209.         logLine = "SPEECH OUTPUT: '" + event_string +"'"
  210.         debug.println(debug.LEVEL_INFO, logLine)
  211.         log.info(logLine)
  212.  
  213. def speakCharacter(character, acss=None):
  214.     """Speaks a single character immediately.
  215.  
  216.     Arguments:
  217.     - character: text to be spoken
  218.     - acss:      acss.ACSS instance; if None,
  219.                  the default voice settings will be used.
  220.                  Otherwise, the acss settings will be
  221.                  used to augment/override the default
  222.                  voice settings.
  223.     """
  224.     if settings.silenceSpeech:
  225.         return
  226.  
  227.     spokenCharacter = chnames.getCharacterName(character)
  228.     debug.println(debug.LEVEL_INFO, "SPEECH OUTPUT: '" + spokenCharacter + "'")
  229.     log.info("SPEECH OUTPUT: '%s'" % spokenCharacter)
  230.  
  231.     if _speechserver:
  232.         _speechserver.speakCharacter(character, acss=acss)
  233.  
  234. def isSpeaking():
  235.     """Returns True if the system is currently speaking."""
  236.     if _speechserver:
  237.         return _speechserver.isSpeaking()
  238.     else:
  239.         return False
  240.  
  241. def speakUtterances(utterances, acss=None, interrupt=True):
  242.     """Speaks the given list of utterances immediately.
  243.  
  244.     Arguments:
  245.     - list:      list of strings to be spoken
  246.     - acss:      acss.ACSS instance; if None,
  247.                  the default voice settings will be used.
  248.                  Otherwise, the acss settings will be
  249.                  used to augment/override the default
  250.                  voice settings.
  251.     - interrupt: if True, stop any speech currently in progress.
  252.     """
  253.  
  254.     # We will not interrupt a key echo in progress.
  255.     #
  256.     if orca_state.lastKeyEchoTime:
  257.         interrupt = interrupt \
  258.             and ((time.time() - orca_state.lastKeyEchoTime) > 0.5)
  259.  
  260.     if settings.silenceSpeech:
  261.         return
  262.     i = 0
  263.     length = len(utterances)
  264.     while ( i < length ):
  265.         if settings.speakMultiCaseStringsAsWords:
  266.             utterances[i] = _processMultiCaseString(utterances[i])
  267.         if orca_state.activeScript and orca_state.usePronunciationDictionary:
  268.             utterances[i] = orca_state.activeScript.adjustForPronunciation(\
  269.                             utterances[i])
  270.         if settings.speakMultiCaseStringsAsWords:
  271.             utterances[i] = _processMultiCaseString(utterances[i])
  272.         logLine = "SPEECH OUTPUT: '" + utterances[i] + "'"
  273.         debug.println(debug.LEVEL_INFO, logLine)
  274.         log.info(logLine)
  275.         i = i + 1
  276.  
  277.     if _speechserver:
  278.         _speechserver.speakUtterances(utterances,
  279.                                        __resolveACSS(acss),
  280.                                        interrupt)
  281.  
  282. def getInfo():
  283.     info = None
  284.     if _speechserver:
  285.         info = _speechserver.getInfo()
  286.  
  287.     return info
  288.  
  289. def stop():
  290.     if _speechserver:
  291.         _speechserver.stop()
  292.  
  293. def increaseSpeechRate(script=None, inputEvent=None):
  294.     if _speechserver:
  295.         _speechserver.increaseSpeechRate()
  296.     else:
  297.         logLine = "SPEECH OUTPUT: 'faster'"
  298.         debug.println(debug.LEVEL_INFO, logLine)
  299.         log.info(logLine)
  300.  
  301.     return True
  302.  
  303. def decreaseSpeechRate(script=None, inputEvent=None):
  304.     if _speechserver:
  305.         _speechserver.decreaseSpeechRate()
  306.     else:
  307.         logLine = "SPEECH OUTPUT: 'slower'"
  308.         debug.println(debug.LEVEL_INFO, logLine)
  309.         log.info(logLine)
  310.  
  311.     return True
  312.  
  313. def increaseSpeechPitch(script=None, inputEvent=None):
  314.     if _speechserver:
  315.         _speechserver.increaseSpeechPitch()
  316.     else:
  317.         logLine = "SPEECH OUTPUT: 'higher'"
  318.         debug.println(debug.LEVEL_INFO, logLine)
  319.         log.info(logLine)
  320.  
  321.     return True
  322.  
  323. def decreaseSpeechPitch(script=None, inputEvent=None):
  324.     if _speechserver:
  325.         _speechserver.decreaseSpeechPitch()
  326.     else:
  327.         logLine = "SPEECH OUTPUT: 'lower'"
  328.         debug.println(debug.LEVEL_INFO, logLine)
  329.         log.info(logLine)
  330.  
  331.     return True
  332.  
  333. def shutdown():
  334.     global _speechserver
  335.     if _speechserver:
  336.         _speechserver.shutdownActiveServers()
  337.         _speechserver = None
  338.  
  339. def reset(text=None, acss=None):
  340.     if _speechserver:
  341.         _speechserver.reset(text, acss)
  342.  
  343. def testNoSettingsInit():
  344.     init()
  345.     speak("testing")
  346.     speak("this is higher", ACSS({'average-pitch' : 7}))
  347.     speak("this is slower", ACSS({'rate' : 3}))
  348.     speak("this is faster", ACSS({'rate' : 80}))
  349.     speak("this is quiet",  ACSS({'gain' : 2}))
  350.     speak("this is loud",   ACSS({'gain' : 10}))
  351.     speak("this is normal")
  352.  
  353. def test():
  354.     import speechserver
  355.     factories = getSpeechServerFactories()
  356.     for factory in factories:
  357.         print factory.__name__
  358.         servers = factory.SpeechServer.getSpeechServers()
  359.         for server in servers:
  360.             try:
  361.                 print "    ", server.getInfo()
  362.                 for family in server.getVoiceFamilies():
  363.                     name = family[speechserver.VoiceFamily.NAME]
  364.                     print "      ", name
  365.                     acss = ACSS({ACSS.FAMILY : family})
  366.                     server.speak(name, acss)
  367.                     server.speak("testing")
  368.                 server.shutdown()
  369.             except:
  370.                 debug.printException(debug.LEVEL_OFF)
  371.  
  372. def _processMultiCaseString(string):
  373.     """Helper function, applies the regexes to split multiCaseStrings
  374.     to multiple words.
  375.     """
  376.  
  377.     string = multiCaseReg1.sub('\\1 \\2', string)
  378.     string = multiCaseReg2.sub('\\1 \\2', string)
  379.     string = multiCaseReg3.sub('\\1 \\2', string)    
  380.     return string
  381.