|
|
@ -51,12 +51,7 @@ struct module_state {
|
|
|
|
PyObject *error;
|
|
|
|
PyObject *error;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
#if PY_MAJOR_VERSION >= 3
|
|
|
|
|
|
|
|
#define GETSTATE(m) ((struct module_state*)PyModule_GetState(m))
|
|
|
|
#define GETSTATE(m) ((struct module_state*)PyModule_GetState(m))
|
|
|
|
#else
|
|
|
|
|
|
|
|
#define GETSTATE(m) (&_state)
|
|
|
|
|
|
|
|
static struct module_state _state;
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
static PyObject *
|
|
|
|
error_out(PyObject *m) {
|
|
|
|
error_out(PyObject *m) {
|
|
|
@ -356,8 +351,6 @@ static PyMethodDef karamba_methods[] = {
|
|
|
|
{NULL, NULL, 0 ,NULL}
|
|
|
|
{NULL, NULL, 0 ,NULL}
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
#if PY_MAJOR_VERSION >= 3
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int karamba_traverse(PyObject *m, visitproc visit, void *arg) {
|
|
|
|
static int karamba_traverse(PyObject *m, visitproc visit, void *arg) {
|
|
|
|
Py_VISIT(GETSTATE(m)->error);
|
|
|
|
Py_VISIT(GETSTATE(m)->error);
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
@ -382,22 +375,18 @@ static struct PyModuleDef karambadef = {
|
|
|
|
|
|
|
|
|
|
|
|
#define INITERROR return NULL
|
|
|
|
#define INITERROR return NULL
|
|
|
|
|
|
|
|
|
|
|
|
#else
|
|
|
|
PyMODINIT_FUNC PyInit_karamba(void)
|
|
|
|
|
|
|
|
{
|
|
|
|
#define INITERROR return
|
|
|
|
return PyModule_Create(&karambadef);
|
|
|
|
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
PyThreadState* KarambaPython::mainThreadState = 0;
|
|
|
|
PyThreadState* KarambaPython::mainThreadState = 0;
|
|
|
|
|
|
|
|
|
|
|
|
KarambaPython::KarambaPython(const ThemeFile& theme, bool reloading):
|
|
|
|
KarambaPython::KarambaPython(const ThemeFile& theme, bool reloading):
|
|
|
|
pythonThemeExtensionLoaded(false), pName(0), pModule(0), pDict(0)
|
|
|
|
pythonThemeExtensionLoaded(false), pName(0), pModule(0), pDict(0)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
PyThreadState* myThreadState;
|
|
|
|
|
|
|
|
char pypath[1024];
|
|
|
|
char pypath[1024];
|
|
|
|
|
|
|
|
|
|
|
|
getLock(&myThreadState);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// load the .py file for this .theme
|
|
|
|
// load the .py file for this .theme
|
|
|
|
PyRun_SimpleString((char*)"import sys");
|
|
|
|
PyRun_SimpleString((char*)"import sys");
|
|
|
|
//Add theme path to python path so that we can find the python file
|
|
|
|
//Add theme path to python path so that we can find the python file
|
|
|
@ -405,13 +394,7 @@ KarambaPython::KarambaPython(const ThemeFile& theme, bool reloading):
|
|
|
|
PyRun_SimpleString(pypath);
|
|
|
|
PyRun_SimpleString(pypath);
|
|
|
|
PyRun_SimpleString((char*)"sys.path.insert(0, '')");
|
|
|
|
PyRun_SimpleString((char*)"sys.path.insert(0, '')");
|
|
|
|
|
|
|
|
|
|
|
|
PyImport_AddModule((char*)"karamba");
|
|
|
|
pName = PyUnicode_FromString(theme.pythonModule().utf8());
|
|
|
|
#if PY_MAJOR_VERSION >= 3
|
|
|
|
|
|
|
|
PyModule_Create(&karambadef);
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
Py_InitModule((char*)"karamba", karamba_methods);
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
pName = PyBytes_FromString(theme.pythonModule().ascii());
|
|
|
|
|
|
|
|
pModule = PyImport_Import(pName);
|
|
|
|
pModule = PyImport_Import(pName);
|
|
|
|
|
|
|
|
|
|
|
|
fprintf(stderr, "%s\n", pypath);
|
|
|
|
fprintf(stderr, "%s\n", pypath);
|
|
|
@ -443,72 +426,40 @@ KarambaPython::KarambaPython(const ThemeFile& theme, bool reloading):
|
|
|
|
fprintf(stderr,
|
|
|
|
fprintf(stderr,
|
|
|
|
"------------------------------------------------------\n");
|
|
|
|
"------------------------------------------------------\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
releaseLock(myThreadState);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
KarambaPython::~KarambaPython()
|
|
|
|
KarambaPython::~KarambaPython()
|
|
|
|
{
|
|
|
|
{
|
|
|
|
//Clean up Python references
|
|
|
|
//Clean up Python references
|
|
|
|
if (pythonThemeExtensionLoaded) {
|
|
|
|
if (pythonThemeExtensionLoaded) {
|
|
|
|
PyThreadState* myThreadState;
|
|
|
|
|
|
|
|
getLock(&myThreadState);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//Displose of current python module so we can reload in constructor.
|
|
|
|
//Displose of current python module so we can reload in constructor.
|
|
|
|
Py_DECREF(pModule);
|
|
|
|
Py_DECREF(pModule);
|
|
|
|
Py_DECREF(pName);
|
|
|
|
Py_DECREF(pName);
|
|
|
|
|
|
|
|
|
|
|
|
releaseLock(myThreadState);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void KarambaPython::initPython()
|
|
|
|
void KarambaPython::initPython()
|
|
|
|
{
|
|
|
|
{
|
|
|
|
// initialize Python
|
|
|
|
// initialize Python
|
|
|
|
|
|
|
|
PyImport_AppendInittab((char*)"karamba", PyInit_karamba);
|
|
|
|
Py_Initialize();
|
|
|
|
Py_Initialize();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION <= 6
|
|
|
|
// initialize thread support
|
|
|
|
// initialize thread support
|
|
|
|
PyEval_InitThreads();
|
|
|
|
PyEval_InitThreads();
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
// save a pointer to the main PyThreadState object
|
|
|
|
// save a pointer to the main PyThreadState object
|
|
|
|
mainThreadState = PyThreadState_Get();
|
|
|
|
mainThreadState = PyThreadState_Get();
|
|
|
|
|
|
|
|
|
|
|
|
// release the lock
|
|
|
|
|
|
|
|
PyEval_ReleaseLock();
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void KarambaPython::shutdownPython()
|
|
|
|
void KarambaPython::shutdownPython()
|
|
|
|
{
|
|
|
|
{
|
|
|
|
// shut down the interpreter
|
|
|
|
// shut down the interpreter
|
|
|
|
PyInterpreterState * mainInterpreterState = mainThreadState->interp;
|
|
|
|
PyThreadState_Swap(mainThreadState);
|
|
|
|
// create a thread state object for this thread
|
|
|
|
|
|
|
|
PyThreadState * myThreadState = PyThreadState_New(mainInterpreterState);
|
|
|
|
|
|
|
|
PyThreadState_Swap(myThreadState);
|
|
|
|
|
|
|
|
PyEval_AcquireLock();
|
|
|
|
|
|
|
|
Py_Finalize();
|
|
|
|
Py_Finalize();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void KarambaPython::getLock(PyThreadState** myThreadState)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
// get the global lock
|
|
|
|
|
|
|
|
PyEval_AcquireLock();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// create a thread state object for this thread
|
|
|
|
|
|
|
|
*myThreadState = PyThreadState_New(mainThreadState->interp);
|
|
|
|
|
|
|
|
PyThreadState_Swap(*myThreadState);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void KarambaPython::releaseLock(PyThreadState* myThreadState)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
// swap my thread state out of the interpreter
|
|
|
|
|
|
|
|
PyThreadState_Swap(NULL);
|
|
|
|
|
|
|
|
// clear out any cruft from thread state object
|
|
|
|
|
|
|
|
PyThreadState_Clear(myThreadState);
|
|
|
|
|
|
|
|
// delete my thread state object
|
|
|
|
|
|
|
|
PyThreadState_Delete(myThreadState);
|
|
|
|
|
|
|
|
// release the lock
|
|
|
|
|
|
|
|
PyEval_ReleaseLock();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
PyObject* KarambaPython::getFunc(const char* function)
|
|
|
|
PyObject* KarambaPython::getFunc(const char* function)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
PyObject* pFunc = PyDict_GetItemString(pDict, (char*)function);
|
|
|
|
PyObject* pFunc = PyDict_GetItemString(pDict, (char*)function);
|
|
|
@ -517,17 +468,11 @@ PyObject* KarambaPython::getFunc(const char* function)
|
|
|
|
return NULL;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool KarambaPython::callObject(const char* func, PyObject* pArgs, bool lock)
|
|
|
|
bool KarambaPython::callObject(const char* func, PyObject* pArgs)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
bool result = false;
|
|
|
|
bool result = false;
|
|
|
|
PyThreadState* myThreadState;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//tqDebug("Calling %s", func);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (lock)
|
|
|
|
|
|
|
|
getLock(&myThreadState);
|
|
|
|
|
|
|
|
PyObject* pFunc = getFunc(func);
|
|
|
|
PyObject* pFunc = getFunc(func);
|
|
|
|
|
|
|
|
|
|
|
|
if (pFunc != NULL)
|
|
|
|
if (pFunc != NULL)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
PyObject* pValue = PyObject_CallObject(pFunc, pArgs);
|
|
|
|
PyObject* pValue = PyObject_CallObject(pFunc, pArgs);
|
|
|
@ -544,8 +489,6 @@ bool KarambaPython::callObject(const char* func, PyObject* pArgs, bool lock)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Py_DECREF(pArgs);
|
|
|
|
Py_DECREF(pArgs);
|
|
|
|
if (lock)
|
|
|
|
|
|
|
|
releaseLock(myThreadState);
|
|
|
|
|
|
|
|
return result;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -597,8 +540,7 @@ bool KarambaPython::widgetClicked(karamba* k, int x, int y, int button)
|
|
|
|
return callObject("widgetClicked", pArgs);
|
|
|
|
return callObject("widgetClicked", pArgs);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool KarambaPython::keyPressed(karamba* k, const Meter* meter,
|
|
|
|
bool KarambaPython::keyPressed(karamba* k, const Meter* meter, const TQString& text)
|
|
|
|
const TQString& text)
|
|
|
|
|
|
|
|
{
|
|
|
|
{
|
|
|
|
PyObject* pArgs = Py_BuildValue((char*)"(lls)", k, meter, text.ucs2());
|
|
|
|
PyObject* pArgs = Py_BuildValue((char*)"(lls)", k, meter, text.ucs2());
|
|
|
|
return callObject("keyPressed", pArgs);
|
|
|
|
return callObject("keyPressed", pArgs);
|
|
|
@ -660,13 +602,8 @@ bool KarambaPython::itemDropped(karamba* k, TQString text, int x, int y)
|
|
|
|
|
|
|
|
|
|
|
|
bool KarambaPython::themeNotify(karamba* k, const char *from, const char *str)
|
|
|
|
bool KarambaPython::themeNotify(karamba* k, const char *from, const char *str)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
// WARNING WARNING WARNING i had to switch off thread locking to get
|
|
|
|
|
|
|
|
// this to work. callNotify is called from INSIDE another locked thread,
|
|
|
|
|
|
|
|
// so can never complete because themeNotify will expect locking to be
|
|
|
|
|
|
|
|
// released...
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
PyObject* pArgs = Py_BuildValue((char*)"(lss)", k, from, str);
|
|
|
|
PyObject* pArgs = Py_BuildValue((char*)"(lss)", k, from, str);
|
|
|
|
return callObject("themeNotify", pArgs, false);
|
|
|
|
return callObject("themeNotify", pArgs);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool KarambaPython::systrayUpdated(karamba* k)
|
|
|
|
bool KarambaPython::systrayUpdated(karamba* k)
|
|
|
|