Commit bef43435fa3d88ea2e9c7d7669667a186a292e8b

Authored by André Araújo
1 parent fa93d856
Exists in plugin

Primeira versão do plugin

vlibras.nvda-addon/.gitignore 0 → 100644
... ... @@ -0,0 +1,12 @@
  1 +.*
  2 +!*.gitignore
  3 +*~
  4 +*.autosave
  5 +*.gz
  6 +*.log
  7 +*.nvda-addon
  8 +*.pyc
  9 +*.swp
  10 +*.txt
  11 +*.zip
  12 +build/
... ...
vlibras.nvda-addon/bin/7z.dll 0 → 100644
No preview for this file type
vlibras.nvda-addon/bin/7z.exe 0 → 100644
No preview for this file type
vlibras.nvda-addon/doc/pt_BR/readme.html 0 → 100644
... ... @@ -0,0 +1,23 @@
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
  3 +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="pt-BR" lang="pt-BR">
  4 + <head>
  5 + <meta http-equiv="Content-Type" content="text/html" charset="UTF-8"/>
  6 + <link rel="stylesheet" type="text/css" href="../style.css" media="screen"/>
  7 + <title></title>
  8 + </head>
  9 + <body>
  10 + <h1>VLibras Pugin para NVDA</h1>
  11 + <ul>
  12 + <li>Autor: Laboratório de Aplicações de Vídeo Digital <a href="http://lavid.ufpb.br">Lavid</a></li>
  13 + <li>Baixe a <a href="http://www.vlibras.gov.br/">versão estável</a></li>
  14 + </ul>
  15 + <p>
  16 + Este plug-in redireciona o texto de saída do NVDA para a aplicação VLibras Player.
  17 + </p>
  18 + <h2>Versão 1.0</h2>
  19 + <ol>
  20 + <li>Primeira versão pública</li>
  21 + </ol>
  22 + </body>
  23 +</html>
... ...
vlibras.nvda-addon/doc/pt_BR/readme.md 0 → 100644
... ... @@ -0,0 +1,12 @@
  1 +# VLibras #
  2 +
  3 +* Autor: Lavid
  4 +* Baixe a [versão estável][1]
  5 +
  6 +Este plug-in redireciona o texto de saída do NVDA para a aplicação VLibras Player.
  7 +
  8 +## Versão 1.0 ##
  9 +
  10 +* Primeira versão pública
  11 +
  12 +[1]: http://www.vlibras.gov.br/
... ...
vlibras.nvda-addon/doc/style.css 0 → 100644
... ... @@ -0,0 +1,46 @@
  1 +@charset "utf-8";
  2 +body {
  3 + font-family : Verdana, Arial, Helvetica, Sans-serif;
  4 + color : #FFFFFF;
  5 + background-color : #000000;
  6 + line-height: 1.2em;
  7 +}
  8 +
  9 +h1, h2 {
  10 + text-align: center
  11 +}
  12 +
  13 +dt {
  14 + font-weight : bold;
  15 + float : left;
  16 + width: 10%;
  17 + clear: left
  18 +}
  19 +
  20 +dd {
  21 + margin : 0 0 0.4em 0;
  22 + float : left;
  23 + width: 90%;
  24 + display: block;
  25 +}
  26 +
  27 +p {
  28 + clear : both;
  29 +}
  30 +
  31 +a {
  32 + text-decoration : underline;
  33 +}
  34 +
  35 +:active {
  36 + text-decoration : none;
  37 +}
  38 +
  39 +a:focus, a:hover {
  40 + outline: solid
  41 +}
  42 +
  43 +:link {
  44 + color: #0000FF;
  45 + background-color: #FFFFFF
  46 +}
