00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "py_commands.h"
00022 #include "Inform.h"
00023 #include "PythonTextInterp.h"
00024 #include "config.h"
00025 #include "VMDApp.h"
00026 #include "TextEvent.h"
00027
00028 #if defined(__APPLE__)
00029
00030 #include "Python/errcode.h"
00031 #else
00032 #include "errcode.h"
00033 #endif
00034
00035 static PyObject *cbdict = NULL;
00036
00037 static PyObject *add_callback(PyObject *, PyObject *args) {
00038 char *type;
00039 PyObject *temp;
00040
00041 if (!PyArg_ParseTuple(args, (char *)"sO:add_callback", &type, &temp))
00042 return NULL;
00043
00044 if (!PyCallable_Check(temp)) {
00045 PyErr_SetString(PyExc_TypeError, "parameter must be callable");
00046 return NULL;
00047 }
00048 PyObject *cblist = PyDict_GetItemString(cbdict, type);
00049 if (!cblist) {
00050 PyErr_SetString(PyExc_KeyError, type);
00051 return NULL;
00052 }
00053 PyList_Append(cblist, temp);
00054 Py_INCREF(Py_None);
00055 return Py_None;
00056 }
00057
00058 static PyObject *del_callback(PyObject *, PyObject *args) {
00059 char *type;
00060 PyObject *temp;
00061
00062 if (!PyArg_ParseTuple(args, (char *)"sO:del_callback", &type, &temp))
00063 return NULL;
00064
00065 if (!PyCallable_Check(temp)) {
00066 PyErr_SetString(PyExc_TypeError, "parameter must be callable");
00067 return NULL;
00068 }
00069 PyObject *cblist = PyDict_GetItemString(cbdict, type);
00070 if (!cblist) {
00071 PyErr_SetString(PyExc_KeyError, type);
00072 return NULL;
00073 }
00074 int ind = PySequence_Index(cblist, temp);
00075 if (ind >= 0) {
00076 PySequence_DelItem(cblist, ind);
00077 }
00078 Py_INCREF(Py_None);
00079 return Py_None;
00080 }
00081
00082 static void call_callbacks(const char *type, PyObject *arglist) {
00083 PyObject *cblist = PyDict_GetItemString(cbdict, (char *)type);
00084 if (!cblist) {
00085 msgErr << "Internal error: callback list " << type << " does not exist."
00086 << sendmsg;
00087 return;
00088 }
00089
00090
00091
00092
00093
00094 PyGILState_STATE state = PyGILState_Ensure();
00095
00096 for (int i=0; i<PyList_GET_SIZE(cblist); i++) {
00097 PyObject *obj = PyList_GET_ITEM(cblist, i);
00098 PyObject *result = PyEval_CallObject(obj, arglist);
00099 if (result == NULL) {
00100 PyErr_Print();
00101 PySequence_DelItem(cblist, i);
00102 i--;
00103 } else {
00104 Py_DECREF(result);
00105 }
00106 }
00107 Py_DECREF(arglist);
00108
00109 PyGILState_Release(state);
00110 }
00111
00112 static PyMethodDef CallbackMethods[] = {
00113 {(char *)"add_callback", (vmdPyMethod)add_callback, METH_VARARGS },
00114 {(char *)"del_callback", (vmdPyMethod)del_callback, METH_VARARGS },
00115 {NULL, NULL}
00116 };
00117
00118 static void initvmdcallbacks() {
00119 PyObject *m = Py_InitModule((char *)"vmdcallbacks", CallbackMethods);
00120 PyObject *dict = PyDict_New();
00121 PyDict_SetItemString(dict, (char *)"display_update", PyList_New(0));
00122 PyDict_SetItemString(dict, (char *)"frame", PyList_New(0));
00123 PyDict_SetItemString(dict, (char *)"initialize_structure", PyList_New(0));
00124 PyDict_SetItemString(dict, (char *)"molecule", PyList_New(0));
00125 PyDict_SetItemString(dict, (char *)"pick_atom", PyList_New(0));
00126 PyDict_SetItemString(dict, (char *)"pick_event", PyList_New(0));
00127 PyDict_SetItemString(dict, (char *)"pick_value", PyList_New(0));
00128 PyDict_SetItemString(dict, (char *)"timestep", PyList_New(0));
00129 PyDict_SetItemString(dict, (char *)"trajectory", PyList_New(0));
00130 PyDict_SetItemString(dict, (char *)"userkey", PyList_New(0));
00131 PyObject_SetAttrString(m, (char *)"callbacks", dict);
00132 cbdict = dict;
00133 }
00134
00135 extern "C" void initvmd(void);
00136
00137
00138 PythonTextInterp::PythonTextInterp(VMDApp *vmdapp)
00139 : app(vmdapp) {
00140 msgInfo << "Starting Python..." << sendmsg;
00141 Py_Initialize();
00142
00143
00144 PySys_SetArgv(app->argc_m, (char **)app->argv_m);
00145
00146 set_vmdapp(app);
00147
00148
00149 PySys_SetObject((char *)"ps1", PyString_FromString((char *)""));
00150 PySys_SetObject((char *)"ps2", PyString_FromString((char *)"... "));
00151
00152 initvmdcallbacks();
00153 initvmd();
00154 initanimate();
00155 initatomselection();
00156 initatomsel();
00157 initaxes();
00158 initcolor();
00159 initdisplay();
00160 initgraphics();
00161 initimd();
00162 initlabel();
00163 initmaterial();
00164 initmolecule();
00165 initmolrep();
00166 initmouse();
00167 initrender();
00168 inittrans();
00169 initvmdmenu();
00170
00171 #ifdef VMDNUMPY
00172 initvmdnumpy();
00173 #endif
00174
00175
00176 evalString("import VMD");
00177
00178
00179
00180
00181 have_tkinter = 1;
00182 in_tk = 0;
00183 needPrompt = 1;
00184 }
00185
00186 PythonTextInterp::~PythonTextInterp() {
00187 Py_Finalize();
00188 msgInfo << "Done with Python." << sendmsg;
00189
00190 }
00191
00192 int PythonTextInterp::doTkUpdate() {
00193
00194
00195 if (in_tk) return 0;
00196 if (have_tkinter) {
00197 in_tk = 1;
00198 int rc = evalString(
00199 "import Tkinter\n"
00200 "while Tkinter.tkinter.dooneevent(Tkinter.tkinter.DONT_WAIT):\n"
00201 "\tpass\n"
00202 );
00203 in_tk = 0;
00204 if (rc) {
00205 return 1;
00206 }
00207
00208 have_tkinter = 0;
00209 }
00210 return 0;
00211 }
00212
00213 void PythonTextInterp::doEvent() {
00214
00215
00216 PyObject *arglist = Py_BuildValue((char *)"()");
00217 call_callbacks("display_update", arglist);
00218
00219 if (needPrompt) {
00220 printf(">>> ");
00221 fflush(stdout);
00222 needPrompt = 0;
00223 }
00224
00225 if (!vmd_check_stdin())
00226 return;
00227 int code = PyRun_InteractiveOne(stdin, (char *)"VMD");
00228 needPrompt = 1;
00229 if (code == E_EOF) {
00230
00231
00232 app->textinterp_change("tcl");
00233 }
00234 }
00235
00236 int PythonTextInterp::evalString(const char *s) {
00237
00238
00239
00240 return !PyRun_SimpleString((char *)s);
00241 }
00242
00243 int PythonTextInterp::evalFile(const char *s) {
00244 FILE *fid = fopen(s, "r");
00245 if (!fid) {
00246 msgErr << "Error opening file '" << s << "'" << sendmsg;
00247 return FALSE;
00248 }
00249 int code = PyRun_SimpleFile(fid, (char *)"VMD");
00250 fclose(fid);
00251 return !code;
00252 }
00253
00254 void PythonTextInterp::frame_cb(int molid, int frame) {
00255 PyObject *arglist = Py_BuildValue((char *)"(i,i)", molid, frame);
00256 call_callbacks("frame", arglist);
00257 }
00258
00259 void PythonTextInterp::initialize_structure_cb(int molid, int code) {
00260 PyObject *arglist = Py_BuildValue((char *)"(i,i)", molid, code);
00261 call_callbacks("initialize_structure", arglist);
00262 }
00263
00264 void PythonTextInterp::molecule_changed_cb(int molid, int code) {
00265 PyObject *arglist = Py_BuildValue((char *)"(i,i)", molid, code);
00266 call_callbacks("molecule", arglist);
00267 }
00268
00269 void PythonTextInterp::pick_atom_cb(int mol, int atom, int key_shift_state, bool ispick) {
00270 PyObject *arglist = Py_BuildValue((char *)"(i,i,i)", mol, atom, key_shift_state);
00271 call_callbacks("pick_atom", arglist);
00272 if (ispick) {
00273
00274
00275 PyObject *arglist = Py_BuildValue((char *)"(i)", 1);
00276 call_callbacks("pick_event", arglist);
00277 }
00278 }
00279
00280 void PythonTextInterp::pick_value_cb(float val) {
00281 PyObject *arglist = Py_BuildValue((char *)"(f)", val);
00282 call_callbacks("pick_value", arglist);
00283 }
00284
00285 void PythonTextInterp::timestep_cb(int id, int frame) {
00286 PyObject *arglist = Py_BuildValue((char *)"(i,i)", id, frame);
00287 call_callbacks("timestep", arglist);
00288 }
00289
00290 void PythonTextInterp::trajectory_cb(int id, const char *name) {
00291 PyObject *arglist = Py_BuildValue((char *)"(i,s)", id, name);
00292 call_callbacks("trajectory", arglist);
00293 }
00294
00295 void PythonTextInterp::python_cb(const char *cmd) {
00296 evalString(cmd);
00297 }
00298
00299 void PythonTextInterp::userkey_cb(const char *keydesc) {
00300 PyObject *arglist = Py_BuildValue((char *)"(s)", keydesc);
00301 call_callbacks("userkey", arglist);
00302 }
00303