Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members   Related Pages  

PythonTextInterp.C

Go to the documentation of this file.
00001 /***************************************************************************
00002  *cr
00003  *cr            (C) Copyright 1995-2011 The Board of Trustees of the
00004  *cr                        University of Illinois
00005  *cr                         All Rights Reserved
00006  *cr
00007  ***************************************************************************/
00008 
00009 /***************************************************************************
00010  * RCS INFORMATION:
00011  *
00012  *      $RCSfile: PythonTextInterp.C,v $
00013  *      $Author: johns $        $Locker:  $             $State: Exp $
00014  *      $Revision: 1.66 $       $Date: 2010/12/16 04:08:36 $
00015  *
00016  ***************************************************************************
00017  * DESCRIPTION:
00018  *  Python text interpreter
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 // use the Apple-provided Python framework
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   /* The GIL must be held when callbacks are invoked, but we don't have
00091    * the GIL when Tk (as opposed to Tkinter) events come in.  This ensures
00092    * that we have the GIL in either case.
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   // Some modules (like Tk) assume that os.argv has been initialized
00144   PySys_SetArgv(app->argc_m, (char **)app->argv_m);
00145 
00146   set_vmdapp(app);
00147 
00148   // Set up the prompts
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   // The VMD module imports all the above modules.
00176   evalString("import VMD");
00177 
00178   // have_tkinter and have_vmdcallback flags are set to zero if these calls
00179   // ever fail so that we don't fail over and over again and fill up the
00180   // screen with errors.
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   // Don't recursively call into dooneevent - it makes Tkinter crash for
00194   // some infathomable reason.
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; // success
00206     }
00207     // give up
00208     have_tkinter = 0;
00209   }
00210   return 0;
00211 }
00212   
00213 void PythonTextInterp::doEvent() {
00214   // Call any display loop callbacks
00215   // abort if the call ever fails
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     // Try to change to Tcl interpreter.  If that fails, UIText will
00231     // bounce us back to the Python interpreter again.
00232     app->textinterp_change("tcl");
00233   }
00234 }
00235 
00236 int PythonTextInterp::evalString(const char *s) {
00237   // evaluate the string in the interpreter
00238   // returns success.
00239   // XXX should print error message if there was one.
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     // if this is a user pick event, give it its own callback event
00274     // to discourage devs from inappropriately overloading all pick events
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 

Generated on Tue May 22 01:48:08 2012 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002