Putting all the code from the current master branch of TWBlue

This commit is contained in:
2014-10-27 16:29:04 -06:00
parent 58c82e5486
commit 1af4a8b291
284 changed files with 58760 additions and 0 deletions

View File

@@ -0,0 +1,29 @@
import ctypes
import os
import types
from platform_utils import paths
def load_library(libname):
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)
return ctypes.windll[libfile]
def get_output_classes():
import outputs
module_type = types.ModuleType
classes = [m.output_class for m in outputs.__dict__.itervalues() 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.

Binary file not shown.

View File

@@ -0,0 +1,16 @@
import platform
if platform.system() == 'Windows':
import nvda
import jaws
import sapi5
import window_eyes
import system_access
import dolphin
import pc_talker
#import sapi4
elif platform.system() == "Darwin":
import voiceover
elif platform.system() == "Linux":
import speechDispatcher
import auto

View File

@@ -0,0 +1,42 @@
import platform
import accessible_output2
from base import Output, OutputError
class Auto(Output):
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()
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)

View File

@@ -0,0 +1,31 @@
from accessible_output2 import load_library
import platform
class OutputError(Exception):
pass
class Output(object):
name = "Unnamed Output" #The name of this output
lib32 = None #name of 32-bit lib
lib64 = None #name of 64-bit lib
priority = 100 #Where to sort in the list of available outputs for automaticly speaking
def __init__(self):
is_32bit = platform.architecture()[0] == "32bit"
if self.lib32 and is_32bit:
self.lib = load_library(self.lib32)
elif self.lib64:
self.lib = load_library(self.lib64)
def output(self, text, **options):
output = False
if hasattr(self, 'speak') and callable(self.speak):
self.speak(text, **options)
output = True
if hasattr(self, 'braille') and callable(self.braille):
self.braille(text, **options)
output = True
if not output:
raise RuntimeError("Output %r does not have any method defined to output" % self)

View File

@@ -0,0 +1,27 @@
import os
from base import Output
class Dolphin (Output):
"""Supports dolphin products."""
name = 'Dolphin'
lib32 = 'dolapi.dll'
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(unicode(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

View File

@@ -0,0 +1,33 @@
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

View File

@@ -0,0 +1,31 @@
import os
import platform
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'
def is_active(self):
try:
return self.lib.nvdaController_testIfRunning() == 0
except:
return False
def braille(self, text, **options):
self.lib.nvdaController_brailleMessage(unicode(text))
def speak(self, text, interrupt=False):
if interrupt:
self.silence()
self.lib.nvdaController_speakText(unicode(text))
def silence(self):
self.lib.nvdaController_cancelSpeech()
output_class = NVDA

View File

@@ -0,0 +1,19 @@
import ctypes
from base import Output
class PCTalker(Output):
lib32 = 'pctkusr.dll'
lib64 = 'pctkusr64.dll'
def speak(self, text, interrupt=False):
if interrupt:
self.silence()
self.lib.PCTKPRead(text.encode('cp932', 'replace'))
def silence(self):
self.lib.PCTKVReset()
def is_active(self):
return self.lib.PCTKStatus() != 0
output_class = PCTalker

View File

@@ -0,0 +1,141 @@
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

View File

@@ -0,0 +1,88 @@
# -*- coding: utf-8 -*-
import config
from collections import OrderedDict
from libloader.com import load_com
from base import Output, OutputError
import pywintypes
import logging
log = logging.getLogger(__name__)
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
def __init__(self):
if config.main["general"]["voice_enabled"] == False: raise OutputError
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 self.available_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.available_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("<", "&lt;"))
self.object.Speak(textOutput, 1|8)
def silence(self):
self.object.Speak("", 3)
def is_active(self):
if self.object:
return True
return False
output_class = SAPI5

View File

@@ -0,0 +1,29 @@
from base import Output, OutputError
import atexit
class SpeechDispatcher(Output):
"""Supports speech dispatcher on Linux.
Note that it will take the configuration from the speech dispatcher, the user will need configure voice, language, punctuation and rate before use this module.
"""
name = 'SpeechDispatcher'
def __init__(self, *args, **kwargs):
super(SpeechDispatcher, self).__init__(*args, **kwargs)
try:
import speechd
self.spd = speechd.SSIPClient("TWBlue")
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

View File

@@ -0,0 +1,18 @@
# Copyright (C) 2001, 2002 Brailcom, o.p.s.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
from .client import *

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1 @@
SPD_SPAWN_CMD = "/usr/bin/speech-dispatcher"

View File

@@ -0,0 +1,23 @@
from base import Output
class SystemAccess (Output):
"""Supports System Access and System Access Mobile"""
name = "System Access"
lib32 = 'saapi32.dll'
priority = 99
def braille(self, text, **options):
self.lib.SA_BrlShowTextW(unicode(text))
def speak(self, text, interrupt=False):
if self.is_active():
self.dll.SA_SayW(unicode(text))
def is_active(self):
try:
return self.dll.SA_IsRunning()
except:
return False
output_class = SystemAccess

View File

@@ -0,0 +1,23 @@
from base import Output, OutputError
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

View File

@@ -0,0 +1,32 @@
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