NVDA globalPlugins
since 2012-05-07
nvda のグローバルプラグインに関する覚え書き。
ファイル名またはディレクトリ名が _ で始まるときはスキャンしない。 それ以外のファイルおよびディレクトリはスキャンされて class GlobalPlugin(globalPluginHandler.GlobalPlugin) がないとエラーになる。
Pythonコンソールとプラグイン
Python コンソールで以下のようにプラグインにアクセスできる。
import globalPluginHandler globalPluginHandler.runningPlugins -> 実行中のプラグインオブジェクトの set インスタンス import globalPlugins dir(globalPlugins.プラグイン名.GlobalPlugin) -> クラスのプロパティとメソッド
日本語処理のプラグイン化
下記を確認した。
2012.1j の nvdajptext フォルダを NVDA 本家の開発版の source/globalPlugins/_nvdajptext としてコピーする。
source/globalPlugins/nvdajp.py を以下のように作る。
from logHandler import log import globalPluginHandler from _nvdajptext import translate class GlobalPlugin(globalPluginHandler.GlobalPlugin): def __init__(self): super(GlobalPlugin, self).__init__() log.info("nvdajp plugin loaded") text=u'日本語' text=translate.braille_transcription(text) log.info(text)
source/globalPlugins/_nvdajptext/translate.py はこのままだと nvdajptext.mecab を見に行ってしまうので、下記を修正する:
#try: # from nvdajptext.mecab import * #except: # import sys # import os # sys.path.append(os.getcwd()) # from nvdajptext.mecab import * from mecab import *
source\nvda.pyw を実行すると、ログが下記のようになり、NVDA本家版で mecab の実行ができたことがわかる。
INFO - globalPlugins.nvdajp.GlobalPlugin.__init__ (13:02:18): nvdajp plugin loaded INFO - globalPlugins._nvdajptext.mecab.Mecab_initialize (13:02:18): nvdajptext.dll 20111017 mecab:0.98 nvdajp-jtalk-dic 20120403-053143 INFO - globalPlugins._nvdajptext.translate.braille_transcription (13:02:18): ニホンゴ INFO - globalPlugins.nvdajp.GlobalPlugin.__init__ (13:02:18): ニホンゴ
しかし実は mecab.py の中で DLL と辞書ファイルが指定されているので、source/nvdajptext ディレクトリがないと以下のエラーになる。
INFO - globalPlugins.nvdajp.GlobalPlugin.__init__ (13:19:08): nvdajp plugin loaded ERROR - globalPluginHandler.initialize (13:19:08): Error initializing global plugin <class 'globalPlugins.nvdajp.GlobalPlugin'> Traceback (most recent call last): File "globalPluginHandler.py", line 32, in initialize runningPlugins.add(plugin()) File "globalPlugins\nvdajp.py", line 14, in __init__ text=translate.braille_transcription(text) File "globalPlugins\_nvdajptext\translate.py", line 83, in braille_transcription Mecab_initialize(_logwrite) File "globalPlugins\_nvdajptext\mecab.py", line 130, in Mecab_initialize libmc = cdll.LoadLibrary(MECAB_DLL) File "C:\Python27\lib\ctypes\__init__.py", line 431, in LoadLibrary return self._dlltype(name) File "C:\Python27\lib\ctypes\__init__.py", line 353, in __init__ self._handle = _dlopen(self._name, mode) WindowsError: [Error 126] 指定されたモジュールが見つかりません。 INFO - core.main (13:19:08):
エラーメッセージを参考に globalPlugins/_nvdajptext/mecab.py を修正する:
DIC = r"globalPlugins\_nvdajptext\dic" MECAB_DLL = r"globalPlugins\_nvdajptext\libmecab.dll" MECABRC = r"globalPlugins\_nvdajptext\mecabrc" NVDAJPTEXT_DLL = r"globalPlugins\_nvdajptext\nvdajptext.dll"
nvdajptext.dll は lib から globalPlugins/_nvdajptext に移動する。
これで同じように実験すると、成功:
INFO - globalPlugins.nvdajp.GlobalPlugin.__init__ (13:23:00): nvdajp plugin loaded INFO - globalPlugins._nvdajptext.mecab.Mecab_initialize (13:23:00): nvdajptext.dll 20111017 mecab:0.98 nvdajp-jtalk-dic 20120403-053143 INFO - globalPlugins._nvdajptext.translate.braille_transcription (13:23:00): ニホンゴ INFO - globalPlugins.nvdajp.GlobalPlugin.__init__ (13:23:00): ニホンゴ
C:\Users\nishimotz\AppData\Roaming\nvda\globalPlugins に nvdajp.py と _nvdajptext を移す。
本家 nvda_snapshot_main-5152 を実行。
結果は失敗:
INFO - ..................nishimotz.AppData.Roaming.nvda.globalPlugins.nvdajp.GlobalPlugin.__init__ (13:32:16): nvdajp plugin loaded ERROR - globalPluginHandler.initialize (13:32:16): Error initializing global plugin <class 'globalPlugins.nvdajp.GlobalPlugin'> Traceback (most recent call last): File "globalPluginHandler.pyc", line 32, in initialize File "C:\Users\nishimotz\AppData\Roaming\nvda\globalPlugins\nvdajp.py", line 14, in __init__ File "C:\Users\nishimotz\AppData\Roaming\nvda\globalPlugins\_nvdajptext\translate.py", line 83, in braille_transcription File "C:\Users\nishimotz\AppData\Roaming\nvda\globalPlugins\_nvdajptext\mecab.py", line 126, in Mecab_initialize File "ctypes\__init__.pyc", line 431, in LoadLibrary File "ctypes\__init__.pyc", line 353, in __init__ WindowsError: [Error 126] 指定されたモジュールが見つかりません。 INFO - core.main (13:32:16): NVDA initialized
本家の OCR プラグインを参考に globalPlugins/_nvdajptext/mecab.py をふたたび修正する:
import os # omitted PLUGIN_DIR = os.path.dirname(__file__) DIC = os.path.join(PLUGIN_DIR, "dic" ) MECAB_DLL = os.path.join(PLUGIN_DIR, "libmecab.dll") MECABRC = os.path.join(PLUGIN_DIR, "mecabrc") NVDAJPTEXT_DLL = os.path.join(PLUGIN_DIR, "nvdajptext.dll")
今度はうまくいった:
INFO - ..................nishimotz.AppData.Roaming.nvda.globalPlugins.nvdajp.GlobalPlugin.__init__ (14:29:49): nvdajp plugin loaded INFO - ..................nishimotz.AppData.Roaming.nvda.globalPlugins._nvdajptext.mecab.Mecab_initialize (14:29:49): nvdajptext.dll 20111017 mecab:0.98 nvdajp-jtalk-dic 20120403-053143 INFO - ..................nishimotz.AppData.Roaming.nvda.globalPlugins._nvdajptext.translate.braille_transcription (14:29:49): ニホンゴ INFO - ..................nishimotz.AppData.Roaming.nvda.globalPlugins.nvdajp.GlobalPlugin.__init__ (14:29:49): ニホンゴ INFO - core.main (14:29:49): NVDA initialized
音声ドライバから呼び出す
最初は synthDriver から nvdajp プラグインのメソッドを呼び出そうと思っていた。
しかし、よく調べてみると、起動シーケンスが、音声ドライバのロード、点字ディスプレイドライバのロード、グローバルプラグインのロード、という順番なので、初期化に失敗する。
結局、グローバルプラグインのディレクトリを調べて import することに。プラグインにしなくてもよかった(プラグイン nvdajp.py は使わなかった)という話。。
# find mecab.py in globalPlugins/_nvdajptext import config from logHandler import log loaded = False for d in config.getConfigDirs('globalPlugins'): if loaded: break d2 = os.path.join(d, '_nvdajptext') sys.path.append(d2) log.debug("sys.path %s" % ' '.join(sys.path)) try: from mecab import * log.info("mecab loaded from %s" % d2) loaded = True except: log.debug("mecab load failed from %s" % d2) del sys.path[-1] if not loaded: log.error("mecab load failed")
JTalk への実装の成果は lp:~nishimotz/nvdajp/betterJtalk 4214 である。
本家 NVDA のポータブル版で userConfig/{synthDrivers,globalPlugins} に入れた JTalk がしゃべることは確認できた。