00001
00002 #include "py_commands.h"
00003 #include "vmd.h"
00004 #include "DisplayDevice.h"
00005 #include "UIText.h"
00006
00007 #ifdef VMDTCL
00008 #include <tcl.h>
00009 #endif
00010
00011 static PyObject *py_vmdupdate(PyObject *self, PyObject *args) {
00012 VMDApp *app;
00013 if (!(app = get_vmdapp())) {
00014 fprintf(stderr, "no app!!\n");
00015 Py_INCREF(Py_None);
00016 return Py_None;
00017 }
00018 return as_pyint(app->VMDupdate(1));
00019 }
00020
00021 static const char exit_doc[] =
00022 "Exits VMD\n\n"
00023 "Args:\n"
00024 " message (str): Message to print\n"
00025 " code (int): Code to return. Defaults to 0 (normal exit)\n"
00026 " delay (int): Number of seconds to delay before exiting. Defaults to 0\n";
00027 static PyObject *py_vmdexit(PyObject *self, PyObject *args, PyObject *kwargs)
00028 {
00029 const char *kwnames[] = {"message", "code", "delay", NULL};
00030 int code = 0, pauseseconds = 0;
00031 VMDApp *app;
00032 char *msg;
00033
00034 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"s|ii:vmd.VMDupdate",
00035 (char**) kwnames, &msg, &code,
00036 &pauseseconds))
00037 return NULL;
00038
00039 if (!(app = get_vmdapp()))
00040 return NULL;
00041
00042 app->VMDexit(msg, code, pauseseconds);
00043
00044
00045 Py_INCREF(Py_None);
00046 return Py_None;
00047 }
00048
00049 #ifdef VMDTCL
00050 static const char evaltcl_doc[] =
00051 "Evaluates a command in the TCL interpreter. This can be useful for accessing "
00052 "functionality that is not yet implemented via the Python interface.\n\n"
00053 "Args:\n"
00054 " command (str): TCL command to evaluate\n"
00055 "Returns:\n"
00056 " (str) Output from the TCL interpreter";
00057 static PyObject *py_evaltcl(PyObject *self, PyObject *args, PyObject *kwargs)
00058 {
00059 const char *kwnames[] = {"command", NULL};
00060 const char *cmd, *result;
00061 Tcl_Interp *interp;
00062 VMDApp *app;
00063
00064 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s:vmd.evaltcl",
00065 (char**) kwnames, &cmd))
00066 return NULL;
00067
00068 if (!(app = get_vmdapp()))
00069 return NULL;
00070
00071 interp = app->uiText->get_tcl_interp();
00072 int rc = Tcl_Eval(interp, cmd);
00073 result = Tcl_GetStringResult(interp);
00074
00075 if (rc != TCL_OK) {
00076 PyErr_SetString(PyExc_ValueError, result);
00077 return NULL;
00078 }
00079 return as_pystring(result);
00080 }
00081 #endif
00082
00083 static PyMethodDef VMDAppMethods [] = {
00084 {"VMDupdate", (PyCFunction) py_vmdupdate, METH_VARARGS },
00085 {"VMDexit", (PyCFunction) py_vmdexit, METH_VARARGS | METH_KEYWORDS, exit_doc },
00086 #ifdef VMDTCL
00087 {"VMDevaltcl", (PyCFunction) py_evaltcl, METH_VARARGS | METH_KEYWORDS, evaltcl_doc },
00088 {"evaltcl", (PyCFunction) py_evaltcl, METH_VARARGS | METH_KEYWORDS, evaltcl_doc},
00089 #endif
00090 { NULL, NULL }
00091 };
00092
00093 static VMDApp *the_app = NULL;
00094 static PyThreadState *event_tstate = NULL;
00095
00096 #if defined(VMD_SHARED)
00097 static int vmd_input_hook() {
00098 if (the_app) {
00099 the_app->VMDupdate(1);
00100 }
00101 PyEval_RestoreThread(event_tstate);
00102 PyRun_SimpleString(
00103 "try:\n"
00104 "\timport Tkinter\n"
00105 "\twhile Tkinter.tkinter.dooneevent(Tkinter.tkinter.DONT_WAIT):\n"
00106 "\t\tpass\n"
00107 "except:\n"
00108 "\tpass\n");
00109 PyEval_SaveThread();
00110 return 0;
00111 }
00112 #endif
00113
00114 static const char vmd_moddoc[] =
00115 "The main VMD python module. Provides access to the `evaltcl` method for "
00116 "accessing features not yet available in the Python interface. When VMD "
00117 "is built as a standalone Python module, the vmd module serves as an access "
00118 "point for all other modules, such as `vmd.molecule` for example";
00119
00120 #if PY_MAJOR_VERSION >= 3
00121 static struct PyModuleDef vmddef = {
00122 PyModuleDef_HEAD_INIT,
00123 "vmd",
00124 vmd_moddoc,
00125 -1,
00126 VMDAppMethods,
00127 };
00128
00129 #define INITERROR return NULL
00130 extern "C" PyObject* PyInit_vmd() {
00131 #else
00132 #define INITERROR return
00133 extern "C" void initvmd() {
00134 #endif
00135
00136
00137
00138
00139
00140
00141
00142 int mpienabled = 0;
00143
00144
00145
00146
00147
00148 if (get_vmdapp()) {
00149 #if PY_MAJOR_VERSION >= 3
00150 return PyModule_Create(&vmddef);
00151 #else
00152 (void)Py_InitModule3("vmd", VMDAppMethods, vmd_moddoc);
00153 return;
00154 #endif
00155 }
00156
00157 int argc = 1;
00158 char *argv[] = {(char*) Py_GetProgramFullPath()};
00159 char **argp = argv;
00160 if (!VMDinitialize(&argc, (char ***) &argp, mpienabled)) {
00161 INITERROR;
00162 }
00163
00164
00165
00166
00167 const char *disp = getenv("VMDDISPLAYDEVICE");
00168 if (!disp) disp = "text";
00169
00170 int loc[2] = { 50, 50 };
00171 int size[2] = { 400, 400 };
00172 VMDgetDisplayFrame(loc, size);
00173
00174 VMDApp *app = new VMDApp(1, argv, mpienabled);
00175 app->VMDinit(1, argv, disp, loc, size);
00176
00177
00178 VMDreadInit(app);
00179
00180
00181
00182
00183 #if 0
00184
00185 VMDreadStartup(app);
00186 #endif
00187
00188 set_vmdapp(app);
00189
00190
00191 the_app = app;
00192
00193 #if PY_MAJOR_VERSION >= 3
00194 PyObject *vmdmodule = PyModule_Create(&vmddef);
00195 #else
00196 PyObject *vmdmodule = Py_InitModule3("vmd", VMDAppMethods, vmd_moddoc);
00197 #endif
00198 if (!vmdmodule) {
00199 msgErr << "Failed to import vmd module" << sendmsg;
00200 PyErr_Print();
00201 INITERROR;
00202 }
00203
00204 int i = 0;
00205 while (py_initializers[i].name) {
00206 const char *name = py_initializers[i].name;
00207 PyObject *module = (*(py_initializers[i].initfunc))();
00208 if (!module) {
00209 msgErr << "Failed to initialize builtin module " << name << sendmsg;
00210 PyErr_Print();
00211 continue;
00212 }
00213
00214 int retval = PyModule_AddObject(vmdmodule, CAST_HACK name, module);
00215 if (retval || PyErr_Occurred()) {
00216 msgErr << "Failed to import builtin module " << name << sendmsg;
00217 msgErr << "Aborting module import" << sendmsg;
00218 INITERROR;
00219 }
00220 i++;
00221 }
00222
00223 event_tstate = PyThreadState_Get();
00224 #if defined(VMD_SHARED)
00225 PyOS_InputHook = vmd_input_hook;
00226 #endif
00227
00228 #if PY_MAJOR_VERSION >= 3
00229 return vmdmodule;
00230 #endif
00231 }
00232