... ...
vlibras.nvda-addon/globalPlugins/vlibras.py 0 → 100644
... ... @@ -0,0 +1,244 @@
  1 +# -*- coding: utf-8 -*-
  2 +
  3 +# NVDA imports
  4 +import api
  5 +import globalPluginHandler
  6 +import logHandler
  7 +import speech
  8 +import textInfos
  9 +import ui
  10 +import controlTypes
  11 +
  12 +# python imports
  13 +import select
  14 +import socket
  15 +import threading
  16 +import time
  17 +
  18 +
  19 +class Cli2Srvnt(threading.Thread):
  20 +
  21 + def __init__(self, host, port, timeout=1):
  22 + threading.Thread.__init__(self)
  23 + self.__connected = False
  24 + self.__sock = None
  25 + self.__host = host
  26 + self.__port = port
  27 + self.__timeout = timeout
  28 + self.__addr = (self.__host, self.__port)
  29 +
  30 + def __create(self):
  31 + self.__sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  32 + self.__sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
  33 +
  34 + def run(self):
  35 + exceptional = []
  36 + readable = []
  37 + writable = []
  38 + self.__create()
  39 + while True:
  40 + try:
  41 + if (readable == [] and writable == [] and exceptional == []):
  42 + if (self.__sock.connect_ex((self.__host, self.__port)) == 0):
  43 + # ui.message("VLibras Plugin CONECTADO")
  44 + self.__connected = True
  45 + try:
  46 + readable, writable, exceptional = select.select(
  47 + [self.__sock], [self.__sock], [], self.__timeout
  48 + )
  49 + except:
  50 + pass
  51 + if (readable != []):
  52 + self.__connected = False
  53 + try:
  54 + self.__sock.shutdown(1)
  55 + self.__sock.close()
  56 + self.__create()
  57 + except:
  58 + pass
  59 + elif (writable != []):
  60 + self.__connected = True
  61 + except:
  62 + pass
  63 + time.sleep(1)
  64 +
  65 + def send(self, msg):
  66 + try:
  67 + if (self.__connected and self.__sock is not None):
  68 + return self.__sock.sendto(
  69 + msg.encode("utf-8", "ignore"),
  70 + self.__addr
  71 + )
  72 + except Exception as e:
  73 + logHandler.log.error(u"%s\n%s" % (e.message, e.args))
  74 + return False
  75 +
  76 +
  77 +class GlobalPlugin(globalPluginHandler.GlobalPlugin):
  78 +
  79 + __captureMouse = False
  80 + __silentMode = False
  81 +
  82 + # keyboard shortcuts
  83 + __kbToggleSilentMode = "NVDA+shift+v"
  84 + __kbToggleCaptureMouseMode = "NVDA+shift+m"
  85 +
  86 + # keyboard gestures
  87 + __gestures = {
  88 + "kb:" + __kbToggleSilentMode: "toggleSilentMode",
  89 + "kb:" + __kbToggleCaptureMouseMode: "toggleCaptureMouseMode"
  90 + }
  91 +
  92 + # message to speak on enable or disable
  93 + def toggleMessage(self, msg, enabled, kb):
  94 + message = "VLibras Plugin: %s %s. Para %s use %s"
  95 + if (enabled):
  96 + message = message % (msg, "ativado", "desativar", kb)
  97 + else:
  98 + message = message % (msg, "desativado", "ativar", kb)
  99 + return ui.message(message)
  100 +
  101 + # toggle silent mode by user (default is False)
  102 + def script_toggleSilentMode(self, obj):
  103 + self.__silentMode = not self.__silentMode
  104 + return self.toggleMessage(
  105 + "Modo silencioso",
  106 + self.__silentMode,
  107 + self.__kbToggleSilentMode
  108 + )
  109 +
  110 + # toggle capture mouse mode by user (default is False)
  111 + def script_toggleCaptureMouseMode(self, obj):
  112 + self.__captureMouse = not self.__captureMouse
  113 + return self.toggleMessage(
  114 + "Modo captura de mouse",
  115 + self.__captureMouse,
  116 + self.__kbToggleCaptureMouseMode
  117 + )
  118 +
  119 + # constructor
  120 + def __init__(self):
  121 + super(self.__class__, self).__init__()
  122 + self.__lastTextSend = ""
  123 + self.__mutex = threading.Lock()
  124 + self.__client = Cli2Srvnt("127.0.0.1", 10001)
  125 + self.__client.start()
  126 +
  127 + # destructor
  128 + def __exit__(self, exc_type, exc_value, traceback):
  129 + self.__client.join()
  130 +
  131 + # cancel speech if silent mode is true
  132 + def handleSpeech(self, obj, nextHandler):
  133 + try:
  134 + if (self.__silentMode):
  135 + return speech.cancelSpeech()
  136 + except Exception as e:
  137 + logHandler.log.error(u"%s\n%s" % (e.message, e.args))
  138 + return nextHandler()
  139 +
  140 + # get the current text in focus and send to vlibras
  141 + def processFocus(self, obj, nextHandler):
  142 + try:
  143 + if (obj.role == controlTypes.ROLE_UNKNOWN):
  144 + return self.handleSpeech(obj, nextHandler)
  145 + info = api.getReviewPosition()
  146 + if (info is None):
  147 + return self.handleSpeech(obj, nextHandler)
  148 + info.expand(textInfos.UNIT_READINGCHUNK)
  149 + textToSend = info._get_text()
  150 + if textToSend is None:
  151 + return self.handleSpeech(obj, nextHandler)
  152 + textToSend = textToSend.strip(" \t\r\n")
  153 + # mutex to protect self.__lastTextSend
  154 + self.__mutex.acquire()
  155 + try:
  156 + if (textToSend and textToSend != self.__lastTextSend):
  157 + self.__lastTextSend = textToSend
  158 + if (self.__client.send(textToSend)):
  159 + logHandler.log.debugWarning(">> %s\n" % (textToSend))
  160 + finally:
  161 + self.__mutex.release()
  162 + except Exception as e:
  163 + logHandler.log.error(u"%s\n%s" % (e.message, e.args))
  164 + return self.handleSpeech(obj, nextHandler)
  165 +
  166 + # get the current text in mouse focus and send to vlibras
  167 + def processMouse(self, obj, nextHandler, x, y):
  168 + try:
  169 + if (not self.__captureMouse):
  170 + return self.handleSpeech(obj, nextHandler)
  171 + if (obj.role == controlTypes.ROLE_UNKNOWN):
  172 + return self.handleSpeech(obj, nextHandler)
  173 + info = api.getReviewPosition()
  174 + if (info is None):
  175 + return self.handleSpeech(obj, nextHandler)
  176 + info.expand(info.unit_mouseChunk)
  177 + textToSend = info._get_text()
  178 + if textToSend is None:
  179 + return self.handleSpeech(obj, nextHandler)
  180 + textToSend = textToSend.strip(" \t\r\n")
  181 + # mutex to protect self.__lastTextSend
  182 + self.__mutex.acquire()
  183 + try:
  184 + if (textToSend and textToSend != self.__lastTextSend):
  185 + self.__lastTextSend = textToSend
  186 + if (self.__client.send(textToSend)):
  187 + logHandler.log.debugWarning(">> %s\n" % (textToSend))
  188 + finally:
  189 + self.__mutex.release()
  190 + except Exception as e:
  191 + logHandler.log.error(u"%s\n%s" % (e.message, e.args))
  192 + return self.handleSpeech(obj, nextHandler)
  193 +
  194 + # Override
  195 + def event_typedCharacter(self, obj, nextHandler, ch):
  196 + return self.handleSpeech(obj, nextHandler)
  197 +
  198 + # Override -> processMouse
  199 + def event_mouseMove(self, obj, nextHandler, x, y):
  200 + return self.processMouse(obj, nextHandler, x, y)
  201 +
  202 + # Override
  203 + def event_stateChange(self, obj, nextHandler):
  204 + return self.handleSpeech(obj, nextHandler)
  205 +
  206 + # Override
  207 + def event_focusEntered(self, obj, nextHandler):
  208 + return self.handleSpeech(obj, nextHandler)
  209 +
  210 + # Override -> processFocus
  211 + def event_gainFocus(self, obj, nextHandler):
  212 + return self.processFocus(obj, nextHandler)
  213 +
  214 + # Override
  215 + def event_foreground(self, obj, nextHandler):
  216 + return self.handleSpeech(obj, nextHandler)
  217 +
  218 + # Override
  219 + def event_becomeNavigatorObject(self, obj, nextHandler):
  220 + return self.handleSpeech(obj, nextHandler)
  221 +
  222 + # Override
  223 + def event_valueChange(self, obj, nextHandler):
  224 + return self.handleSpeech(obj, nextHandler)
  225 +
  226 + # Override
  227 + def event_nameChange(self, obj, nextHandler):
  228 + return self.handleSpeech(obj, nextHandler)
  229 +
  230 + # Override
  231 + def event_descriptionChange(self, obj, nextHandler):
  232 + return self.handleSpeech(obj, nextHandler)
  233 +
  234 + # Override
  235 + def event_caret(self, obj, nextHandler):
  236 + return self.handleSpeech(obj, nextHandler)
  237 +
  238 + # Override
  239 + def event_loseFocus(self, obj, nextHandler):
  240 + return self.handleSpeech(obj, nextHandler)
  241 +
  242 + # Override
  243 + def event_locationChange(self, obj, nextHandler):
  244 + return self.handleSpeech(obj, nextHandler)
