Main Page   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-2008 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.62 $       $Date: 2008/03/27 19:36:45 $
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   }
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   // Some modules (like Tk) assume that os.argv has been initialized
00131   PySys_SetArgv(app->argc_m, (char **)app->argv_m);
00132 
00133   set_vmdapp(app);
00134 
00135   // Set up the prompts
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   // The VMD module imports all the above modules.
00165   evalString("import VMD");
00166 
00167   // have_tkinter and have_vmdcallback flags are set to zero if these calls
00168   // ever fail so that we don't fail over and over again and fill up the
00169   // screen with errors.
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   // Don't recursively call into dooneevent - it makes Tkinter crash for
00187   // some infathomable reason.
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; // success
00199     }
00200     // give up
00201     have_tkinter = 0;
00202   }
00203   return 0;
00204 }
00205   
00206 void PythonTextInterp::doEvent() {
00207   // Call any display loop callbacks
00208   // abort if the call ever fails
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     // Try to change to Tcl interpreter.  If that fails, UIText will
00224     // bounce us back to the Python interpreter again.
00225     app->textinterp_change("tcl");
00226   }
00227 }
00228 
00229 int PythonTextInterp::evalString(const char *s) {
00230   // evaluate the string in the interpreter
00231   // returns success.
00232   // XXX should print error message if there was one.
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     // if this is a user pick event, give it its own callback event
00267     // to discourage devs from inappropriately overloading all pick events
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 

Generated on Sat Aug 30 01:27:01 2008 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002