Replaced libloader and accessible_output2 for modules retrieved in requirements file
This commit is contained in:
parent
26b78eecf6
commit
c655e23cb3
@ -7,3 +7,6 @@ requests-oauthlib
|
|||||||
future
|
future
|
||||||
arrow
|
arrow
|
||||||
yandex.translate
|
yandex.translate
|
||||||
|
# forked repositories previously found at http://q-continuum.net
|
||||||
|
git+https://code.manuelcortez.net/manuelcortez/libloader
|
||||||
|
git+https://code.manuelcortez.net/manuelcortez/accessible_output2
|
@ -1,33 +0,0 @@
|
|||||||
from __future__ import absolute_import
|
|
||||||
import ctypes
|
|
||||||
import os
|
|
||||||
import types
|
|
||||||
from platform_utils import paths
|
|
||||||
|
|
||||||
def load_library(libname, cdll=False):
|
|
||||||
if paths.is_frozen():
|
|
||||||
libfile = os.path.join(paths.embedded_data_path(), 'accessible_output2', 'lib', libname)
|
|
||||||
else:
|
|
||||||
libfile = os.path.join(paths.module_path(), 'lib', libname)
|
|
||||||
if cdll:
|
|
||||||
return ctypes.cdll[libfile]
|
|
||||||
else:
|
|
||||||
return ctypes.windll[libfile]
|
|
||||||
|
|
||||||
def get_output_classes():
|
|
||||||
from . import outputs
|
|
||||||
module_type = types.ModuleType
|
|
||||||
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)
|
|
||||||
|
|
||||||
def find_datafiles():
|
|
||||||
import os
|
|
||||||
import platform
|
|
||||||
from glob import glob
|
|
||||||
import accessible_output2
|
|
||||||
if platform.system() != 'Windows':
|
|
||||||
return []
|
|
||||||
path = os.path.join(accessible_output2.__path__[0], 'lib', '*.dll')
|
|
||||||
results = glob(path)
|
|
||||||
dest_dir = os.path.join('accessible_output2', 'lib')
|
|
||||||
return [(dest_dir, results)]
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1,20 +0,0 @@
|
|||||||
from __future__ import absolute_import
|
|
||||||
import platform
|
|
||||||
if platform.system() == 'Windows':
|
|
||||||
from . import nvda
|
|
||||||
from . import jaws
|
|
||||||
from . import sapi5
|
|
||||||
from . import window_eyes
|
|
||||||
from . import system_access
|
|
||||||
from . import dolphin
|
|
||||||
from . import pc_talker
|
|
||||||
#import sapi4
|
|
||||||
|
|
||||||
if platform.system() == 'Darwin':
|
|
||||||
from . import voiceover
|
|
||||||
from . import say
|
|
||||||
|
|
||||||
if platform.system() == 'Linux':
|
|
||||||
from . import e_speak
|
|
||||||
|
|
||||||
from . import auto
|
|
@ -1,40 +0,0 @@
|
|||||||
from __future__ import absolute_import
|
|
||||||
import accessible_output2
|
|
||||||
from .base import Output, OutputError
|
|
||||||
|
|
||||||
class Auto(Output):
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
output_classes = accessible_output2.get_output_classes()
|
|
||||||
self.outputs = []
|
|
||||||
for output in output_classes:
|
|
||||||
try:
|
|
||||||
self.outputs.append(output())
|
|
||||||
except OutputError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
def get_first_available_output(self):
|
|
||||||
for output in self.outputs:
|
|
||||||
if output.is_active():
|
|
||||||
return output
|
|
||||||
return None
|
|
||||||
|
|
||||||
def speak(self, *args, **kwargs):
|
|
||||||
output = self.get_first_available_output()
|
|
||||||
if output:
|
|
||||||
output.speak(*args, **kwargs)
|
|
||||||
|
|
||||||
def braille(self, *args, **kwargs):
|
|
||||||
output = self.get_first_available_output()
|
|
||||||
if output:
|
|
||||||
output.braille(*args, **kwargs)
|
|
||||||
|
|
||||||
def output(self, *args, **kwargs):
|
|
||||||
output = self.get_first_available_output()
|
|
||||||
if output:
|
|
||||||
output.speak(*args, **kwargs)
|
|
||||||
|
|
||||||
def is_system_output(self):
|
|
||||||
output = self.get_first_available_output()
|
|
||||||
if output:
|
|
||||||
return output.is_system_output()
|
|
@ -1,47 +0,0 @@
|
|||||||
from accessible_output2 import load_library
|
|
||||||
import platform
|
|
||||||
|
|
||||||
class OutputError(Exception):
|
|
||||||
pass
|
|
||||||
|
|
||||||
class Output(object):
|
|
||||||
name = "Unnamed Output"
|
|
||||||
lib32 = None
|
|
||||||
lib64 = None
|
|
||||||
argtypes = {}
|
|
||||||
cdll = False
|
|
||||||
priority = 100
|
|
||||||
system_output = False
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
self.is_32bit = platform.architecture()[0] == "32bit"
|
|
||||||
if self.lib32 and self.is_32bit:
|
|
||||||
self.lib = load_library(self.lib32, cdll=self.cdll)
|
|
||||||
elif 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):
|
|
||||||
output = False
|
|
||||||
if self.speak(text, **options):
|
|
||||||
output = True
|
|
||||||
if self.braille(text, **options):
|
|
||||||
output = True
|
|
||||||
if not output:
|
|
||||||
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, *args, **options):
|
|
||||||
return False
|
|
@ -1,33 +0,0 @@
|
|||||||
from __future__ import absolute_import
|
|
||||||
import os
|
|
||||||
import ctypes
|
|
||||||
|
|
||||||
from .base import Output
|
|
||||||
|
|
||||||
class Dolphin (Output):
|
|
||||||
"""Supports dolphin products."""
|
|
||||||
|
|
||||||
name = 'Dolphin'
|
|
||||||
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):
|
|
||||||
if interrupt:
|
|
||||||
self.silence()
|
|
||||||
#If we don't call this, the API won't let us speak.
|
|
||||||
if self.is_active():
|
|
||||||
self.lib.DolAccess_Command(text, (len(text)*2)+2, 1)
|
|
||||||
|
|
||||||
def silence(self):
|
|
||||||
self.lib.DolAccess_Action(141)
|
|
||||||
|
|
||||||
def is_active(self):
|
|
||||||
try:
|
|
||||||
return self.lib.DolAccess_GetSystem() in (1, 4, 8)
|
|
||||||
except:
|
|
||||||
return False
|
|
||||||
|
|
||||||
output_class = Dolphin
|
|
@ -1,31 +0,0 @@
|
|||||||
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,34 +0,0 @@
|
|||||||
from __future__ import absolute_import
|
|
||||||
import win32gui
|
|
||||||
from libloader.com import load_com
|
|
||||||
import pywintypes
|
|
||||||
|
|
||||||
from .base import Output, OutputError
|
|
||||||
|
|
||||||
class Jaws (Output):
|
|
||||||
"""Output supporting the Jaws for Windows screen reader."""
|
|
||||||
|
|
||||||
name = 'jaws'
|
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
super (Jaws, self).__init__(*args, **kwargs)
|
|
||||||
try:
|
|
||||||
self.object = load_com("FreedomSci.JawsApi", "jfwapi")
|
|
||||||
except pywintypes.com_error:
|
|
||||||
raise OutputError
|
|
||||||
|
|
||||||
def braille(self, text, **options):
|
|
||||||
# HACK: replace " with ', Jaws doesn't seem to understand escaping them with \
|
|
||||||
text = text.replace('"', "'")
|
|
||||||
self.object.RunFunction("BrailleString(\"%s\")" % text)
|
|
||||||
|
|
||||||
def speak(self, text, interrupt=False):
|
|
||||||
self.object.SayString(' %s' % text, interrupt)
|
|
||||||
|
|
||||||
def is_active(self):
|
|
||||||
try:
|
|
||||||
return self.object.SayString('',0) == True or win32gui.FindWindow("JFWUI2", "JAWS") != 0
|
|
||||||
except:
|
|
||||||
return False
|
|
||||||
|
|
||||||
output_class = Jaws
|
|
@ -1,37 +0,0 @@
|
|||||||
from __future__ import absolute_import
|
|
||||||
import os
|
|
||||||
import platform
|
|
||||||
import ctypes
|
|
||||||
|
|
||||||
from platform_utils import paths
|
|
||||||
from libloader import load_library
|
|
||||||
from .base import Output
|
|
||||||
|
|
||||||
class NVDA(Output):
|
|
||||||
"""Supports The NVDA screen reader"""
|
|
||||||
name = "NVDA"
|
|
||||||
lib32 = 'nvdaControllerClient32.dll'
|
|
||||||
lib64 = 'nvdaControllerClient64.dll'
|
|
||||||
argtypes = {
|
|
||||||
'nvdaController_brailleMessage': (ctypes.c_wchar_p,),
|
|
||||||
'nvdaController_speakText': (ctypes.c_wchar_p,),
|
|
||||||
}
|
|
||||||
|
|
||||||
def is_active(self):
|
|
||||||
try:
|
|
||||||
return self.lib.nvdaController_testIfRunning() == 0
|
|
||||||
except:
|
|
||||||
return False
|
|
||||||
|
|
||||||
def braille(self, text, **options):
|
|
||||||
self.lib.nvdaController_brailleMessage(text)
|
|
||||||
|
|
||||||
def speak(self, text, interrupt=False):
|
|
||||||
if interrupt:
|
|
||||||
self.silence()
|
|
||||||
self.lib.nvdaController_speakText(text)
|
|
||||||
|
|
||||||
def silence(self):
|
|
||||||
self.lib.nvdaController_cancelSpeech()
|
|
||||||
|
|
||||||
output_class = NVDA
|
|
@ -1,24 +0,0 @@
|
|||||||
from __future__ import absolute_import
|
|
||||||
import ctypes
|
|
||||||
from .base import Output
|
|
||||||
|
|
||||||
class PCTalker(Output):
|
|
||||||
lib32 = 'pctkusr.dll'
|
|
||||||
lib64 = 'pctkusr64.dll'
|
|
||||||
cdll = True
|
|
||||||
argtypes = {
|
|
||||||
'PCTKPRead': (ctypes.c_char_p, ctypes.c_int, ctypes.c_int)
|
|
||||||
}
|
|
||||||
|
|
||||||
def speak(self, text, interrupt=False):
|
|
||||||
if interrupt:
|
|
||||||
self.silence()
|
|
||||||
self.lib.PCTKPRead(text.encode('cp932', 'replace'), 0, 1)
|
|
||||||
|
|
||||||
def silence(self):
|
|
||||||
self.lib.PCTKVReset()
|
|
||||||
|
|
||||||
def is_active(self):
|
|
||||||
return self.lib.PCTKStatus() != 0
|
|
||||||
|
|
||||||
output_class = PCTalker
|
|
@ -1,143 +0,0 @@
|
|||||||
from __future__ import absolute_import
|
|
||||||
from builtins import range
|
|
||||||
from libloader.com import load_com
|
|
||||||
from .base import Output
|
|
||||||
|
|
||||||
import logging
|
|
||||||
log = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
class Sapi4(Output):
|
|
||||||
|
|
||||||
name = 'sapi4'
|
|
||||||
priority = 102
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
sapi4 = load_com("{EEE78591-FE22-11D0-8BEF-0060081841DE}")
|
|
||||||
self._voiceNo = sapi4.Find(0)
|
|
||||||
sapi4.Select(self._voiceNo)
|
|
||||||
sapi4.Speak(" ")
|
|
||||||
self.__object = sapi4
|
|
||||||
self._voice_list = self._available_voices()
|
|
||||||
|
|
||||||
def _set_capabilities(self):
|
|
||||||
sapi4 = self.__object
|
|
||||||
try:
|
|
||||||
sapi4.Pitch = sapi4.Pitch
|
|
||||||
self._min_pitch = sapi4.MinPitch
|
|
||||||
self._max_pitch = sapi4.MaxPitch
|
|
||||||
self._has_pitch = True
|
|
||||||
except:
|
|
||||||
self._min_pitch = 0
|
|
||||||
self._max_pitch = 0
|
|
||||||
self._has_pitch = False
|
|
||||||
try:
|
|
||||||
sapi4.Speed = sapi4.Speed
|
|
||||||
self._min_rate = sapi4.MinSpeed
|
|
||||||
self._max_rate = sapi4.MaxSpeed
|
|
||||||
self._has_rate = True
|
|
||||||
except:
|
|
||||||
self._min_rate = 0
|
|
||||||
self._max_rate = 0
|
|
||||||
self._has_rate = False
|
|
||||||
try:
|
|
||||||
sapi4.VolumeLeft = sapi4.VolumeLeft
|
|
||||||
self._min_volume = sapi4.MinVolumeLeft
|
|
||||||
self._max_volume = sapi4.MaxVolumeLeft
|
|
||||||
self._has_volume = True
|
|
||||||
except:
|
|
||||||
self._min_volume = 0
|
|
||||||
self._max_volume = 0
|
|
||||||
self._has_volume = False
|
|
||||||
|
|
||||||
def _available_voices(self):
|
|
||||||
voice_list = []
|
|
||||||
for voice_no in range(1, self.__object.CountEngines):
|
|
||||||
voice_list.append(self.__object.ModeName(voice_no))
|
|
||||||
return voice_list
|
|
||||||
|
|
||||||
@property
|
|
||||||
def available_voices(self):
|
|
||||||
return self._voice_list
|
|
||||||
|
|
||||||
def list_voices(self):
|
|
||||||
return self.available_voices
|
|
||||||
|
|
||||||
def get_voice(self):
|
|
||||||
return self.__object.ModeName(self._voice_no)
|
|
||||||
|
|
||||||
def set_voice(self, value):
|
|
||||||
self._voice_no = self.list_voices().index(value) + 1
|
|
||||||
self.__object.Select(self._voice_no)
|
|
||||||
self.silence()
|
|
||||||
self.__object.Speak(" ")
|
|
||||||
self._set_capabilities()
|
|
||||||
|
|
||||||
def get_pitch(self):
|
|
||||||
if self.has_pitch:
|
|
||||||
return self.__object.Pitch
|
|
||||||
|
|
||||||
def set_pitch(self, value):
|
|
||||||
if self.has_pitch:
|
|
||||||
self.__object.Pitch = value
|
|
||||||
|
|
||||||
def get_rate(self):
|
|
||||||
if self.has_rate:
|
|
||||||
return self.__object.Speed
|
|
||||||
|
|
||||||
def set_rate(self, value):
|
|
||||||
if self.has_rate:
|
|
||||||
self.__object.Speed = value
|
|
||||||
|
|
||||||
def get_volume(self):
|
|
||||||
if self.has_volume:
|
|
||||||
return self.__object.VolumeLeft
|
|
||||||
|
|
||||||
def set_volume(self, value):
|
|
||||||
if self.has_volume:
|
|
||||||
self.__object.VolumeLeft = value
|
|
||||||
|
|
||||||
@property
|
|
||||||
def has_pitch(self):
|
|
||||||
return self._has_pitch
|
|
||||||
|
|
||||||
@property
|
|
||||||
def has_rate(self):
|
|
||||||
return self._has_rate
|
|
||||||
|
|
||||||
@property
|
|
||||||
def has_volume(self):
|
|
||||||
return self._has_volume
|
|
||||||
|
|
||||||
@property
|
|
||||||
def min_pitch(self):
|
|
||||||
return self._min_pitch
|
|
||||||
|
|
||||||
@property
|
|
||||||
def max_pitch(self):
|
|
||||||
return self._max_pitch
|
|
||||||
|
|
||||||
@property
|
|
||||||
def min_rate(self):
|
|
||||||
return self._min_rate
|
|
||||||
|
|
||||||
@property
|
|
||||||
def max_rate(self):
|
|
||||||
return self._max_rate
|
|
||||||
|
|
||||||
@property
|
|
||||||
def min_volume(self):
|
|
||||||
return self._min_volume
|
|
||||||
|
|
||||||
@property
|
|
||||||
def max_volume(self):
|
|
||||||
return self._max_volume
|
|
||||||
|
|
||||||
def speak(self, text, interrupt=False):
|
|
||||||
if interrupt:
|
|
||||||
self.silence()
|
|
||||||
self.__object.Speak(text)
|
|
||||||
|
|
||||||
def silence(self):
|
|
||||||
self.__object.AudioReset()
|
|
||||||
|
|
||||||
output_class = Sapi4
|
|
@ -1,95 +0,0 @@
|
|||||||
from __future__ import absolute_import
|
|
||||||
from collections import OrderedDict
|
|
||||||
from libloader.com import load_com
|
|
||||||
from .base import Output, OutputError
|
|
||||||
import pywintypes
|
|
||||||
import logging
|
|
||||||
log = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
SVSFDefault = 0
|
|
||||||
SVSFlagsAsync = 1
|
|
||||||
SVSFPurgeBeforeSpeak = 2
|
|
||||||
SVSFIsFilename = 4
|
|
||||||
SVSFIsXML = 8
|
|
||||||
SVSFIsNotXML = 16
|
|
||||||
SVSFPersistXML = 32
|
|
||||||
|
|
||||||
class SAPI5(Output):
|
|
||||||
has_volume = True
|
|
||||||
has_rate = True
|
|
||||||
has_pitch = True
|
|
||||||
min_pitch = -10
|
|
||||||
max_pitch = 10
|
|
||||||
min_rate = -10
|
|
||||||
max_rate = 10
|
|
||||||
min_volume = 0
|
|
||||||
max_volume = 100
|
|
||||||
name = "sapi5"
|
|
||||||
priority = 101
|
|
||||||
system_output = True
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
try:
|
|
||||||
self.object = load_com("SAPI.SPVoice")
|
|
||||||
self._voices = self._available_voices()
|
|
||||||
except pywintypes.com_error:
|
|
||||||
raise OutputError
|
|
||||||
self._pitch = 0
|
|
||||||
|
|
||||||
def _available_voices(self):
|
|
||||||
_voices = OrderedDict()
|
|
||||||
for v in self.object.GetVoices():
|
|
||||||
_voices[v.GetDescription()] = v
|
|
||||||
return _voices
|
|
||||||
|
|
||||||
def list_voices(self):
|
|
||||||
return list(self._voices.keys())
|
|
||||||
|
|
||||||
def get_voice(self):
|
|
||||||
return self.object.Voice.GetDescription()
|
|
||||||
|
|
||||||
def set_voice(self, value):
|
|
||||||
log.debug("Setting SAPI5 voice to \"%s\"" % value)
|
|
||||||
self.object.Voice = self._voices[value]
|
|
||||||
# For some reason SAPI5 does not reset audio after changing the voice
|
|
||||||
# By setting the audio device after changing voices seems to fix this
|
|
||||||
# This was noted from information at:
|
|
||||||
# http://lists.nvaccess.org/pipermail/nvda-dev/2011-November/022464.html
|
|
||||||
self.object.AudioOutput = self.object.AudioOutput
|
|
||||||
|
|
||||||
def get_pitch(self):
|
|
||||||
return self._pitch
|
|
||||||
|
|
||||||
def set_pitch(self, value):
|
|
||||||
log.debug("Setting pitch to %d" % value)
|
|
||||||
self._pitch = value
|
|
||||||
|
|
||||||
def get_rate(self):
|
|
||||||
return self.object.Rate
|
|
||||||
|
|
||||||
def set_rate(self, value):
|
|
||||||
log.debug("Setting rate to %d" % value)
|
|
||||||
self.object.Rate = value
|
|
||||||
|
|
||||||
def get_volume(self):
|
|
||||||
return self.object.Volume
|
|
||||||
|
|
||||||
def set_volume(self, value):
|
|
||||||
self.object.Volume = value
|
|
||||||
|
|
||||||
def speak(self, text, interrupt=False):
|
|
||||||
if interrupt:
|
|
||||||
self.silence()
|
|
||||||
# We need to do the pitch in XML here
|
|
||||||
textOutput = "<pitch absmiddle=\"%d\">%s</pitch>" % (round(self._pitch), text.replace("<", "<"))
|
|
||||||
self.object.Speak(textOutput, SVSFlagsAsync | SVSFIsXML)
|
|
||||||
|
|
||||||
def silence(self):
|
|
||||||
self.object.Speak("", SVSFlagsAsync | SVSFPurgeBeforeSpeak)
|
|
||||||
|
|
||||||
def is_active(self):
|
|
||||||
if self.object:
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
output_class = SAPI5
|
|
@ -1,21 +0,0 @@
|
|||||||
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 __future__ import absolute_import
|
|
||||||
import ctypes
|
|
||||||
from .base import Output
|
|
||||||
|
|
||||||
class SystemAccess (Output):
|
|
||||||
"""Supports System Access and System Access Mobile"""
|
|
||||||
|
|
||||||
name = "System Access"
|
|
||||||
lib32 = 'saapi32.dll'
|
|
||||||
argtypes = {
|
|
||||||
'SA_BrlShowTextW': (ctypes.c_wchar_p,),
|
|
||||||
'SA_SayW': (ctypes.c_wchar_p,),
|
|
||||||
}
|
|
||||||
priority = 99
|
|
||||||
|
|
||||||
def braille(self, text, **options):
|
|
||||||
self.lib.SA_BrlShowTextW(text)
|
|
||||||
|
|
||||||
def speak(self, text, interrupt=False):
|
|
||||||
if self.is_active():
|
|
||||||
self.dll.SA_SayW(str(text))
|
|
||||||
|
|
||||||
def is_active(self):
|
|
||||||
try:
|
|
||||||
return self.dll.SA_IsRunning()
|
|
||||||
except:
|
|
||||||
return False
|
|
||||||
|
|
||||||
output_class = SystemAccess
|
|
@ -1 +0,0 @@
|
|||||||
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
|
|
@ -1,33 +0,0 @@
|
|||||||
from __future__ import absolute_import
|
|
||||||
import win32gui
|
|
||||||
from libloader.com import load_com
|
|
||||||
from .base import Output, OutputError
|
|
||||||
import pywintypes
|
|
||||||
|
|
||||||
class WindowEyes (Output):
|
|
||||||
"""Speech output supporting the WindowEyes screen reader"""
|
|
||||||
|
|
||||||
name = 'Window-Eyes'
|
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
super(WindowEyes, self).__init__(*args, **kwargs)
|
|
||||||
try:
|
|
||||||
self.object = load_com("gwspeak.speak")
|
|
||||||
except pywintypes.com_error:
|
|
||||||
raise OutputError
|
|
||||||
|
|
||||||
def speak(self, text, interrupt=0):
|
|
||||||
if interrupt:
|
|
||||||
self.silence()
|
|
||||||
self.object.SpeakString(text)
|
|
||||||
|
|
||||||
def silence (self):
|
|
||||||
self.object.Silence()
|
|
||||||
|
|
||||||
def is_active(self):
|
|
||||||
try:
|
|
||||||
return win32gui.FindWindow("GWMExternalControl", "External Control") != 0
|
|
||||||
except:
|
|
||||||
return False
|
|
||||||
|
|
||||||
output_class = WindowEyes
|
|
@ -1,10 +1,13 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
import sys
|
import sys
|
||||||
import fix_requests
|
from . import fix_requests
|
||||||
|
|
||||||
if hasattr(sys, "frozen"):
|
if hasattr(sys, "frozen"):
|
||||||
import fix_win32com
|
from . import fix_win32com
|
||||||
|
from . import fix_libloader
|
||||||
|
|
||||||
def setup():
|
def setup():
|
||||||
fix_requests.fix()
|
fix_requests.fix()
|
||||||
if hasattr(sys, "frozen"):
|
if hasattr(sys, "frozen"):
|
||||||
fix_win32com.fix()
|
fix_win32com.fix()
|
||||||
|
fix_libloader.fix()
|
36
src/fixes/fix_libloader.py
Normal file
36
src/fixes/fix_libloader.py
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
import win32com
|
||||||
|
import paths
|
||||||
|
win32com.__gen_path__=paths.com_path()
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
sys.path.append(os.path.join(win32com.__gen_path__, "."))
|
||||||
|
from win32com.client import gencache
|
||||||
|
from pywintypes import com_error
|
||||||
|
from libloader import com
|
||||||
|
|
||||||
|
fixed=False
|
||||||
|
|
||||||
|
def patched_getmodule(modname):
|
||||||
|
mod=__import__(modname)
|
||||||
|
return sys.modules[modname]
|
||||||
|
|
||||||
|
def load_com(*names):
|
||||||
|
global fixed
|
||||||
|
if fixed==False:
|
||||||
|
gencache._GetModule=patched_getmodule
|
||||||
|
com.prepare_gencache()
|
||||||
|
fixed=True
|
||||||
|
result = None
|
||||||
|
for name in names:
|
||||||
|
try:
|
||||||
|
result = gencache.EnsureDispatch(name)
|
||||||
|
break
|
||||||
|
except com_error:
|
||||||
|
continue
|
||||||
|
if result is None:
|
||||||
|
raise com_error("Unable to load any of the provided com objects.")
|
||||||
|
return result
|
||||||
|
|
||||||
|
def fix():
|
||||||
|
com.load_com = load_com
|
@ -1,7 +0,0 @@
|
|||||||
from .libloader import *
|
|
||||||
|
|
||||||
__version__ = 0.1
|
|
||||||
__author__ = 'Christopher Toth <q@q-continuum.net>'
|
|
||||||
__doc__ = """
|
|
||||||
Quickly and easily load shared libraries from various platforms. Also includes a libloader.com module for loading com modules on Windows.
|
|
||||||
"""
|
|
@ -1,40 +0,0 @@
|
|||||||
from pywintypes import com_error
|
|
||||||
import win32com
|
|
||||||
import paths
|
|
||||||
win32com.__gen_path__=paths.com_path()
|
|
||||||
import sys
|
|
||||||
import os
|
|
||||||
sys.path.append(os.path.join(win32com.__gen_path__, "."))
|
|
||||||
from win32com.client import gencache
|
|
||||||
fixed=False
|
|
||||||
|
|
||||||
def prepare_gencache():
|
|
||||||
gencache.is_readonly = False
|
|
||||||
gencache.GetGeneratePath()
|
|
||||||
|
|
||||||
def patched_getmodule(modname):
|
|
||||||
mod=__import__(modname)
|
|
||||||
return sys.modules[modname]
|
|
||||||
|
|
||||||
def load_com(*names):
|
|
||||||
global fixed
|
|
||||||
if fixed==False:
|
|
||||||
gencache._GetModule=patched_getmodule
|
|
||||||
fixed=True
|
|
||||||
result = None
|
|
||||||
for name in names:
|
|
||||||
try:
|
|
||||||
result = gencache.EnsureDispatch(name)
|
|
||||||
break
|
|
||||||
except com_error:
|
|
||||||
continue
|
|
||||||
if result is None:
|
|
||||||
raise com_error("Unable to load any of the provided com objects.")
|
|
||||||
return result
|
|
||||||
|
|
||||||
|
|
||||||
def preexec():
|
|
||||||
global fixed
|
|
||||||
if fixed==False:
|
|
||||||
gencache._GetModule=patched_getmodule
|
|
||||||
fixed=True
|
|
@ -1,56 +0,0 @@
|
|||||||
import ctypes
|
|
||||||
import collections
|
|
||||||
import platform
|
|
||||||
import os
|
|
||||||
|
|
||||||
TYPES = {
|
|
||||||
'Linux': {
|
|
||||||
'loader': ctypes.CDLL,
|
|
||||||
'functype': ctypes.CFUNCTYPE,
|
|
||||||
'prefix': 'lib',
|
|
||||||
'extension': '.so'
|
|
||||||
},
|
|
||||||
'Darwin': {
|
|
||||||
'loader': ctypes.CDLL,
|
|
||||||
'functype': ctypes.CFUNCTYPE,
|
|
||||||
'prefix': 'lib',
|
|
||||||
'extension': '.dylib'
|
|
||||||
},
|
|
||||||
}
|
|
||||||
if platform.system() == 'Windows':
|
|
||||||
TYPES['Windows'] = {
|
|
||||||
'loader': ctypes.WinDLL,
|
|
||||||
'functype': ctypes.WINFUNCTYPE,
|
|
||||||
'prefix': "",
|
|
||||||
'extension': '.dll'
|
|
||||||
}
|
|
||||||
|
|
||||||
class LibraryLoadError(OSError): pass
|
|
||||||
|
|
||||||
def load_library(library, x86_path='.', x64_path='.', *args, **kwargs):
|
|
||||||
lib = find_library_path(library, x86_path=x86_path, x64_path=x64_path)
|
|
||||||
loaded = _do_load(lib, *args, **kwargs)
|
|
||||||
if loaded is not None:
|
|
||||||
return loaded
|
|
||||||
raise LibraryLoadError('unable to load %r. Provided library path: %r' % (library, lib))
|
|
||||||
|
|
||||||
def _do_load(file, *args, **kwargs):
|
|
||||||
loader = TYPES[platform.system()]['loader']
|
|
||||||
return loader(file, *args, **kwargs)
|
|
||||||
|
|
||||||
def find_library_path(libname, x86_path='.', x64_path='.'):
|
|
||||||
libname = '%s%s' % (TYPES[platform.system()]['prefix'], libname)
|
|
||||||
if platform.architecture()[0] == '64bit':
|
|
||||||
path = os.path.join(x64_path, libname)
|
|
||||||
else:
|
|
||||||
path = os.path.join(x86_path, libname)
|
|
||||||
ext = get_library_extension()
|
|
||||||
path = '%s%s' % (path, ext)
|
|
||||||
return os.path.abspath(path)
|
|
||||||
|
|
||||||
|
|
||||||
def get_functype():
|
|
||||||
return TYPES[platform.system()]['functype']
|
|
||||||
|
|
||||||
def get_library_extension():
|
|
||||||
return TYPES[platform.system()]['extension']
|
|
Loading…
Reference in New Issue
Block a user