... ...
vlibras.nvda-addon/make.cmd 0 → 100644
... ... @@ -0,0 +1,110 @@
  1 +@ECHO OFF
  2 +
  3 +CD /D "%~dp0"
  4 +
  5 +SET "VLIBRAS_ADDON_DIR=%APPDATA%\nvda\addons\vlibras"
  6 +SET "VLIBRAS_ADDON_NAME=vlibras.nvda-addon"
  7 +
  8 +:MAIN
  9 + SETLOCAL ENABLEDELAYEDEXPANSION
  10 + SET "TARGETS=BUILD HELP INSTALL KILL OPEN RUN UNINSTALL UPDATE"
  11 + SET /A "ARGC=0"
  12 + FOR %%A IN (%*) DO (
  13 + SET /A "ARGC+=1"
  14 + SET "ARGVALID=FALSE"
  15 + IF /I "%%A" EQU "--help" (CALL :HELP & GOTO :END)
  16 + IF /I "%%A" EQU "-help" (CALL :HELP & GOTO :END)
  17 + IF /I "%%A" EQU "/help" (CALL :HELP & GOTO :END)
  18 + FOR %%B IN (%TARGETS%) DO (
  19 + IF /I "%%A" == "%%B" (
  20 + SET "ARGVALID=TRUE"
  21 + CALL :%%A
  22 + )
  23 + )
  24 + IF /I "!ARGVALID!" EQU "FALSE" (
  25 + ECHO.Argument !ARGC! is not valid: %%A
  26 + ECHO.For help type: %~nn0 HELP
  27 + ECHO.Targets: %TARGETS%
  28 + GOTO :END
  29 + )
  30 + )
  31 + IF %ARGC% LSS 1 (CALL :BUILD)
  32 +:END
  33 + ENDLOCAL
  34 +EXIT /B
  35 +
  36 +:HELP
  37 + ECHO.
  38 + ECHO. Usage: Makefile ^<options^>
  39 + ECHO.
  40 + ECHO. Options Description
  41 + ECHO. build build plugin %VLIBRAS_ADDON_NAME%
  42 + ECHO. help show this help
  43 + ECHO. install install %VLIBRAS_ADDON_NAME%
  44 + ECHO. kill kill all nvda process
  45 + ECHO. open open nvda appdata directory
  46 + ECHO. run start nvda
  47 + ECHO. uninstall remove %VLIBRAS_ADDON_NAME%
  48 + ECHO. update reinstall %VLIBRAS_ADDON_NAME% and restart NVDA
  49 + ECHO.
  50 +GOTO :EOF
  51 +
  52 +:BUILD
  53 + SET "PATH=%CD%\bin;%PATH%"
  54 + SET "FILE=%FILE% manifest.ini"
  55 + SET "FOLDER=%FOLDER% doc\*"
  56 + REM SET "FOLDER=%FOLDER% appModules\*"
  57 + SET "FOLDER=%FOLDER% globalPlugins\*"
  58 + 2>NUL DEL "%VLIBRAS_ADDON_NAME%"
  59 + 7z a -aoa -tzip "%VLIBRAS_ADDON_NAME%" %FILE% %FOLDER% -r -mx9 -mmt
  60 +GOTO :EOF
  61 +
  62 +:INSTALL
  63 + XCOPY /V /I /S /Q /Y ".\doc" "%VLIBRAS_ADDON_DIR%\doc"
  64 + REM XCOPY /V /I /S /Q /Y ".\appModules" "%VLIBRAS_ADDON_DIR%\appModules"
  65 + XCOPY /V /I /S /Q /Y ".\globalPlugins" "%VLIBRAS_ADDON_DIR%\globalPlugins"
  66 + XCOPY /V /I /Q /Y ".\manifest.ini" "%VLIBRAS_ADDON_DIR%"
  67 +GOTO :EOF
  68 +
  69 +:KILL
  70 + TASKKILL /F /IM nvda.exe
  71 + TASKKILL /F /IM nvda_eoaProxy.exe
  72 + TASKKILL /F /IM nvda_noUIAccess.exe
  73 + TASKKILL /F /IM nvda_service.exe
  74 + TASKKILL /F /IM nvda_slave.exe
  75 +GOTO :EOF
  76 +
  77 +:OPEN
  78 + IF EXIST "%VLIBRAS_ADDON_DIR%" (
  79 + START "" EXPLORER "%VLIBRAS_ADDON_DIR%"
  80 + ) ELSE (
  81 + ECHO.NVDA is not installed!
  82 + )
  83 +GOTO :EOF
  84 +
  85 +:RUN
  86 + SET "NVDA_EXE=NVDA\nvda_slave.exe"
  87 + SET "NVDA_X86=%PROGRAMFILES%\%NVDA_EXE%"
  88 + SET "NVDA_X64=%PROGRAMFILES(x86)%\%NVDA_EXE%"
  89 + IF EXIST "%NVDA_X86%" (
  90 + START "" "%NVDA_X86%" launchNVDA -r
  91 + ) ELSE IF EXIST "%NVDA_X64%" (
  92 + START "" "%NVDA_X64%" launchNVDA -r
  93 + ) ELSE (
  94 + ECHO.NVDA is not installed!
  95 + )
  96 +GOTO :EOF
  97 +
  98 +:UNINSTALL
  99 + IF EXIST "%VLIBRAS_ADDON_DIR%" (
  100 + RMDIR /S /Q "%VLIBRAS_ADDON_DIR%"
  101 + ) ELSE (
  102 + ECHO.%VLIBRAS_ADDON_NAME% is not installed!
  103 + )
  104 +GOTO :EOF
  105 +
  106 +:UPDATE
  107 + CALL :KILL
  108 + CALL :INSTALL
  109 + CALL :RUN
  110 +GOTO :EOF
