mirror of
https://github.com/MCV-Software/TWBlue.git
synced 2025-04-09 04:52:30 -04:00
Updated accessible_output2. Add mac and a better linux support
This commit is contained in:
parent
6a4a3cc94e
commit
fe9f724673
@ -1,19 +1,23 @@
|
|||||||
|
from __future__ import absolute_import
|
||||||
import ctypes
|
import ctypes
|
||||||
import os
|
import os
|
||||||
import types
|
import types
|
||||||
from platform_utils import paths
|
from platform_utils import paths
|
||||||
|
|
||||||
def load_library(libname):
|
def load_library(libname, cdll=False):
|
||||||
if paths.is_frozen():
|
if paths.is_frozen():
|
||||||
libfile = os.path.join(paths.embedded_data_path(), 'accessible_output2', 'lib', libname)
|
libfile = os.path.join(paths.embedded_data_path(), 'accessible_output2', 'lib', libname)
|
||||||
else:
|
else:
|
||||||
libfile = os.path.join(paths.module_path(), 'lib', libname)
|
libfile = os.path.join(paths.module_path(), 'lib', libname)
|
||||||
|
if cdll:
|
||||||
|
return ctypes.cdll[libfile]
|
||||||
|
else:
|
||||||
return ctypes.windll[libfile]
|
return ctypes.windll[libfile]
|
||||||
|
|
||||||
def get_output_classes():
|
def get_output_classes():
|
||||||
import outputs
|
from . import outputs
|
||||||
module_type = types.ModuleType
|
module_type = types.ModuleType
|
||||||
classes = [m.output_class for m in outputs.__dict__.itervalues() if type(m) == module_type and hasattr(m, 'output_class')]
|
classes = [m.output_class for m in outputs.__dict__.values() if type(m) == module_type and hasattr(m, 'output_class')]
|
||||||
return sorted(classes, key=lambda c: c.priority)
|
return sorted(classes, key=lambda c: c.priority)
|
||||||
|
|
||||||
def find_datafiles():
|
def find_datafiles():
|
||||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1,16 +1,20 @@
|
|||||||
|
from __future__ import absolute_import
|
||||||
import platform
|
import platform
|
||||||
if platform.system() == 'Windows':
|
if platform.system() == 'Windows':
|
||||||
import nvda
|
from . import nvda
|
||||||
import jaws
|
from . import jaws
|
||||||
import sapi5
|
from . import sapi5
|
||||||
import window_eyes
|
from . import window_eyes
|
||||||
import system_access
|
from . import system_access
|
||||||
import dolphin
|
from . import dolphin
|
||||||
import pc_talker
|
from . import pc_talker
|
||||||
#import sapi4
|
#import sapi4
|
||||||
elif platform.system() == "Darwin":
|
|
||||||
import voiceover
|
|
||||||
elif platform.system() == "Linux":
|
|
||||||
import speechDispatcher
|
|
||||||
|
|
||||||
import auto
|
if platform.system() == 'Darwin':
|
||||||
|
from . import voiceover
|
||||||
|
from . import say
|
||||||
|
|
||||||
|
if platform.system() == 'Linux':
|
||||||
|
from . import e_speak
|
||||||
|
|
||||||
|
from . import auto
|
||||||
|
@ -1,17 +1,10 @@
|
|||||||
import platform
|
from __future__ import absolute_import
|
||||||
import accessible_output2
|
import accessible_output2
|
||||||
from base import Output, OutputError
|
from .base import Output, OutputError
|
||||||
|
|
||||||
class Auto(Output):
|
class Auto(Output):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
if platform.system() == "Darwin":
|
|
||||||
import voiceover
|
|
||||||
self.outputs = [voiceover.VoiceOver()]
|
|
||||||
elif platform.system() == "Linux":
|
|
||||||
import speechDispatcher
|
|
||||||
self.outputs = [speechDispatcher.SpeechDispatcher()]
|
|
||||||
elif platform.system() == "Windows":
|
|
||||||
output_classes = accessible_output2.get_output_classes()
|
output_classes = accessible_output2.get_output_classes()
|
||||||
self.outputs = []
|
self.outputs = []
|
||||||
for output in output_classes:
|
for output in output_classes:
|
||||||
@ -40,3 +33,8 @@ class Auto(Output):
|
|||||||
output = self.get_first_available_output()
|
output = self.get_first_available_output()
|
||||||
if output:
|
if output:
|
||||||
output.speak(*args, **kwargs)
|
output.speak(*args, **kwargs)
|
||||||
|
|
||||||
|
def is_system_output(self):
|
||||||
|
output = self.get_first_available_output()
|
||||||
|
if output:
|
||||||
|
return output.is_system_output()
|
||||||
|
@ -5,27 +5,43 @@ class OutputError(Exception):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
class Output(object):
|
class Output(object):
|
||||||
name = "Unnamed Output" #The name of this output
|
name = "Unnamed Output"
|
||||||
lib32 = None #name of 32-bit lib
|
lib32 = None
|
||||||
lib64 = None #name of 64-bit lib
|
lib64 = None
|
||||||
priority = 100 #Where to sort in the list of available outputs for automaticly speaking
|
argtypes = {}
|
||||||
|
cdll = False
|
||||||
|
priority = 100
|
||||||
|
system_output = False
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
is_32bit = platform.architecture()[0] == "32bit"
|
self.is_32bit = platform.architecture()[0] == "32bit"
|
||||||
if self.lib32 and is_32bit:
|
if self.lib32 and self.is_32bit:
|
||||||
self.lib = load_library(self.lib32)
|
self.lib = load_library(self.lib32, cdll=self.cdll)
|
||||||
elif self.lib64:
|
elif self.lib64:
|
||||||
self.lib = load_library(self.lib64)
|
self.lib = load_library(self.lib64, cdll=self.cdll)
|
||||||
|
else:
|
||||||
|
self.lib = None
|
||||||
|
if self.lib is not None:
|
||||||
|
for func in self.argtypes:
|
||||||
|
try:
|
||||||
|
getattr(self.lib, func).argtypes = self.argtypes[func]
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
|
||||||
def output(self, text, **options):
|
def output(self, text, **options):
|
||||||
output = False
|
output = False
|
||||||
if hasattr(self, 'speak') and callable(self.speak):
|
if self.speak(text, **options):
|
||||||
self.speak(text, **options)
|
|
||||||
output = True
|
output = True
|
||||||
if hasattr(self, 'braille') and callable(self.braille):
|
if self.braille(text, **options):
|
||||||
self.braille(text, **options)
|
|
||||||
output = True
|
output = True
|
||||||
if not output:
|
if not output:
|
||||||
raise RuntimeError("Output %r does not have any method defined to output" % self)
|
raise RuntimeError("Output %r does not have any method defined to output" % self)
|
||||||
|
|
||||||
|
def is_system_output(self):
|
||||||
|
return self.system_output
|
||||||
|
|
||||||
|
def speak(self, **optiont):
|
||||||
|
return False
|
||||||
|
|
||||||
|
def braille(self, **options):
|
||||||
|
return False
|
||||||
|
@ -1,19 +1,25 @@
|
|||||||
|
from __future__ import absolute_import
|
||||||
import os
|
import os
|
||||||
|
import ctypes
|
||||||
|
|
||||||
from base import Output
|
from .base import Output
|
||||||
|
|
||||||
class Dolphin (Output):
|
class Dolphin (Output):
|
||||||
"""Supports dolphin products."""
|
"""Supports dolphin products."""
|
||||||
|
|
||||||
name = 'Dolphin'
|
name = 'Dolphin'
|
||||||
lib32 = 'dolapi.dll'
|
lib32 = 'dolapi.dll'
|
||||||
|
argtypes = {
|
||||||
|
'DolAccess_Command': (ctypes.c_wchar_p, ctypes.c_int, ctypes.c_int),
|
||||||
|
'DolAccess_Action': (ctypes.c_int,),
|
||||||
|
}
|
||||||
|
|
||||||
def speak(self, text, interrupt=0):
|
def speak(self, text, interrupt=0):
|
||||||
if interrupt:
|
if interrupt:
|
||||||
self.silence()
|
self.silence()
|
||||||
#If we don't call this, the API won't let us speak.
|
#If we don't call this, the API won't let us speak.
|
||||||
if self.is_active():
|
if self.is_active():
|
||||||
self.lib.DolAccess_Command(unicode(text), (len(text)*2)+2, 1)
|
self.lib.DolAccess_Command(text, (len(text)*2)+2, 1)
|
||||||
|
|
||||||
def silence(self):
|
def silence(self):
|
||||||
self.lib.DolAccess_Action(141)
|
self.lib.DolAccess_Action(141)
|
||||||
|
31
src/accessible_output2/outputs/e_speak.py
Normal file
31
src/accessible_output2/outputs/e_speak.py
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
from __future__ import absolute_import
|
||||||
|
from .base import Output
|
||||||
|
|
||||||
|
try:
|
||||||
|
import espeak.core
|
||||||
|
except:
|
||||||
|
raise RuntimeError("Cannot find espeak.core. Please install python-espeak")
|
||||||
|
|
||||||
|
class ESpeak(Output):
|
||||||
|
"""Speech output supporting ESpeak on Linux
|
||||||
|
Note this requires python-espeak to be installed
|
||||||
|
This can be done on Debian distros by using apt-get install python-espeak
|
||||||
|
Or through this tarball: https://launchpad.net/python-espeak
|
||||||
|
"""
|
||||||
|
name = "Linux ESpeak"
|
||||||
|
|
||||||
|
def is_active(self):
|
||||||
|
try:
|
||||||
|
import espeak.core
|
||||||
|
except:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
def speak(self, text, interrupt = 0):
|
||||||
|
if interrupt:
|
||||||
|
self.silence()
|
||||||
|
espeak.core.synth(text)
|
||||||
|
def silence(self):
|
||||||
|
espeak.core.cancel()
|
||||||
|
|
||||||
|
output_class = ESpeak
|
@ -1,8 +1,9 @@
|
|||||||
|
from __future__ import absolute_import
|
||||||
import win32gui
|
import win32gui
|
||||||
from libloader.com import load_com
|
from libloader.com import load_com
|
||||||
import pywintypes
|
import pywintypes
|
||||||
|
|
||||||
from base import Output, OutputError
|
from .base import Output, OutputError
|
||||||
|
|
||||||
class Jaws (Output):
|
class Jaws (Output):
|
||||||
"""Output supporting the Jaws for Windows screen reader."""
|
"""Output supporting the Jaws for Windows screen reader."""
|
||||||
|
@ -1,15 +1,21 @@
|
|||||||
|
from __future__ import absolute_import
|
||||||
import os
|
import os
|
||||||
import platform
|
import platform
|
||||||
|
import ctypes
|
||||||
|
|
||||||
from platform_utils import paths
|
from platform_utils import paths
|
||||||
from libloader import load_library
|
from libloader import load_library
|
||||||
from base import Output
|
from .base import Output
|
||||||
|
|
||||||
class NVDA(Output):
|
class NVDA(Output):
|
||||||
"""Supports The NVDA screen reader"""
|
"""Supports The NVDA screen reader"""
|
||||||
name = "NVDA"
|
name = "NVDA"
|
||||||
lib32 = 'nvdaControllerClient32.dll'
|
lib32 = 'nvdaControllerClient32.dll'
|
||||||
lib64 = 'nvdaControllerClient64.dll'
|
lib64 = 'nvdaControllerClient64.dll'
|
||||||
|
argtypes = {
|
||||||
|
'nvdaController_brailleMessage': (ctypes.c_wchar_p,),
|
||||||
|
'nvdaController_speakText': (ctypes.c_wchar_p,),
|
||||||
|
}
|
||||||
|
|
||||||
def is_active(self):
|
def is_active(self):
|
||||||
try:
|
try:
|
||||||
@ -18,12 +24,12 @@ class NVDA(Output):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
def braille(self, text, **options):
|
def braille(self, text, **options):
|
||||||
self.lib.nvdaController_brailleMessage(unicode(text))
|
self.lib.nvdaController_brailleMessage(text)
|
||||||
|
|
||||||
def speak(self, text, interrupt=False):
|
def speak(self, text, interrupt=False):
|
||||||
if interrupt:
|
if interrupt:
|
||||||
self.silence()
|
self.silence()
|
||||||
self.lib.nvdaController_speakText(unicode(text))
|
self.lib.nvdaController_speakText(text)
|
||||||
|
|
||||||
def silence(self):
|
def silence(self):
|
||||||
self.lib.nvdaController_cancelSpeech()
|
self.lib.nvdaController_cancelSpeech()
|
||||||
|
@ -1,14 +1,19 @@
|
|||||||
|
from __future__ import absolute_import
|
||||||
import ctypes
|
import ctypes
|
||||||
from base import Output
|
from .base import Output
|
||||||
|
|
||||||
class PCTalker(Output):
|
class PCTalker(Output):
|
||||||
lib32 = 'pctkusr.dll'
|
lib32 = 'pctkusr.dll'
|
||||||
lib64 = 'pctkusr64.dll'
|
lib64 = 'pctkusr64.dll'
|
||||||
|
cdll = True
|
||||||
|
argtypes = {
|
||||||
|
'PCTKPRead': (ctypes.c_char_p, ctypes.c_int, ctypes.c_int)
|
||||||
|
}
|
||||||
|
|
||||||
def speak(self, text, interrupt=False):
|
def speak(self, text, interrupt=False):
|
||||||
if interrupt:
|
if interrupt:
|
||||||
self.silence()
|
self.silence()
|
||||||
self.lib.PCTKPRead(text.encode('cp932', 'replace'))
|
self.lib.PCTKPRead(text.encode('cp932', 'replace'), 0, 1)
|
||||||
|
|
||||||
def silence(self):
|
def silence(self):
|
||||||
self.lib.PCTKVReset()
|
self.lib.PCTKVReset()
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
|
from __future__ import absolute_import
|
||||||
|
from builtins import range
|
||||||
from libloader.com import load_com
|
from libloader.com import load_com
|
||||||
from base import Output
|
from .base import Output
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
@ -1,12 +1,19 @@
|
|||||||
# -*- coding: utf-8 -*-
|
from __future__ import absolute_import
|
||||||
import config
|
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
from libloader.com import load_com
|
from libloader.com import load_com
|
||||||
from base import Output, OutputError
|
from .base import Output, OutputError
|
||||||
import pywintypes
|
import pywintypes
|
||||||
import logging
|
import logging
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
SVSFDefault = 0
|
||||||
|
SVSFlagsAsync = 1
|
||||||
|
SVSFPurgeBeforeSpeak = 2
|
||||||
|
SVSFIsFilename = 4
|
||||||
|
SVSFIsXML = 8
|
||||||
|
SVSFIsNotXML = 16
|
||||||
|
SVSFPersistXML = 32
|
||||||
|
|
||||||
class SAPI5(Output):
|
class SAPI5(Output):
|
||||||
has_volume = True
|
has_volume = True
|
||||||
has_rate = True
|
has_rate = True
|
||||||
@ -19,9 +26,9 @@ class SAPI5(Output):
|
|||||||
max_volume = 100
|
max_volume = 100
|
||||||
name = "sapi5"
|
name = "sapi5"
|
||||||
priority = 101
|
priority = 101
|
||||||
|
system_output = True
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
if config.app["app-settings"]["voice_enabled"] == False: raise OutputError
|
|
||||||
try:
|
try:
|
||||||
self.object = load_com("SAPI.SPVoice")
|
self.object = load_com("SAPI.SPVoice")
|
||||||
self._voices = self._available_voices()
|
self._voices = self._available_voices()
|
||||||
@ -36,14 +43,14 @@ class SAPI5(Output):
|
|||||||
return _voices
|
return _voices
|
||||||
|
|
||||||
def list_voices(self):
|
def list_voices(self):
|
||||||
return self.available_voices.keys()
|
return list(self._voices.keys())
|
||||||
|
|
||||||
def get_voice(self):
|
def get_voice(self):
|
||||||
return self.object.Voice.GetDescription()
|
return self.object.Voice.GetDescription()
|
||||||
|
|
||||||
def set_voice(self, value):
|
def set_voice(self, value):
|
||||||
log.debug("Setting SAPI5 voice to \"%s\"" % value)
|
log.debug("Setting SAPI5 voice to \"%s\"" % value)
|
||||||
self.object.Voice = self.available_voices[value]
|
self.object.Voice = self._voices[value]
|
||||||
# For some reason SAPI5 does not reset audio after changing the voice
|
# For some reason SAPI5 does not reset audio after changing the voice
|
||||||
# By setting the audio device after changing voices seems to fix this
|
# By setting the audio device after changing voices seems to fix this
|
||||||
# This was noted from information at:
|
# This was noted from information at:
|
||||||
@ -75,10 +82,10 @@ class SAPI5(Output):
|
|||||||
self.silence()
|
self.silence()
|
||||||
# We need to do the pitch in XML here
|
# We need to do the pitch in XML here
|
||||||
textOutput = "<pitch absmiddle=\"%d\">%s</pitch>" % (round(self._pitch), text.replace("<", "<"))
|
textOutput = "<pitch absmiddle=\"%d\">%s</pitch>" % (round(self._pitch), text.replace("<", "<"))
|
||||||
self.object.Speak(textOutput, 1|8)
|
self.object.Speak(textOutput, SVSFlagsAsync | SVSFIsXML)
|
||||||
|
|
||||||
def silence(self):
|
def silence(self):
|
||||||
self.object.Speak("", 3)
|
self.object.Speak("", SVSFlagsAsync | SVSFPurgeBeforeSpeak)
|
||||||
|
|
||||||
def is_active(self):
|
def is_active(self):
|
||||||
if self.object:
|
if self.object:
|
||||||
|
21
src/accessible_output2/outputs/say.py
Normal file
21
src/accessible_output2/outputs/say.py
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
from __future__ import absolute_import
|
||||||
|
import os
|
||||||
|
from .base import Output
|
||||||
|
|
||||||
|
class AppleSay(Output):
|
||||||
|
"""Speech output supporting the Apple Say subsystem."""
|
||||||
|
name = 'Apple Say'
|
||||||
|
def __init__(self, voice = 'Alex', rate = '300'):
|
||||||
|
self.voice = voice
|
||||||
|
self.rate = rate
|
||||||
|
super(AppleSay, self).__init__()
|
||||||
|
def is_active(self):
|
||||||
|
return not os.system('which say')
|
||||||
|
def speak(self, text, interrupt = 0):
|
||||||
|
if interrupt:
|
||||||
|
self.silence()
|
||||||
|
os.system('say -v %s -r %s "%s" &' % (self.voice, self.rate, text))
|
||||||
|
def silence(self):
|
||||||
|
os.system('killall say')
|
||||||
|
|
||||||
|
output_class = AppleSay
|
@ -1,29 +0,0 @@
|
|||||||
from base import Output, OutputError
|
|
||||||
import atexit
|
|
||||||
import application
|
|
||||||
class SpeechDispatcher(Output):
|
|
||||||
"""Supports speech dispatcher on Linux.
|
|
||||||
Note that this module will use the configuration of speech dispatcher, the user will need to configure the voice, language, punctuation and rate before using this module.
|
|
||||||
"""
|
|
||||||
name = 'SpeechDispatcher'
|
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
super(SpeechDispatcher, self).__init__(*args, **kwargs)
|
|
||||||
try:
|
|
||||||
import speechd
|
|
||||||
self.spd = speechd.SSIPClient(application.name)
|
|
||||||
except ImportError:
|
|
||||||
raise OutputError
|
|
||||||
atexit.register(self.on_exit_event)
|
|
||||||
|
|
||||||
def speak(self, text, interupt=False):
|
|
||||||
if interupt == True:
|
|
||||||
self.spd.cancel()
|
|
||||||
self.spd.speak(text)
|
|
||||||
|
|
||||||
def is_active(self):
|
|
||||||
return True
|
|
||||||
|
|
||||||
def on_exit_event(self):
|
|
||||||
self.spd.close()
|
|
||||||
del self.spd
|
|
@ -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 *
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
@ -1 +0,0 @@
|
|||||||
SPD_SPAWN_CMD = "/usr/bin/speech-dispatcher"
|
|
@ -1,18 +1,24 @@
|
|||||||
from base import Output
|
from __future__ import absolute_import
|
||||||
|
import ctypes
|
||||||
|
from .base import Output
|
||||||
|
|
||||||
class SystemAccess (Output):
|
class SystemAccess (Output):
|
||||||
"""Supports System Access and System Access Mobile"""
|
"""Supports System Access and System Access Mobile"""
|
||||||
|
|
||||||
name = "System Access"
|
name = "System Access"
|
||||||
lib32 = 'saapi32.dll'
|
lib32 = 'saapi32.dll'
|
||||||
|
argtypes = {
|
||||||
|
'SA_BrlShowTextW': (ctypes.c_wchar_p,),
|
||||||
|
'SA_SayW': (ctypes.c_wchar_p,),
|
||||||
|
}
|
||||||
priority = 99
|
priority = 99
|
||||||
|
|
||||||
def braille(self, text, **options):
|
def braille(self, text, **options):
|
||||||
self.lib.SA_BrlShowTextW(unicode(text))
|
self.lib.SA_BrlShowTextW(text)
|
||||||
|
|
||||||
def speak(self, text, interrupt=False):
|
def speak(self, text, interrupt=False):
|
||||||
if self.is_active():
|
if self.is_active():
|
||||||
self.dll.SA_SayW(unicode(text))
|
self.dll.SA_SayW(str(text))
|
||||||
|
|
||||||
def is_active(self):
|
def is_active(self):
|
||||||
try:
|
try:
|
||||||
|
@ -1,23 +1 @@
|
|||||||
from base import Output, OutputError
|
from __future__ import absolute_import
from builtins import str
import subprocess, os
from .base import Output
class VoiceOver(Output):
"""Speech output supporting the Apple VoiceOver screen reader."""
def runAppleScript(self, command, process = 'voiceover'):
return subprocess.Popen(['osascript', '-e', 'tell application "' + process + '"\n' + command + '\nend tell'], stdout = subprocess.PIPE).communicate()[0]
name = 'VoiceOver'
def speak(self, text, interrupt=0):
if interrupt:
self.silence()
os.system('osascript -e \"tell application \\\"voiceover\\\" to output \\\"%s\\\"\" &' % text)
def silence (self):
self.runAppleScript('output ""')
def is_active(self):
return self.runAppleScript('return (name of processes) contains "VoiceOver"', 'system events').startswith('true') and not self.runAppleScript('try\nreturn bounds of vo cursor\non error\nreturn false\nend try').startswith('false')
output_class = VoiceOver
|
||||||
|
|
||||||
class VoiceOver (Output):
|
|
||||||
"""Supports the VoiceOver screenreader on the Mac.
|
|
||||||
|
|
||||||
Note that this will also output as a message to the braille display if VoiceOver is used with braille.
|
|
||||||
Calling this module could cause VoiceOver to be started.
|
|
||||||
"""
|
|
||||||
name = 'VoiceOver'
|
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
super(VoiceOver, self).__init__(*args, **kwargs)
|
|
||||||
try:
|
|
||||||
from appscript import app
|
|
||||||
self.app = app('VoiceOver')
|
|
||||||
except ImportError:
|
|
||||||
raise OutputError
|
|
||||||
|
|
||||||
def speak(self, text, interupt=False):
|
|
||||||
self.app.output(text)
|
|
||||||
|
|
||||||
def is_active(self):
|
|
||||||
return True
|
|
@ -1,6 +1,7 @@
|
|||||||
|
from __future__ import absolute_import
|
||||||
import win32gui
|
import win32gui
|
||||||
from libloader.com import load_com
|
from libloader.com import load_com
|
||||||
from base import Output, OutputError
|
from .base import Output, OutputError
|
||||||
import pywintypes
|
import pywintypes
|
||||||
|
|
||||||
class WindowEyes (Output):
|
class WindowEyes (Output):
|
||||||
|
Loading…
x
Reference in New Issue
Block a user