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 }
00088 for (int i=0; i<PyList_GET_SIZE(cblist); i++) {
00089 PyObject *obj = PyList_GET_ITEM(cblist, i);
00090 PyObject *result = PyEval_CallObject(obj, arglist);
00091 if (result == NULL) {
00092 PyErr_Print();
00093 PySequence_DelItem(cblist, i);
00094 i--;
00095 } else {
00096 Py_DECREF(result);
00097 }
00098 }
00099 Py_DECREF(arglist);
00100 }
00101
00102 static PyMethodDef CallbackMethods[] = {
00103 {(char *)"add_callback", (vmdPyMethod)add_callback, METH_VARARGS },
00104 {(char *)"del_callback", (vmdPyMethod)del_callback, METH_VARARGS },
00105 {NULL, NULL}
00106 };
00107
00108 static void initvmdcallbacks() {
00109 PyObject *m = Py_InitModule((char *)"vmdcallbacks", CallbackMethods);
00110 PyObject *dict = PyDict_New();
00111 PyDict_SetItemString(dict, (char *)"display_update", PyList_New(0));
00112 PyDict_SetItemString(dict, (char *)"frame", PyList_New(0));
00113 PyDict_SetItemString(dict, (char *)"initialize_structure", PyList_New(0));
00114 PyDict_SetItemString(dict, (char *)"molecule", PyList_New(0));
00115 PyDict_SetItemString(dict, (char *)"pick_atom", PyList_New(0));
00116 PyDict_SetItemString(dict, (char *)"pick_value", PyList_New(0));
00117 PyDict_SetItemString(dict, (char *)"timestep", PyList_New(0));
00118 PyDict_SetItemString(dict, (char *)"trajectory", PyList_New(0));
00119 PyDict_SetItemString(dict, (char *)"userkey", PyList_New(0));
00120 PyObject_SetAttrString(m, (char *)"callbacks", dict);
00121 cbdict = dict;
00122 }
00123
00124
00125 PythonTextInterp::PythonTextInterp(VMDApp *vmdapp)
00126 : app(vmdapp) {
00127 msgInfo << "Starting Python..." << sendmsg;
00128 Py_Initialize();
00129
00130
00131 PySys_SetArgv(app->argc_m, (char **)app->argv_m);
00132
00133 set_vmdapp(app);
00134
00135
00136 PySys_SetObject((char *)"ps1", PyString_FromString((char *)""));
00137 PySys_SetObject((char *)"ps2", PyString_FromString((char *)"... "));
00138
00139 initvmdcallbacks();
00140 #ifdef VMDSWIG
00141 initvmd();
00142 #endif
00143 initanimate();
00144 initatomselection();
00145 initatomsel();
00146 initaxes();
00147 initcolor();
00148 initdisplay();
00149 initgraphics();
00150 initimd();
00151 initlabel();
00152 initmaterial();
00153 initmolecule();
00154 initmolrep();
00155 initmouse();
00156 initrender();
00157 inittrans();
00158 initvmdmenu();
00159
00160 #ifdef VMDNUMPY
00161 initvmdnumpy();
00162 #endif
00163
00164
00165 evalString("import VMD");
00166
00167
00168
00169
00170 have_tkinter = 1;
00171 in_tk = 0;
00172 needPrompt = 1;
00173 }
00174
00175 PythonTextInterp::~PythonTextInterp() {
00176 Py_Finalize();
00177 msgInfo << "Done with Python." << sendmsg;
00178
00179 }
00180
00181 #ifdef VMDSWIG
00182 extern "C" void initvmd(void);
00183 #endif
00184
00185 int PythonTextInterp::doTkUpdate() {
00186
00187
00188 if (in_tk) return 0;
00189 if (have_tkinter) {
00190 in_tk = 1;
00191 int rc = evalString(
00192 "import Tkinter\n"
00193 "while Tkinter.tkinter.dooneevent(Tkinter.tkinter.DONT_WAIT):\n"
00194 "\tpass\n"
00195 );
00196 in_tk = 0;
00197 if (rc) {
00198 return 1;
00199 }
00200
00201 have_tkinter = 0;
00202 }
00203 return 0;
00204 }
00205
00206 void PythonTextInterp::doEvent() {
00207
00208
00209 PyObject *arglist = Py_BuildValue((char *)"()");
00210 call_callbacks("display_update", arglist);
00211
00212 if (needPrompt) {
00213 printf(">>> ");
00214 fflush(stdout);
00215 needPrompt = 0;
00216 }
00217
00218 if (!vmd_check_stdin())
00219 return;
00220 int code = PyRun_InteractiveOne(stdin, (char *)"VMD");
00221 needPrompt = 1;
00222 if (code == E_EOF) {
00223
00224
00225 app->textinterp_change("tcl");
00226 }
00227 }
00228
00229 int PythonTextInterp::evalString(const char *s) {
00230
00231
00232
00233 return !PyRun_SimpleString((char *)s);
00234 }
00235
00236 int PythonTextInterp::evalFile(const char *s) {
00237 FILE *fid = fopen(s, "r");
00238 if (!fid) {
00239 msgErr << "Error opening file '" << s << "'" << sendmsg;
00240 return FALSE;
00241 }
00242 int code = PyRun_SimpleFile(fid, (char *)"VMD");
00243 fclose(fid);
00244 return !code;
00245 }
00246
00247 void PythonTextInterp::frame_cb(int molid, int frame) {
00248 PyObject *arglist = Py_BuildValue((char *)"(i,i)", molid, frame);
00249 call_callbacks("frame", arglist);
00250 }
00251
00252 void PythonTextInterp::initialize_structure_cb(int molid, int code) {
00253 PyObject *arglist = Py_BuildValue((char *)"(i,i)", molid, code);
00254 call_callbacks("initialize_structure", arglist);
00255 }
00256
00257 void PythonTextInterp::molecule_changed_cb(int molid, int code) {
00258 PyObject *arglist = Py_BuildValue((char *)"(i,i)", molid, code);
00259 call_callbacks("molecule", arglist);
00260 }
00261
00262 void PythonTextInterp::pick_atom_cb(int mol, int atom, int key_shift_state, bool ispick) {
00263 PyObject *arglist = Py_BuildValue((char *)"(i,i,i)", mol, atom, key_shift_state);
00264 call_callbacks("pick_atom", arglist);
00265 if (ispick) {
00266
00267
00268 PyObject *arglist = Py_BuildValue((char *)"(i)", 1);
00269 call_callbacks("pick_event", arglist);
00270 }
00271 }
00272
00273 void PythonTextInterp::pick_value_cb(float val) {
00274 PyObject *arglist = Py_BuildValue((char *)"(f)", val);
00275 call_callbacks("pick_value", arglist);
00276 }
00277
00278 void PythonTextInterp::timestep_cb(int id, int frame) {
00279 PyObject *arglist = Py_BuildValue((char *)"(i,i)", id, frame);
00280 call_callbacks("timestep", arglist);
00281 }
00282
00283 void PythonTextInterp::trajectory_cb(int id, const char *name) {
00284 PyObject *arglist = Py_BuildValue((char *)"(i,s)", id, name);
00285 call_callbacks("trajectory", arglist);
00286 }
00287
00288 void PythonTextInterp::python_cb(const char *cmd) {
00289 evalString(cmd);
00290 }
00291
00292 void PythonTextInterp::userkey_cb(const char *keydesc) {
00293 PyObject *arglist = Py_BuildValue((char *)"(s)", keydesc);
00294 call_callbacks("userkey", arglist);
00295 }
00296