Skip to content

Commit

Permalink
Merge remote-tracking branch 'dt/master'
Browse files Browse the repository at this point in the history
  • Loading branch information
quintijn committed Aug 23, 2024
2 parents b15f085 + b94edd2 commit 3af908d
Show file tree
Hide file tree
Showing 6 changed files with 114 additions and 29 deletions.
2 changes: 1 addition & 1 deletion CMakeSettings.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"configurations": [
{
"name": "3.10-32",
"name": "3.10-11",
"generator": "Visual Studio 16 2019",
"configurationType": "Debug",
"buildRoot": "${projectDir}\\out\\build\\${name}",
Expand Down
100 changes: 82 additions & 18 deletions NatlinkSource/COM/appsupp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ CDragonCode * initModule();

CDgnAppSupport::CDgnAppSupport()
{
OutputDebugStringA("CDgnAppSupport::CDgnAppSupport");
m_pNatlinkModule = NULL;
m_pDragCode = NULL;
}
Expand All @@ -36,10 +37,13 @@ CDgnAppSupport::CDgnAppSupport()

CDgnAppSupport::~CDgnAppSupport()
{
OutputDebugStringA("CDgnAppSupport::~CDgnAppSupport");
}
//see https://gist.github.com/pwm1234/05280cf2e462853e183d
static std::string get_this_module_path()

{
OutputDebugStringA("get_this_module_path");
void* address = (void*)get_this_module_path;
char path[FILENAME_MAX];
HMODULE hm = NULL;
Expand All @@ -48,13 +52,16 @@ static std::string get_this_module_path()
GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
(LPCSTR)address,
&hm))
{
{ OutputDebugString(TEXT("get_this_module_path fail GetModuleHandleExA"));
//if this fails, well just return nonsense.
return "";
}
GetModuleFileNameA(hm, path, sizeof(path));

std::string p = path;
std::string msg = std::string("get_this_module_path returning: ") + p;
OutputDebugStringA(msg.c_str());

return p;
}
static int pyrun_string(std::string python_cmd)
Expand Down Expand Up @@ -106,24 +113,50 @@ static std::string AddOurDirToConfig(PyConfig *config) {


static std::string AddPythonInstallPathToConfig(PyConfig *config) {
using winreg::RegKey, winreg::RegResult;
std::wstring key_wstring(L"SOFTWARE\\Natlink");
RegKey key;
RegResult result = key.TryOpen(HKEY_LOCAL_MACHINE, key_wstring.c_str(), KEY_READ);
if (!result) {
return (std::string("Error: could not open HKLM\\") +
std::string(key_wstring.begin(), key_wstring.end()) + std::string("\n"));
}
else { // now the install location of Python is known
std::wstring new_wstring(key.GetStringValue(L"pythonInstallPath"));
if (auto new_wstring = key.TryGetStringValue(L"pythonInstallPath")) {
PyConfig_SetString(config, &(config->prefix), (*new_wstring).c_str());
return std::string("");
} else {
return (std::string("Error: could not open subkey pythonInstallPath of HKLM\\") +
try
{
using winreg::RegKey, winreg::RegResult;
std::wstring key_wstring(L"SOFTWARE\\Natlink");
RegKey key;
std::wstring msg=std::wstring(L"AddPythonInstallPathToConfig: key_wstring: ")+key_wstring + L" trying TryOpen";
OutputDebugStringW(msg.c_str());

RegResult result = key.TryOpen(HKEY_LOCAL_MACHINE, key_wstring.c_str(), KEY_READ);
OutputDebugString(TEXT("Try Open returned"));


if (!result) {
return (std::string("Error: could not open HKLM\\") +
std::string(key_wstring.begin(), key_wstring.end()) + std::string("\n"));
}
}
else { // now the install location of Python is known
OutputDebugString(L"Attempted pythonInstallPath");
std::wstring new_wstring(key.GetStringValue(L"pythonInstallPath"));
OutputDebugString( (std::wstring(L"new_wstring: ") + new_wstring).c_str());

OutputDebugString(L"Attempted pythonInstallPath again");

if (auto new_wstring = key.TryGetStringValue(L"pythonInstallPath")) {

OutputDebugString(std::wstring(L"Attempting PyConfig_SetString: ").c_str() );
OutputDebugString( (std::wstring(L"new_wstring: ") + *new_wstring).c_str());

PyConfig_SetString(config, &(config->prefix), (*new_wstring).c_str());
OutputDebugString(std::wstring(L"SetString Completed ").c_str() );

return std::string("");
} else {
return (std::string("Error: could not open subkey pythonInstallPath of HKLM\\") +
std::string(key_wstring.begin(), key_wstring.end()) + std::string("\n"));
}
}
}
catch(...)
{
OutputDebugString(L"Exception in AddPythonInstallPathToConfig");
return std::string("");
}
return std::string("");
}


Expand Down Expand Up @@ -180,33 +213,47 @@ static void CallPyFunctionOrDisplayError(CDragonCode* pDragCode, PyObject* pMod,
// Try to make our customized Python behave like regular Python;
// see https://docs.python.org/3/c-api/init_config.html#init-python-config
std::string DoPyConfig(void) {

OutputDebugString(TEXT("DoPyConfig"));

std::string init_error = "";
PyStatus status;
PyConfig config;
PyConfig_InitPythonConfig(&config);
OutputDebugString(TEXT("DoPyConfig PyConfig_InitPythonConfig done, attempt AddOutDirToConfig"));


init_error = AddOurDirToConfig(&config);

std::string msg1 = std::string("DoPyConfig PyConfig_InitPythonConfig done, init_error: ")+ init_error;
OutputDebugStringA(msg1.c_str());

if (!init_error.empty()) {
goto fail;
}
OutputDebugString(TEXT("DoPyConfig attempt AddPythonInstallPathToConfig"));

init_error = AddPythonInstallPathToConfig(&config);
if (!init_error.empty()) {
goto fail;
}
OutputDebugString(TEXT("DoPyConfig attempt PyConfig_SetString"));

status = PyConfig_SetString(&config, &(config.program_name), L"Python");
if (PyStatus_Exception(status)) {
init_error = "Natlink: failed to set program_name\n";
goto fail;
}
OutputDebugString(TEXT("DoPyConfig attempt PyIntializeFromConfig"));

status = Py_InitializeFromConfig(&config);
if (PyStatus_Exception(status)) {
init_error = "Natlink: failed initialize from config\n";
goto fail;
}


OutputDebugString(TEXT("DoPyConfig sucess"));

return init_error; // success, return ""

fail:
Expand All @@ -231,6 +278,7 @@ std::string DoPyConfig(void) {

STDMETHODIMP CDgnAppSupport::Register( IServiceProvider * pIDgnSite )
{
OutputDebugString(TEXT("CDgnAppSupport::Register"));
// load and initialize the Python system
std::string init_error = DoPyConfig();
Py_Initialize();
Expand All @@ -252,6 +300,7 @@ STDMETHODIMP CDgnAppSupport::Register( IServiceProvider * pIDgnSite )
// Python init
DisplayVersions(m_pDragCode);
if ( !init_error.empty()) {
OutputDebugStringA(init_error.c_str() );
m_pDragCode->displayText(init_error.c_str());
return S_OK;
}
Expand All @@ -265,6 +314,8 @@ STDMETHODIMP CDgnAppSupport::Register( IServiceProvider * pIDgnSite )
DisplayPythonException(m_pDragCode);
return S_OK;
} else {
OutputDebugString( TEXT( "Natlink is loaded..." ) );

m_pDragCode->displayText( "Natlink is loaded...\n\n", FALSE );
}

Expand Down Expand Up @@ -304,16 +355,26 @@ STDMETHODIMP CDgnAppSupport::Register( IServiceProvider * pIDgnSite )

STDMETHODIMP CDgnAppSupport::UnRegister()
{
OutputDebugString( TEXT( "CDgnAppSupport::UnRegister, calling natDisconnect" ) );

// simulate calling natlink.natDisconnect()
m_pDragCode->natDisconnect();

OutputDebugString( TEXT( "CDgnAppSupport::UnRegister, free reference to Python modules" ) );

// free our reference to the Python modules
Py_XDECREF( m_pNatlinkModule );

// finalize the Python interpreter
OutputDebugString( TEXT( "CDgnAppSupport::UnRegister, finalize interpreter" ) );

Py_Finalize();

PyMem_RawFree(L"python");

// finalize the Python interpreter
OutputDebugString( TEXT( "CDgnAppSupport::UnRegister, exit UnRegister" ) );

return S_OK;
}

Expand Down Expand Up @@ -366,5 +427,8 @@ STDMETHODIMP CDgnAppSupport::EndProcess( DWORD dwProcessID )

void CDgnAppSupport::reloadPython()
{
// finalize the Python interpreter
OutputDebugString( TEXT( "CDgnAppSupport::reloadPython" ) );

PyImport_ReloadModule(m_pNatlinkModule);
}
2 changes: 1 addition & 1 deletion docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ write computer programs. A grammar specifies what will happen when certain words

<div align="center">

[![view - Documentation](https://img.shields.io/badge/view-Documentation-blue?style=for-the-badge)](https://dictation-toolbox.github.io/natlink/#/)
[![matrix](https://img.shields.io/gitter/room/dictation-toolbox/natlink)](https://matrix.to/#/#dictation-toolbox_natlink:gitter.im) [![view - Documentation](https://img.shields.io/badge/view-Documentation-blue?)](https://dictation-toolbox.github.io/natlink/#/) [![GitHub Release](https://img.shields.io/github/v/release/dictation-toolbox/natlink?include_prereleases)](https://github.com/dictation-toolbox/natlink/releases)

</div>

Expand Down
4 changes: 2 additions & 2 deletions documentation/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ Welcome to a start point of Natlink's Documentation!!!

Natlink is an OpenSource extension module for the speech recognition program Dragon_.

Beware: Natlink is not working yet with Dragon 16!
With version 5.5.7 (August 21, 2024) most functions also work in Dragon 16.

Please go to the instructions for `Installing and configuring Natlink`_.

You you can find an Overview of all aspects of the `Dictation Toolbox`_.

.. _Dragon: https://www.nuance.com/dragon/business-solutions/dragon-professional-individual.html
.. _Installing and configuring Natlink: https://dictation-toolbox.github.io/natlink
.. _Dictation Toolbox: https://dictation-toolbox.github.io/dictation-toolbox.org/
.. _Dictation Toolbox: https://dictation-toolbox.github.io/dictation-toolbox.org/
2 changes: 1 addition & 1 deletion pythonsrc/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ classifiers=[
"Topic :: Software Development :: Libraries :: Python Modules"
]
dependencies=[
"dtactions >= 1.6.1"

]

[project.urls]
Expand Down
33 changes: 27 additions & 6 deletions pythonsrc/src/natlink/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

# make import natlink possible, getting all the _natlink_corexx.pyd functions...
#we have to know which pyd is registered by the installer.
#pylint:disable=W0702
#pylint:disable=W0702, W0718,

#site packages

Expand All @@ -14,7 +14,9 @@
import winreg
import ctypes
import contextlib
from dtactions.vocola_sendkeys import ext_keys
import win32api
import win32gui
from dtactions.vocola_sendkeys import ext_keys ### , SendInput
W32OutputDebugString = ctypes.windll.kernel32.OutputDebugStringW

#copied from pydebugstring.
Expand Down Expand Up @@ -60,7 +62,6 @@ def outputDebugString(to_show):
_natlink_core=importlib.util.module_from_spec(spec)
from _natlink_core import *

import locale
from _natlink_core import execScript as _execScript
from _natlink_core import playString as _playString
from _natlink_core import playEvents as _playEvents
Expand All @@ -82,11 +83,17 @@ def playString(a, hook=0):
# normal case:
return ext_keys.send_input(a)


def playEvents16(events):
"""obsolete with Dragon 16.
"""
print("Deprecated, playEvents on Dragon16 cannot be used any more")

def playEvents(a):
"""causes a halt (ESP error) in Dragon 16.
"""
if getDNSVersion() >= 16:
outputDebugString("ignore playEvents, it halts with Dragon 16 (ESP error)")
playEvents16(a)
return None
return _playEvents(a)

Expand Down Expand Up @@ -150,8 +157,22 @@ def NatlinkConnector():
natDisconnect()


# def _test_playEvents():
# """perform a few mouse moves
# """
# import time
# wm_mousemove = 0x0200
# positionsx = [10, 500, 500, 10, 10]
# positionsy = [10, 10, 500, 500, 10]
# for x, y in zip(positionsx, positionsy):
# playEvents( [(wm_mousemove, x, y)] )
# time.sleep(1)



if __name__ == "__main__":
outputDebugString(f'getDNSVersion: {getDNSVersion()} (type: {type(getDNSVersion())}))')
playString('abcde')
playEvents(tuple())
# playString('abcde')
# _test_playEvents()


0 comments on commit 3af908d

Please sign in to comment.