... ...
vlibras.nvda-addon/manifest.ini 0 → 100644
... ... @@ -0,0 +1,7 @@
  1 +name = "vlibras"
  2 +summary = "VLibras Plugin"
  3 +version = 1.0 23.01.2017
  4 +description = """Comunicate with vlibras player."""
  5 +author = "Laboratório de Aplicações de Vídeo Digital - Lavid"
  6 +url = http://lavid.ufpb.br
  7 +docFileName = readme.html
... ...
vlibras.nvda-addon/server/server.cmd 0 → 100644
... ... @@ -0,0 +1,4 @@
  1 +@ECHO OFF
  2 +CD /D "%~dp0"
  3 +COLOR 9F
  4 +python server.py
... ...
vlibras.nvda-addon/server/server.py 0 → 100644
... ... @@ -0,0 +1,25 @@
  1 +# -*- coding: utf-8 -*-
  2 +
  3 +import socket
  4 +
  5 +host = "127.0.0.1"
  6 +port = 10001
  7 +sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  8 +sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
  9 +sock.bind((host, port))
  10 +sock.listen(1)
  11 +
  12 +print("[Esperando Cliente] %s:%d" % (host, port))
  13 +while True:
  14 + try:
  15 + con, cli = sock.accept()
  16 + print("[Cliente Conectado] %s:%s" % (cli))
  17 + while True:
  18 + msg = con.recv(1024)
  19 + if (msg):
  20 + print(msg)
  21 + else:
  22 + print("[Cliente Desconectado] %s:%s" % (cli))
  23 + break
  24 + except:
  25 + con.close()
... ...