# -*- coding: utf-8 -*- # NVDA imports import api import globalPluginHandler import logHandler import speech import textInfos import ui import controlTypes # python imports import select import socket import threading import time class Cli2Srvnt(threading.Thread): def __init__(self, host, port, timeout=1): threading.Thread.__init__(self) self.__connected = False self.__sock = None self.__host = host self.__port = port self.__timeout = timeout self.__addr = (self.__host, self.__port) def __create(self): self.__sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.__sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) def run(self): exceptional = [] readable = [] writable = [] self.__create() while True: try: if (readable == [] and writable == [] and exceptional == []): if (self.__sock.connect_ex((self.__host, self.__port)) == 0): # ui.message("VLibras Plugin CONECTADO") self.__connected = True try: readable, writable, exceptional = select.select( [self.__sock], [self.__sock], [], self.__timeout ) except: pass if (readable != []): self.__connected = False try: self.__sock.shutdown(1) self.__sock.close() self.__create() except: pass elif (writable != []): self.__connected = True except: pass time.sleep(1) def send(self, msg): try: if (self.__connected and self.__sock is not None): return self.__sock.sendto( msg.encode("utf-8", "ignore"), self.__addr ) except Exception as e: logHandler.log.error(u"%s\n%s" % (e.message, e.args)) return False class GlobalPlugin(globalPluginHandler.GlobalPlugin): __captureMouse = False __silentMode = False # keyboard shortcuts __kbToggleSilentMode = "NVDA+shift+v" __kbToggleCaptureMouseMode = "NVDA+shift+m" # keyboard gestures __gestures = { "kb:" + __kbToggleSilentMode: "toggleSilentMode", "kb:" + __kbToggleCaptureMouseMode: "toggleCaptureMouseMode" } # message to speak on enable or disable def toggleMessage(self, msg, enabled, kb): message = "VLibras Plugin: %s %s. Para %s use %s" if (enabled): message = message % (msg, "ativado", "desativar", kb) else: message = message % (msg, "desativado", "ativar", kb) return ui.message(message) # toggle silent mode by user (default is False) def script_toggleSilentMode(self, obj): self.__silentMode = not self.__silentMode return self.toggleMessage( "Modo silencioso", self.__silentMode, self.__kbToggleSilentMode ) # toggle capture mouse mode by user (default is False) def script_toggleCaptureMouseMode(self, obj): self.__captureMouse = not self.__captureMouse return self.toggleMessage( "Modo captura de mouse", self.__captureMouse, self.__kbToggleCaptureMouseMode ) # constructor def __init__(self): super(self.__class__, self).__init__() self.__lastTextSend = "" self.__mutex = threading.Lock() self.__client = Cli2Srvnt("127.0.0.1", 10001) self.__client.start() # destructor def __exit__(self, exc_type, exc_value, traceback): self.__client.join() # cancel speech if silent mode is true def handleSpeech(self, obj, nextHandler): try: if (self.__silentMode): return speech.cancelSpeech() except Exception as e: logHandler.log.error(u"%s\n%s" % (e.message, e.args)) return nextHandler() # get the current text in focus and send to vlibras def processFocus(self, obj, nextHandler): try: if (obj.role == controlTypes.ROLE_UNKNOWN): return self.handleSpeech(obj, nextHandler) info = api.getReviewPosition() if (info is None): return self.handleSpeech(obj, nextHandler) info.expand(textInfos.UNIT_READINGCHUNK) textToSend = info._get_text() if textToSend is None: return self.handleSpeech(obj, nextHandler) textToSend = textToSend.strip(" \t\r\n") # mutex to protect self.__lastTextSend self.__mutex.acquire() try: if (textToSend and textToSend != self.__lastTextSend): self.__lastTextSend = textToSend if (self.__client.send(textToSend)): logHandler.log.debugWarning(">> %s\n" % (textToSend)) finally: self.__mutex.release() except Exception as e: logHandler.log.error(u"%s\n%s" % (e.message, e.args)) return self.handleSpeech(obj, nextHandler) # get the current text in mouse focus and send to vlibras def processMouse(self, obj, nextHandler, x, y): try: if (not self.__captureMouse): return self.handleSpeech(obj, nextHandler) if (obj.role == controlTypes.ROLE_UNKNOWN): return self.handleSpeech(obj, nextHandler) info = api.getReviewPosition() if (info is None): return self.handleSpeech(obj, nextHandler) info.expand(info.unit_mouseChunk) textToSend = info._get_text() if textToSend is None: return self.handleSpeech(obj, nextHandler) textToSend = textToSend.strip(" \t\r\n") # mutex to protect self.__lastTextSend self.__mutex.acquire() try: if (textToSend and textToSend != self.__lastTextSend): self.__lastTextSend = textToSend if (self.__client.send(textToSend)): logHandler.log.debugWarning(">> %s\n" % (textToSend)) finally: self.__mutex.release() except Exception as e: logHandler.log.error(u"%s\n%s" % (e.message, e.args)) return self.handleSpeech(obj, nextHandler) # Override def event_typedCharacter(self, obj, nextHandler, ch): return self.handleSpeech(obj, nextHandler) # Override -> processMouse def event_mouseMove(self, obj, nextHandler, x, y): return self.processMouse(obj, nextHandler, x, y) # Override def event_stateChange(self, obj, nextHandler): return self.handleSpeech(obj, nextHandler) # Override def event_focusEntered(self, obj, nextHandler): return self.handleSpeech(obj, nextHandler) # Override -> processFocus def event_gainFocus(self, obj, nextHandler): return self.processFocus(obj, nextHandler) # Override def event_foreground(self, obj, nextHandler): return self.handleSpeech(obj, nextHandler) # Override def event_becomeNavigatorObject(self, obj, nextHandler): return self.handleSpeech(obj, nextHandler) # Override def event_valueChange(self, obj, nextHandler): return self.handleSpeech(obj, nextHandler) # Override def event_nameChange(self, obj, nextHandler): return self.handleSpeech(obj, nextHandler) # Override def event_descriptionChange(self, obj, nextHandler): return self.handleSpeech(obj, nextHandler) # Override def event_caret(self, obj, nextHandler): return self.handleSpeech(obj, nextHandler) # Override def event_loseFocus(self, obj, nextHandler): return self.handleSpeech(obj, nextHandler) # Override def event_locationChange(self, obj, nextHandler): return self.handleSpeech(obj, nextHandler)