1 | /* |
---|
2 | A* ------------------------------------------------------------------- |
---|
3 | B* This file contains source code for the PyMOL computer program |
---|
4 | C* copyright 1998-2000 by Warren Lyford Delano of DeLano Scientific. |
---|
5 | D* ------------------------------------------------------------------- |
---|
6 | E* It is unlawful to modify or remove this copyright notice. |
---|
7 | F* ------------------------------------------------------------------- |
---|
8 | G* Please see the accompanying LICENSE file for further information. |
---|
9 | H* ------------------------------------------------------------------- |
---|
10 | I* Additional authors of this source file include: |
---|
11 | -* |
---|
12 | -* |
---|
13 | -* |
---|
14 | Z* ------------------------------------------------------------------- |
---|
15 | */ |
---|
16 | |
---|
17 | /* meaning of defines |
---|
18 | |
---|
19 | _PYMOL_MONOLITHIC: means that we're building PyMOL and its Python C |
---|
20 | dependencies as one C library. That means we need to explicitly call |
---|
21 | the initialization functions for these libraries on startup. |
---|
22 | |
---|
23 | */ |
---|
24 | |
---|
25 | #ifndef _PYMOL_NOPY |
---|
26 | |
---|
27 | #include"os_predef.h" |
---|
28 | #include"Base.h" |
---|
29 | |
---|
30 | #define MAX_SAVED_THREAD ((PYMOL_MAX_THREADS)+3) |
---|
31 | |
---|
32 | |
---|
33 | /* BEGIN PROPRIETARY CODE SEGMENT (see disclaimer in "os_proprietary.h") */ |
---|
34 | #ifdef WIN32 |
---|
35 | #include<windows.h> |
---|
36 | #include<process.h> |
---|
37 | #include<winappc.h> |
---|
38 | #endif |
---|
39 | /* END PROPRIETARY CODE SEGMENT */ |
---|
40 | |
---|
41 | #include"os_python.h" |
---|
42 | |
---|
43 | #include"os_std.h" |
---|
44 | #include"os_time.h" |
---|
45 | #include"os_unix.h" |
---|
46 | |
---|
47 | #include"MemoryDebug.h" |
---|
48 | #include"Base.h" |
---|
49 | #include"Err.h" |
---|
50 | #include"P.h" |
---|
51 | #include"PConv.h" |
---|
52 | #include"Ortho.h" |
---|
53 | #include"Cmd.h" |
---|
54 | #include"main.h" |
---|
55 | #include"AtomInfo.h" |
---|
56 | #include"CoordSet.h" |
---|
57 | #include"Util.h" |
---|
58 | #include"Executive.h" |
---|
59 | #include"PyMOLOptions.h" |
---|
60 | #include"PyMOL.h" |
---|
61 | |
---|
62 | |
---|
63 | |
---|
64 | /* all of the following Python objects must be invariant & global for the application */ |
---|
65 | |
---|
66 | /* local to this C code module */ |
---|
67 | |
---|
68 | static PyObject *P_pymol = NULL; |
---|
69 | static PyObject *P_pymol_dict = NULL; /* must be refomed into globals and instance properties */ |
---|
70 | static PyObject *P_cmd = NULL; |
---|
71 | |
---|
72 | /* used elsewhere */ |
---|
73 | |
---|
74 | PyObject *P_menu = NULL; /* menu definitions are currently global */ |
---|
75 | PyObject *P_xray = NULL; /* okay as global */ |
---|
76 | PyObject *P_chempy = NULL; /* okay as global */ |
---|
77 | PyObject *P_models = NULL; /* okay as global */ |
---|
78 | PyObject *P_setting = NULL; /* must be reformed somehow */ |
---|
79 | PyObject *P_embed = NULL; |
---|
80 | |
---|
81 | /* local to this module */ |
---|
82 | |
---|
83 | static PyObject *P_povray = NULL; |
---|
84 | static PyObject *P_traceback = NULL; |
---|
85 | static PyObject *P_parser = NULL; |
---|
86 | |
---|
87 | static PyObject *P_lock = NULL; /* API locks */ |
---|
88 | static PyObject *P_lock_attempt = NULL; |
---|
89 | static PyObject *P_unlock = NULL; |
---|
90 | |
---|
91 | static PyObject *P_lock_c = NULL; /* C locks */ |
---|
92 | static PyObject *P_unlock_c = NULL; |
---|
93 | |
---|
94 | static PyObject *P_lock_status = NULL; /* status locks */ |
---|
95 | static PyObject *P_lock_status_attempt = NULL; /* status locks */ |
---|
96 | static PyObject *P_unlock_status = NULL; |
---|
97 | |
---|
98 | static PyObject *P_lock_glut = NULL; /* GLUT locks */ |
---|
99 | static PyObject *P_unlock_glut = NULL; |
---|
100 | |
---|
101 | /* BEGIN PROPRIETARY CODE SEGMENT (see disclaimer in "os_proprietary.h") */ |
---|
102 | #ifdef WIN32 |
---|
103 | static PyObject *P_time = NULL; |
---|
104 | static PyObject *P_sleep = NULL; |
---|
105 | #endif |
---|
106 | /* END PROPRIETARY CODE SEGMENT */ |
---|
107 | |
---|
108 | static PyObject *P_main = NULL; |
---|
109 | static PyObject *P_vfont = NULL; |
---|
110 | |
---|
111 | #define P_log_file_str "_log_file" |
---|
112 | |
---|
113 | #define xxxPYMOL_NEW_THREADS |
---|
114 | |
---|
115 | unsigned int PyThread_get_thread_ident(void); /* critical functionality */ |
---|
116 | |
---|
117 | typedef struct { |
---|
118 | int id; |
---|
119 | PyThreadState *state; |
---|
120 | } SavedThreadRec; |
---|
121 | |
---|
122 | void PRunStringModule(PyMOLGlobals *G,char *str); |
---|
123 | |
---|
124 | void PLockStatus(void) /* assumes we have the GIL */ |
---|
125 | { |
---|
126 | PXDecRef(PyObject_CallFunction(P_lock_status,NULL)); |
---|
127 | } |
---|
128 | |
---|
129 | int PLockStatusAttempt(void) /* assumes we have the GIL */ |
---|
130 | { |
---|
131 | int result = true; |
---|
132 | PyObject *got_lock = PyObject_CallFunction(P_lock_status_attempt,NULL); |
---|
133 | if(got_lock) { |
---|
134 | if(!PyInt_AsLong(got_lock)) { |
---|
135 | result = false; |
---|
136 | } |
---|
137 | Py_DECREF(got_lock); |
---|
138 | } |
---|
139 | return result; |
---|
140 | } |
---|
141 | void PUnlockStatus(void) /* assumes we have the GIL */ |
---|
142 | { |
---|
143 | PXDecRef(PyObject_CallFunction(P_unlock_status,NULL)); |
---|
144 | } |
---|
145 | |
---|
146 | static void PLockGLUT(void) /* assumes we have the GIL */ |
---|
147 | { |
---|
148 | PXDecRef(PyObject_CallFunction(P_lock_glut,NULL)); |
---|
149 | } |
---|
150 | |
---|
151 | static void PUnlockGLUT(void) /* assumes we have the GIL */ |
---|
152 | { |
---|
153 | PXDecRef(PyObject_CallFunction(P_unlock_glut,NULL)); |
---|
154 | } |
---|
155 | |
---|
156 | static SavedThreadRec SavedThread[MAX_SAVED_THREAD]; |
---|
157 | |
---|
158 | int P_glut_thread_keep_out = 0; |
---|
159 | unsigned int P_glut_thread_id; |
---|
160 | |
---|
161 | /* enables us to keep glut out if by chance it grabs the API |
---|
162 | * in the middle of a nested API based operation */ |
---|
163 | |
---|
164 | void PCatchInit(void); |
---|
165 | void my_interrupt(int a); |
---|
166 | char *getprogramname(void); |
---|
167 | |
---|
168 | /* |
---|
169 | PyObject *GetBondsDict(PyMOLGlobals *G) |
---|
170 | { |
---|
171 | PyObject *result = NULL; |
---|
172 | result = PyObject_GetAttrString(P_chempy,"bonds"); |
---|
173 | if(!result) ErrMessage(G,"PyMOL","can't find 'chempy.bonds.bonds'"); |
---|
174 | return(result); |
---|
175 | } |
---|
176 | */ |
---|
177 | |
---|
178 | PyObject *PGetFontDict(PyMOLGlobals *G, float size,int face,int style) |
---|
179 | { /* assumes we have a valid interpreter lock */ |
---|
180 | PyObject *result = NULL; |
---|
181 | |
---|
182 | if(!P_vfont) { |
---|
183 | PRunStringModule(G,"import vfont\n"); |
---|
184 | P_vfont = PyDict_GetItemString(P_pymol_dict,"vfont"); |
---|
185 | } |
---|
186 | if(!P_vfont) { |
---|
187 | PRINTFB(G,FB_Python,FB_Errors) |
---|
188 | " PyMOL-Error: can't find module 'vfont'" |
---|
189 | ENDFB(G); |
---|
190 | } |
---|
191 | else { |
---|
192 | result = PyObject_CallMethod(P_vfont,"get_font","fii",size,face,style); |
---|
193 | } |
---|
194 | return(PConvAutoNone(result)); |
---|
195 | } |
---|
196 | |
---|
197 | int PComplete(PyMOLGlobals *G,char *str,int buf_size) |
---|
198 | { |
---|
199 | int ret = false; |
---|
200 | PyObject *result; |
---|
201 | char *st2; |
---|
202 | PBlockAndUnlockAPI(G); |
---|
203 | if(G->P_inst->complete) { |
---|
204 | result = PyObject_CallFunction(G->P_inst->complete,"s",str); |
---|
205 | if(result) { |
---|
206 | if(PyString_Check(result)) { |
---|
207 | st2 = PyString_AsString(result); |
---|
208 | UtilNCopy(str,st2,buf_size); |
---|
209 | ret=true; |
---|
210 | } |
---|
211 | Py_DECREF(result); |
---|
212 | } |
---|
213 | } |
---|
214 | PLockAPIAndUnblock(G); |
---|
215 | return(ret); |
---|
216 | } |
---|
217 | |
---|
218 | int PTruthCallStr0(PyObject *object,char *method) |
---|
219 | { |
---|
220 | int result = false; |
---|
221 | PyObject *tmp; |
---|
222 | tmp = PyObject_CallMethod(object,method,""); |
---|
223 | if(tmp) { |
---|
224 | if(PyObject_IsTrue(tmp)) |
---|
225 | result = 1; |
---|
226 | Py_DECREF(tmp); |
---|
227 | } |
---|
228 | return(result); |
---|
229 | } |
---|
230 | |
---|
231 | |
---|
232 | int PTruthCallStr(PyObject *object,char *method,char *argument) |
---|
233 | { |
---|
234 | int result = false; |
---|
235 | PyObject *tmp; |
---|
236 | tmp = PyObject_CallMethod(object,method,"s",argument); |
---|
237 | if(tmp) { |
---|
238 | if(PyObject_IsTrue(tmp)) |
---|
239 | result = 1; |
---|
240 | Py_DECREF(tmp); |
---|
241 | } |
---|
242 | return(result); |
---|
243 | } |
---|
244 | |
---|
245 | int PTruthCallStr1i(PyObject *object,char *method,int argument) |
---|
246 | { |
---|
247 | int result = false; |
---|
248 | PyObject *tmp; |
---|
249 | tmp = PyObject_CallMethod(object,method,"i",argument); |
---|
250 | if(tmp) { |
---|
251 | if(PyObject_IsTrue(tmp)) |
---|
252 | result = 1; |
---|
253 | Py_DECREF(tmp); |
---|
254 | } |
---|
255 | return(result); |
---|
256 | } |
---|
257 | int PTruthCallStr4i(PyObject *object,char *method,int a1,int a2,int a3,int a4) |
---|
258 | { |
---|
259 | int result = false; |
---|
260 | PyObject *tmp; |
---|
261 | tmp = PyObject_CallMethod(object,method,"iiii",a1,a2,a3,a4); |
---|
262 | if(tmp) { |
---|
263 | if(PyObject_IsTrue(tmp)) |
---|
264 | result = 1; |
---|
265 | Py_DECREF(tmp); |
---|
266 | } |
---|
267 | return(result); |
---|
268 | } |
---|
269 | |
---|
270 | void PXDecRef(PyObject *obj) |
---|
271 | { |
---|
272 | Py_XDECREF(obj); |
---|
273 | } |
---|
274 | |
---|
275 | void PSleepWhileBusy(PyMOLGlobals *G,int usec) |
---|
276 | { |
---|
277 | #ifndef WIN32 |
---|
278 | struct timeval tv; |
---|
279 | PRINTFD(G,FB_Threads) |
---|
280 | " PSleep-DEBUG: napping.\n" |
---|
281 | ENDFD; |
---|
282 | tv.tv_sec=0; |
---|
283 | tv.tv_usec=usec; |
---|
284 | select(0,NULL,NULL,NULL,&tv); |
---|
285 | PRINTFD(G,FB_Threads) |
---|
286 | " PSleep-DEBUG: nap over.\n" |
---|
287 | ENDFD; |
---|
288 | #else |
---|
289 | /* BEGIN PROPRIETARY CODE SEGMENT (see disclaimer in "os_proprietary.h") */ |
---|
290 | PBlock(G); |
---|
291 | PXDecRef(PyObject_CallFunction(P_sleep,"f",usec/1000000.0)); |
---|
292 | PUnblock(G); |
---|
293 | /* END PROPRIETARY CODE SEGMENT */ |
---|
294 | #endif |
---|
295 | } |
---|
296 | |
---|
297 | void PSleepUnlocked(PyMOLGlobals *G,int usec) |
---|
298 | { /* can only be called by the glut process */ |
---|
299 | #ifndef WIN32 |
---|
300 | fd_set fds; /* Sleep Interruption Patch *NJK* */ |
---|
301 | struct timeval tv; |
---|
302 | PRINTFD(G,FB_Threads) |
---|
303 | " PSleep-DEBUG: napping.\n" |
---|
304 | ENDFD; |
---|
305 | tv.tv_sec=0; |
---|
306 | tv.tv_usec=usec; |
---|
307 | /* Sleep Interruption Patch *NJK* */ |
---|
308 | FD_ZERO(&fds); |
---|
309 | FD_SET(TempPyMOLGlobals->CmdPipe[0],&fds); |
---|
310 | select(TempPyMOLGlobals->CmdPipe[0]+1,&fds,NULL,NULL,&tv); |
---|
311 | if (FD_ISSET(TempPyMOLGlobals->CmdPipe[0],&fds)) { |
---|
312 | char c; |
---|
313 | read(TempPyMOLGlobals->CmdPipe[0],&c,1); |
---|
314 | } |
---|
315 | PRINTFD(G,FB_Threads) |
---|
316 | " PSleep-DEBUG: nap over.\n" |
---|
317 | ENDFD; |
---|
318 | #else |
---|
319 | /* BEGIN PROPRIETARY CODE SEGMENT (see disclaimer in "os_proprietary.h") */ |
---|
320 | PBlock(G); |
---|
321 | PXDecRef(PyObject_CallFunction(P_sleep,"f",usec/1000000.0)); |
---|
322 | PUnblock(G); |
---|
323 | /* END PROPRIETARY CODE SEGMENT */ |
---|
324 | #endif |
---|
325 | } |
---|
326 | |
---|
327 | void PSleep(PyMOLGlobals *G,int usec) |
---|
328 | { /* can only be called by the glut process */ |
---|
329 | #ifndef WIN32 |
---|
330 | struct timeval tv; |
---|
331 | PUnlockAPIAsGlut(G); |
---|
332 | PRINTFD(G,FB_Threads) |
---|
333 | " PSleep-DEBUG: napping.\n" |
---|
334 | ENDFD; |
---|
335 | tv.tv_sec=0; |
---|
336 | tv.tv_usec=usec; |
---|
337 | select(0,NULL,NULL,NULL,&tv); |
---|
338 | PRINTFD(G,FB_Threads) |
---|
339 | " PSleep-DEBUG: nap over.\n" |
---|
340 | ENDFD; |
---|
341 | PLockAPIAsGlut(G,true); |
---|
342 | #else |
---|
343 | /* BEGIN PROPRIETARY CODE SEGMENT (see disclaimer in "os_proprietary.h") */ |
---|
344 | PBlockAndUnlockAPI(G); |
---|
345 | PXDecRef(PyObject_CallFunction(P_sleep,"f",usec/1000000.0)); |
---|
346 | PLockAPIAndUnblock(G); |
---|
347 | /* END PROPRIETARY CODE SEGMENT */ |
---|
348 | #endif |
---|
349 | |
---|
350 | } |
---|
351 | |
---|
352 | static PyObject *PCatchWrite(PyObject *self, PyObject *args); |
---|
353 | |
---|
354 | void my_interrupt(int a) |
---|
355 | { |
---|
356 | exit(EXIT_FAILURE); |
---|
357 | } |
---|
358 | |
---|
359 | void PDumpTraceback(PyObject *err) |
---|
360 | { |
---|
361 | PyObject_CallMethod(P_traceback,"print_tb","O",err); |
---|
362 | } |
---|
363 | |
---|
364 | void PDumpException() |
---|
365 | { |
---|
366 | PyObject_CallMethod(P_traceback,"print_exc",""); |
---|
367 | } |
---|
368 | |
---|
369 | int PAlterAtomState(PyMOLGlobals *G,float *v,char *expr,int read_only, |
---|
370 | AtomInfoType *at,char *model,int index, |
---|
371 | PyObject *space) |
---|
372 | /* assumes Blocked python interpreter*/ |
---|
373 | { |
---|
374 | PyObject *dict; |
---|
375 | int result=true; |
---|
376 | float f[3]; |
---|
377 | PyObject *x_id1,*x_id2=NULL,*y_id1,*y_id2=NULL,*z_id1,*z_id2=NULL; |
---|
378 | char atype[7]; |
---|
379 | PyObject *flags_id1=NULL,*flags_id2=NULL; |
---|
380 | int flags; |
---|
381 | dict = PyDict_New(); |
---|
382 | |
---|
383 | if(at) { |
---|
384 | if(at->hetatm) |
---|
385 | strcpy(atype,"HETATM"); |
---|
386 | else |
---|
387 | strcpy(atype,"ATOM"); |
---|
388 | |
---|
389 | /* immutables */ |
---|
390 | PConvStringToPyDictItem(dict,"model",model); |
---|
391 | PConvIntToPyDictItem(dict,"index",index+1); |
---|
392 | |
---|
393 | PConvStringToPyDictItem(dict,"type",atype); |
---|
394 | PConvStringToPyDictItem(dict,"name",at->name); |
---|
395 | PConvStringToPyDictItem(dict,"resn",at->resn); |
---|
396 | PConvStringToPyDictItem(dict,"resi",at->resi); |
---|
397 | PConvIntToPyDictItem(dict,"resv",at->resv); /* subordinate to resi */ |
---|
398 | PConvStringToPyDictItem(dict,"chain",at->chain); |
---|
399 | PConvStringToPyDictItem(dict,"alt",at->alt); |
---|
400 | PConvStringToPyDictItem(dict,"segi",at->segi); |
---|
401 | PConvStringToPyDictItem(dict,"elem",at->elem); |
---|
402 | PConvStringToPyDictItem(dict,"ss",at->ssType); |
---|
403 | |
---|
404 | { |
---|
405 | char null_st[1] = ""; |
---|
406 | char *st = null_st; |
---|
407 | |
---|
408 | if(at->textType) st = OVLexicon_FetchCString(G->Lexicon,at->textType); |
---|
409 | PConvStringToPyDictItem(dict,"text_type",st); |
---|
410 | |
---|
411 | st = null_st; |
---|
412 | if(at->label) st = OVLexicon_FetchCString(G->Lexicon,at->label); |
---|
413 | PConvStringToPyDictItem(dict,"label",st); |
---|
414 | } |
---|
415 | PConvIntToPyDictItem(dict,"numeric_type",at->customType); |
---|
416 | PConvFloatToPyDictItem(dict,"q",at->q); |
---|
417 | PConvFloatToPyDictItem(dict,"b",at->b); |
---|
418 | PConvFloatToPyDictItem(dict,"vdw",at->vdw); |
---|
419 | PConvFloatToPyDictItem(dict,"elec_radius",at->elec_radius); |
---|
420 | PConvFloatToPyDictItem(dict,"partial_charge",at->partialCharge); |
---|
421 | PConvIntToPyDictItem(dict,"formal_charge",at->formalCharge); |
---|
422 | PConvIntToPyDictItem(dict,"cartoon",at->cartoon); |
---|
423 | PConvIntToPyDictItem(dict,"color",at->color); |
---|
424 | PConvIntToPyDictItem(dict,"ID",at->id); |
---|
425 | PConvIntToPyDictItem(dict,"rank",at->rank); |
---|
426 | |
---|
427 | /* mutables */ |
---|
428 | flags_id1 = PConvIntToPyDictItem(dict,"flags",at->flags); |
---|
429 | } |
---|
430 | x_id1 = PConvFloatToPyDictItem(dict,"x",v[0]); |
---|
431 | y_id1 = PConvFloatToPyDictItem(dict,"y",v[1]); |
---|
432 | z_id1 = PConvFloatToPyDictItem(dict,"z",v[2]); |
---|
433 | PXDecRef(PyRun_String(expr,Py_single_input,space,dict)); |
---|
434 | if(PyErr_Occurred()) { |
---|
435 | PyErr_Print(); |
---|
436 | result=false; |
---|
437 | } else if(!read_only) { |
---|
438 | if(result) { |
---|
439 | if(!(x_id2 = PyDict_GetItemString(dict,"x"))) |
---|
440 | result=false; |
---|
441 | else if(!(y_id2 = PyDict_GetItemString(dict,"y"))) |
---|
442 | result=false; |
---|
443 | else if(!(z_id2 = PyDict_GetItemString(dict,"z"))) |
---|
444 | result=false; |
---|
445 | else if(at) { |
---|
446 | if(!(flags_id2 = PyDict_GetItemString(dict,"flags"))) |
---|
447 | result=false; |
---|
448 | } |
---|
449 | if(PyErr_Occurred()) { |
---|
450 | PyErr_Print(); |
---|
451 | result=false; |
---|
452 | ErrMessage(G,"AlterState","Aborting on error. Assignment may be incomplete."); |
---|
453 | } |
---|
454 | } |
---|
455 | if(result) { |
---|
456 | f[0]=(float)PyFloat_AsDouble(x_id2); |
---|
457 | f[1]=(float)PyFloat_AsDouble(y_id2); |
---|
458 | f[2]=(float)PyFloat_AsDouble(z_id2); |
---|
459 | if(at) |
---|
460 | if(flags_id1!=flags_id2) { |
---|
461 | if(!PConvPyObjectToInt(flags_id2,&flags)) |
---|
462 | result=false; |
---|
463 | else |
---|
464 | at->flags = flags; |
---|
465 | } |
---|
466 | if(PyErr_Occurred()) { |
---|
467 | PyErr_Print(); |
---|
468 | result=false; |
---|
469 | ErrMessage(G,"AlterState","Aborting on error. Assignment may be incomplete."); |
---|
470 | } else { |
---|
471 | v[0]=f[0]; |
---|
472 | v[1]=f[1]; |
---|
473 | v[2]=f[2]; |
---|
474 | } |
---|
475 | } |
---|
476 | |
---|
477 | } |
---|
478 | Py_DECREF(dict); |
---|
479 | return result; |
---|
480 | } |
---|
481 | |
---|
482 | int PAlterAtom(PyMOLGlobals *G, |
---|
483 | AtomInfoType *at,char *expr,int read_only, |
---|
484 | char *model,int index,PyObject *space) |
---|
485 | { |
---|
486 | /* assumes Blocked python interpreter*/ |
---|
487 | WordType buf; |
---|
488 | AtomName name; |
---|
489 | PyObject *name_id1,*name_id2=NULL; |
---|
490 | AtomName elem; |
---|
491 | PyObject *elem_id1,*elem_id2=NULL; |
---|
492 | ResName resn; |
---|
493 | PyObject *resn_id1,*resn_id2=NULL; |
---|
494 | ResIdent resi; |
---|
495 | PyObject *resi_id1,*resi_id2=NULL; |
---|
496 | int resv; |
---|
497 | PyObject *resv_id1,*resv_id2=NULL; |
---|
498 | Chain chain; |
---|
499 | PyObject *chain_id1,*chain_id2=NULL; |
---|
500 | Chain alt; |
---|
501 | PyObject *alt_id1,*alt_id2=NULL; |
---|
502 | SegIdent segi; |
---|
503 | PyObject *flags_id1,*flags_id2=NULL; |
---|
504 | int flags; |
---|
505 | PyObject *segi_id1,*segi_id2=NULL; |
---|
506 | PyObject *text_type_id1,*text_type_id2=NULL; |
---|
507 | SSType ssType; |
---|
508 | PyObject *ss_id1,*ss_id2=NULL; |
---|
509 | char atype[7]; |
---|
510 | PyObject *type_id1,*type_id2=NULL; |
---|
511 | float b,q,partialCharge,vdw,elec_radius; |
---|
512 | PyObject *b_id1,*b_id2=NULL; |
---|
513 | PyObject *q_id1,*q_id2=NULL; |
---|
514 | PyObject *partial_charge_id1,*partial_charge_id2=NULL; |
---|
515 | PyObject *vdw_id1,*vdw_id2=NULL; |
---|
516 | PyObject *elec_radius_id1,*elec_radius_id2=NULL; |
---|
517 | int formalCharge,numericType; |
---|
518 | PyObject *formal_charge_id1,*formal_charge_id2=NULL; |
---|
519 | PyObject *numeric_type_id1,*numeric_type_id2=NULL; |
---|
520 | int cartoon; |
---|
521 | PyObject *cartoon_id1,*cartoon_id2=NULL; |
---|
522 | int color; |
---|
523 | PyObject *color_id1,*color_id2=NULL; |
---|
524 | PyObject *label_id1,*label_id2=NULL; |
---|
525 | int id; |
---|
526 | PyObject *ID_id1,*ID_id2=NULL; |
---|
527 | int rank; |
---|
528 | PyObject *rank_id1,*rank_id2=NULL; |
---|
529 | PyObject *state_id1,*state_id2=NULL; |
---|
530 | int state; |
---|
531 | PyObject *dict; |
---|
532 | int result=true; |
---|
533 | |
---|
534 | if(at->hetatm) |
---|
535 | strcpy(atype,"HETATM"); |
---|
536 | else |
---|
537 | strcpy(atype,"ATOM"); |
---|
538 | |
---|
539 | /* PBlockAndUnlockAPI() is not safe, thus these |
---|
540 | * expressions must not call the PyMOL API... |
---|
541 | * what if "at" is destroyed by another thread? */ |
---|
542 | |
---|
543 | dict = PyDict_New(); |
---|
544 | |
---|
545 | /* immutables */ |
---|
546 | PConvStringToPyDictItem(dict,"model",model); |
---|
547 | PConvIntToPyDictItem(dict,"index",index+1); |
---|
548 | |
---|
549 | /* mutables */ |
---|
550 | type_id1 = PConvStringToPyDictItem(dict,"type",atype); |
---|
551 | name_id1 = PConvStringToPyDictItem(dict,"name",at->name); |
---|
552 | resn_id1 = PConvStringToPyDictItem(dict,"resn",at->resn); |
---|
553 | flags_id1 = PConvIntToPyDictItem(dict,"flags",at->flags); |
---|
554 | resi_id1 = PConvStringToPyDictItem(dict,"resi",at->resi); |
---|
555 | resv_id1 = PConvIntToPyDictItem(dict,"resv",at->resv); /* subordinate to resi */ |
---|
556 | chain_id1 = PConvStringToPyDictItem(dict,"chain",at->chain); |
---|
557 | alt_id1 = PConvStringToPyDictItem(dict,"alt",at->alt); |
---|
558 | segi_id1 = PConvStringToPyDictItem(dict,"segi",at->segi); |
---|
559 | elem_id1 = PConvStringToPyDictItem(dict,"elem",at->elem); |
---|
560 | ss_id1 = PConvStringToPyDictItem(dict,"ss",at->ssType); |
---|
561 | numeric_type_id1 = PConvIntToPyDictItem(dict,"numeric_type",at->customType); |
---|
562 | q_id1 = PConvFloatToPyDictItem(dict,"q",at->q); |
---|
563 | b_id1 = PConvFloatToPyDictItem(dict,"b",at->b); |
---|
564 | vdw_id1 = PConvFloatToPyDictItem(dict,"vdw",at->vdw); |
---|
565 | elec_radius_id1 = PConvFloatToPyDictItem(dict,"elec_radius",at->elec_radius); |
---|
566 | partial_charge_id1 = PConvFloatToPyDictItem(dict,"partial_charge",at->partialCharge); |
---|
567 | formal_charge_id1 = PConvIntToPyDictItem(dict,"formal_charge",at->formalCharge); |
---|
568 | cartoon_id1 = PConvIntToPyDictItem(dict,"cartoon",at->cartoon); |
---|
569 | |
---|
570 | { |
---|
571 | char null_st[1] = ""; |
---|
572 | char *st = null_st; |
---|
573 | |
---|
574 | if(at->textType) st = OVLexicon_FetchCString(G->Lexicon,at->textType); |
---|
575 | text_type_id1 = PConvStringToPyDictItem(dict,"text_type",st); |
---|
576 | |
---|
577 | st = null_st; |
---|
578 | if(at->label) st = OVLexicon_FetchCString(G->Lexicon,at->label); |
---|
579 | label_id1 = PConvStringToPyDictItem(dict,"label",st); |
---|
580 | } |
---|
581 | |
---|
582 | color_id1 = PConvIntToPyDictItem(dict,"color",at->color); |
---|
583 | ID_id1 = PConvIntToPyDictItem(dict,"ID",at->id); |
---|
584 | state_id1 = PConvIntToPyDictItem(dict,"state",at->discrete_state); |
---|
585 | rank_id1 = PConvIntToPyDictItem(dict,"rank",at->rank); |
---|
586 | |
---|
587 | PXDecRef(PyRun_String(expr,Py_single_input,space,dict)); |
---|
588 | if(PyErr_Occurred()) { |
---|
589 | ErrMessage(G,"Alter","Aborting on error. Assignment may be incomplete."); |
---|
590 | PyErr_Print(); |
---|
591 | result=false; |
---|
592 | } else if(read_only) { |
---|
593 | result=true; |
---|
594 | } if(PyErr_Occurred()) { |
---|
595 | PyErr_Print(); |
---|
596 | result=false; |
---|
597 | } else if(!read_only) { |
---|
598 | |
---|
599 | if(result) { |
---|
600 | /* get new object IDs */ |
---|
601 | |
---|
602 | if(!(type_id2 = PyDict_GetItemString(dict,"type"))) |
---|
603 | result=false; |
---|
604 | else if(!(name_id2 = PyDict_GetItemString(dict,"name"))) |
---|
605 | result=false; |
---|
606 | else if(!(elem_id2 = PyDict_GetItemString(dict,"elem"))) |
---|
607 | result=false; |
---|
608 | else if(!(resn_id2 = PyDict_GetItemString(dict,"resn"))) |
---|
609 | result=false; |
---|
610 | else if(!(flags_id2 = PyDict_GetItemString(dict,"flags"))) |
---|
611 | result=false; |
---|
612 | else if(!(resi_id2 = PyDict_GetItemString(dict,"resi"))) |
---|
613 | result=false; |
---|
614 | else if(!(resv_id2 = PyDict_GetItemString(dict,"resv"))) |
---|
615 | result=false; |
---|
616 | else if(!(segi_id2 = PyDict_GetItemString(dict,"segi"))) |
---|
617 | result=false; |
---|
618 | else if(!(alt_id2 = PyDict_GetItemString(dict,"alt"))) |
---|
619 | result=false; |
---|
620 | else if(!(chain_id2 = PyDict_GetItemString(dict,"chain"))) |
---|
621 | result=false; |
---|
622 | else if(!(text_type_id2 = PyDict_GetItemString(dict,"text_type"))) |
---|
623 | result=false; |
---|
624 | else if(!(ss_id2 = PyDict_GetItemString(dict,"ss"))) |
---|
625 | result=false; |
---|
626 | else if(!(b_id2 = PyDict_GetItemString(dict,"b"))) |
---|
627 | result=false; |
---|
628 | else if(!(q_id2 = PyDict_GetItemString(dict,"q"))) |
---|
629 | result=false; |
---|
630 | else if(!(vdw_id2=PyDict_GetItemString(dict,"vdw"))) |
---|
631 | result=false; |
---|
632 | else if(!(elec_radius_id2=PyDict_GetItemString(dict,"elec_radius"))) |
---|
633 | result=false; |
---|
634 | else if(!(partial_charge_id2 = PyDict_GetItemString(dict,"partial_charge"))) |
---|
635 | result=false; |
---|
636 | else if(!(formal_charge_id2 = PyDict_GetItemString(dict,"formal_charge"))) |
---|
637 | result=false; |
---|
638 | else if(!(cartoon_id2 = PyDict_GetItemString(dict,"cartoon"))) |
---|
639 | result=false; |
---|
640 | else if(!(color_id2=PyDict_GetItemString(dict,"color"))) |
---|
641 | result=false; |
---|
642 | else if(!(label_id2=PyDict_GetItemString(dict,"label"))) |
---|
643 | result=false; |
---|
644 | if(!(numeric_type_id2 = PyDict_GetItemString(dict,"numeric_type"))) |
---|
645 | result=false; |
---|
646 | if(!(ID_id2 = PyDict_GetItemString(dict,"ID"))) |
---|
647 | result=false; |
---|
648 | if(!(state_id2 = PyDict_GetItemString(dict,"state"))) |
---|
649 | result=false; |
---|
650 | if(!(rank_id2 = PyDict_GetItemString(dict,"rank"))) |
---|
651 | result=false; |
---|
652 | |
---|
653 | if(PyErr_Occurred()) { |
---|
654 | PyErr_Print(); |
---|
655 | result=false; |
---|
656 | } |
---|
657 | } |
---|
658 | if(result) { |
---|
659 | if(type_id1!=type_id2) { |
---|
660 | if(!PConvPyObjectToStrMaxLen(type_id2,atype,6)) |
---|
661 | result=false; |
---|
662 | else |
---|
663 | at->hetatm=((atype[0]=='h')||(atype[0]=='H')); |
---|
664 | } |
---|
665 | if(name_id1!=name_id2) { |
---|
666 | if(!PConvPyObjectToStrMaxLen(name_id2,name,sizeof(AtomName)-1)) |
---|
667 | result=false; |
---|
668 | else |
---|
669 | strcpy(at->name,name); |
---|
670 | } |
---|
671 | if(elem_id1!=elem_id2) { |
---|
672 | if(!PConvPyObjectToStrMaxLen(elem_id2,elem,sizeof(AtomName)-1)) |
---|
673 | result=false; |
---|
674 | else { |
---|
675 | strcpy(at->elem,elem); |
---|
676 | AtomInfoAssignParameters(G,at); |
---|
677 | } |
---|
678 | } |
---|
679 | if(resn_id1!=resn_id2) { |
---|
680 | if(!PConvPyObjectToStrMaxLen(resn_id2,resn,sizeof(ResName)-1)) |
---|
681 | result=false; |
---|
682 | else |
---|
683 | strcpy(at->resn,resn); |
---|
684 | } |
---|
685 | if(resi_id1!=resi_id2) { |
---|
686 | if(!PConvPyObjectToStrMaxLen(resi_id2,resi,sizeof(ResIdent)-1)) |
---|
687 | result=false; |
---|
688 | else { |
---|
689 | if(strcmp(at->resi,resi)!=0) |
---|
690 | at->resv=AtomResvFromResi(resi); |
---|
691 | strcpy(at->resi,resi); |
---|
692 | } |
---|
693 | } else if (resv_id1!=resv_id2) { |
---|
694 | if(!PConvPyObjectToInt(resv_id2,&resv)) |
---|
695 | result=false; |
---|
696 | else { |
---|
697 | sprintf(buf,"%d",resv); |
---|
698 | buf[sizeof(ResIdent)-1]=0; |
---|
699 | strcpy(at->resi,buf); |
---|
700 | } |
---|
701 | |
---|
702 | } |
---|
703 | if(segi_id1!=segi_id2) { |
---|
704 | if(!PConvPyObjectToStrMaxLen(segi_id2,segi,sizeof(SegIdent)-1)) |
---|
705 | result=false; |
---|
706 | else |
---|
707 | strcpy(at->segi,segi); |
---|
708 | |
---|
709 | } |
---|
710 | if(chain_id1!=chain_id2) { |
---|
711 | if(!PConvPyObjectToStrMaxLen(chain_id2,chain,sizeof(Chain)-1)) |
---|
712 | result=false; |
---|
713 | else |
---|
714 | strcpy(at->chain,chain); |
---|
715 | } |
---|
716 | if(alt_id1!=alt_id2) { |
---|
717 | if(!PConvPyObjectToStrMaxLen(alt_id2,alt,sizeof(Chain)-1)) |
---|
718 | result=false; |
---|
719 | else |
---|
720 | strcpy(at->alt,alt); |
---|
721 | } |
---|
722 | if(text_type_id1!=text_type_id2) { |
---|
723 | |
---|
724 | OrthoLineType temp; |
---|
725 | if(at->textType) { |
---|
726 | OVLexicon_DecRef(G->Lexicon,at->textType); |
---|
727 | } |
---|
728 | at->textType = 0; |
---|
729 | |
---|
730 | if(PConvPyObjectToStrMaxLen(text_type_id2,temp,sizeof(OrthoLineType)-1)) { |
---|
731 | if(temp[0]) { |
---|
732 | OVreturn_word result = OVLexicon_GetFromCString(G->Lexicon,temp); |
---|
733 | if(OVreturn_IS_OK(result)) { |
---|
734 | at->textType = result.word; |
---|
735 | } |
---|
736 | } |
---|
737 | } |
---|
738 | } |
---|
739 | if(ss_id1!=ss_id2) { |
---|
740 | if(!PConvPyObjectToStrMaxLen(ss_id2,ssType,sizeof(SSType)-1)) |
---|
741 | result=false; |
---|
742 | else { |
---|
743 | strcpy(at->ssType,ssType); |
---|
744 | at->ssType[0] = toupper(at->ssType[0]); |
---|
745 | } |
---|
746 | } |
---|
747 | if(b_id1!=b_id2) { |
---|
748 | if(!PConvPyObjectToFloat(b_id2,&b)) |
---|
749 | result=false; |
---|
750 | else |
---|
751 | at->b=b; |
---|
752 | } |
---|
753 | if(q_id1!=q_id2) { |
---|
754 | if(!PConvPyObjectToFloat(q_id2,&q)) |
---|
755 | result=false; |
---|
756 | else |
---|
757 | at->q=q; |
---|
758 | } |
---|
759 | if(vdw_id1!=vdw_id2) { |
---|
760 | if(!PConvPyObjectToFloat(vdw_id2,&vdw)) |
---|
761 | result=false; |
---|
762 | else |
---|
763 | at->vdw=vdw; |
---|
764 | |
---|
765 | } |
---|
766 | if(elec_radius_id1!=elec_radius_id2) { |
---|
767 | if(!PConvPyObjectToFloat(elec_radius_id2,&elec_radius)) |
---|
768 | result=false; |
---|
769 | else |
---|
770 | at->elec_radius=elec_radius; |
---|
771 | } |
---|
772 | if(partial_charge_id1!=partial_charge_id2) { |
---|
773 | if(!PConvPyObjectToFloat(partial_charge_id2,&partialCharge)) |
---|
774 | result=false; |
---|
775 | else |
---|
776 | at->partialCharge=partialCharge; |
---|
777 | |
---|
778 | } |
---|
779 | if(formal_charge_id1!=formal_charge_id2) { |
---|
780 | if(!PConvPyObjectToInt(formal_charge_id2,&formalCharge)) |
---|
781 | result=false; |
---|
782 | else { |
---|
783 | at->formalCharge=formalCharge; |
---|
784 | at->chemFlag = false; /* invalidate chemistry info for this atom */ |
---|
785 | } |
---|
786 | |
---|
787 | } |
---|
788 | if(cartoon_id1!=cartoon_id2) { |
---|
789 | if(!PConvPyObjectToInt(cartoon_id2,&cartoon)) |
---|
790 | result=false; |
---|
791 | else |
---|
792 | at->cartoon=cartoon; |
---|
793 | } |
---|
794 | if(color_id1!=color_id2) { |
---|
795 | if(!PConvPyObjectToInt(color_id2,&color)) |
---|
796 | result=false; |
---|
797 | else |
---|
798 | at->color=color; |
---|
799 | } |
---|
800 | if(state_id1!=state_id2) { |
---|
801 | if(!PConvPyObjectToInt(state_id2,&state)) |
---|
802 | result=false; |
---|
803 | else |
---|
804 | at->discrete_state=state; |
---|
805 | } |
---|
806 | if(label_id1!=label_id2) { |
---|
807 | OrthoLineType temp; |
---|
808 | if(at->label) { |
---|
809 | OVLexicon_DecRef(G->Lexicon,at->label); |
---|
810 | } |
---|
811 | at->label = 0; |
---|
812 | |
---|
813 | if(PConvPyObjectToStrMaxLen(label_id2,temp,sizeof(OrthoLineType)-1)) { |
---|
814 | if(temp[0]) { |
---|
815 | OVreturn_word result = OVLexicon_GetFromCString(G->Lexicon,temp); |
---|
816 | if(OVreturn_IS_OK(result)) { |
---|
817 | at->label = result.word; |
---|
818 | } |
---|
819 | } |
---|
820 | } |
---|
821 | } |
---|
822 | if(flags_id1!=flags_id2) { |
---|
823 | if(!PConvPyObjectToInt(flags_id2,&flags)) |
---|
824 | result=false; |
---|
825 | else |
---|
826 | at->flags = flags; |
---|
827 | } |
---|
828 | |
---|
829 | if(numeric_type_id1!=numeric_type_id2) { |
---|
830 | if(!PConvPyObjectToInt(numeric_type_id2,&numericType)) |
---|
831 | result=false; |
---|
832 | else |
---|
833 | at->customType = numericType; |
---|
834 | } |
---|
835 | if(ID_id1!=ID_id2) { |
---|
836 | if(!PConvPyObjectToInt(ID_id2,&id)) |
---|
837 | result=false; |
---|
838 | else |
---|
839 | at->id=id; |
---|
840 | } |
---|
841 | if(rank_id1!=rank_id2) { |
---|
842 | if(!PConvPyObjectToInt(rank_id2,&rank)) |
---|
843 | result=false; |
---|
844 | else |
---|
845 | at->rank=rank; |
---|
846 | } |
---|
847 | |
---|
848 | if(PyErr_Occurred()) { |
---|
849 | PyErr_Print(); |
---|
850 | result=false; |
---|
851 | } |
---|
852 | } |
---|
853 | if(!result) { |
---|
854 | ErrMessage(G,"Alter","Aborting on error. Assignment may be incomplete."); |
---|
855 | } |
---|
856 | } |
---|
857 | Py_DECREF(dict); |
---|
858 | return(result); |
---|
859 | } |
---|
860 | |
---|
861 | int PLabelAtom(PyMOLGlobals *G, AtomInfoType *at,char *model,char *expr,int index) |
---|
862 | { |
---|
863 | PyObject *dict; |
---|
864 | PyObject *P_inst_dict = G->P_inst->dict; |
---|
865 | int result; |
---|
866 | OrthoLineType label; |
---|
867 | char atype[7]; |
---|
868 | OrthoLineType buffer; |
---|
869 | if(at->hetatm) |
---|
870 | strcpy(atype,"HETATM"); |
---|
871 | else |
---|
872 | strcpy(atype,"ATOM"); |
---|
873 | PBlock(G); |
---|
874 | /* PBlockAndUnlockAPI() is not safe. |
---|
875 | * what if "at" is destroyed by another thread? */ |
---|
876 | dict = PyDict_New(); |
---|
877 | |
---|
878 | PConvStringToPyDictItem(dict,"model",model); |
---|
879 | PConvIntToPyDictItem(dict,"index",index+1); |
---|
880 | PConvStringToPyDictItem(dict,"type",atype); |
---|
881 | PConvStringToPyDictItem(dict,"name",at->name); |
---|
882 | PConvStringToPyDictItem(dict,"resn",at->resn); |
---|
883 | PConvStringToPyDictItem(dict,"resi",at->resi); |
---|
884 | PConvIntToPyDictItem(dict,"resv",at->resv); |
---|
885 | PConvStringToPyDictItem(dict,"chain",at->chain); |
---|
886 | PConvStringToPyDictItem(dict,"alt",at->alt); |
---|
887 | PConvStringToPyDictItem(dict,"segi",at->segi); |
---|
888 | PConvStringToPyDictItem(dict,"ss",at->ssType); |
---|
889 | PConvFloatToPyDictItem(dict,"vdw",at->vdw); |
---|
890 | PConvFloatToPyDictItem(dict,"elec_radius",at->elec_radius); |
---|
891 | { |
---|
892 | char null_st[1] = ""; |
---|
893 | char *st = null_st; |
---|
894 | |
---|
895 | if(at->textType) st = OVLexicon_FetchCString(G->Lexicon,at->textType); |
---|
896 | PConvStringToPyDictItem(dict,"text_type",st); |
---|
897 | |
---|
898 | st = null_st; |
---|
899 | if(at->label) st = OVLexicon_FetchCString(G->Lexicon,at->label); |
---|
900 | PConvStringToPyDictItem(dict,"label",st); |
---|
901 | } |
---|
902 | PConvStringToPyDictItem(dict,"elem",at->elem); |
---|
903 | PConvIntToPyDictItem(dict,"geom",at->geom); |
---|
904 | PConvIntToPyDictItem(dict,"valence",at->valence); |
---|
905 | PConvIntToPyDictItem(dict,"rank",at->rank); |
---|
906 | if(at->flags) { |
---|
907 | sprintf(buffer,"%X",at->flags); |
---|
908 | PConvStringToPyDictItem(dict,"flags",buffer); |
---|
909 | } else { |
---|
910 | PConvStringToPyDictItem(dict,"flags","0"); |
---|
911 | } |
---|
912 | PConvFloatToPyDictItem(dict,"q",at->q); |
---|
913 | PConvFloatToPyDictItem(dict,"b",at->b); |
---|
914 | if(at->customType!=cAtomInfoNoType) |
---|
915 | PConvIntToPyDictItem(dict,"numeric_type",at->customType); |
---|
916 | else |
---|
917 | PConvStringToPyDictItem(dict,"numeric_type","?"); |
---|
918 | PConvFloatToPyDictItem(dict,"partial_charge",at->partialCharge); |
---|
919 | PConvIntToPyDictItem(dict,"formal_charge",at->formalCharge); |
---|
920 | PConvIntToPyDictItem(dict,"color",at->color); |
---|
921 | PConvIntToPyDictItem(dict,"cartoon",at->cartoon); |
---|
922 | PConvIntToPyDictItem(dict,"ID",at->id); |
---|
923 | PXDecRef(PyRun_String(expr,Py_single_input,P_inst_dict,dict)); |
---|
924 | if(PyErr_Occurred()) { |
---|
925 | PyErr_Print(); |
---|
926 | result=false; |
---|
927 | } else { |
---|
928 | result=true; |
---|
929 | if(!PConvPyObjectToStrMaxLen(PyDict_GetItemString(dict,"label"), |
---|
930 | label,sizeof(OrthoLineType)-1)) |
---|
931 | result=false; |
---|
932 | if(PyErr_Occurred()) { |
---|
933 | PyErr_Print(); |
---|
934 | result=false; |
---|
935 | } |
---|
936 | if(result) { |
---|
937 | if(at->label) { |
---|
938 | OVLexicon_DecRef(G->Lexicon,at->label); |
---|
939 | } |
---|
940 | at->label = 0; |
---|
941 | |
---|
942 | if(label[0]) { |
---|
943 | OVreturn_word ret = OVLexicon_GetFromCString(G->Lexicon,label); |
---|
944 | if(OVreturn_IS_OK(ret)) { |
---|
945 | /*printf("alloc'd %d [%s]\n",OVLexicon_GetNActive(G->Lexicon),label);*/ |
---|
946 | at->label = ret.word; |
---|
947 | } |
---|
948 | } |
---|
949 | } else { |
---|
950 | ErrMessage(G,"Label","Aborting on error. Labels may be incomplete."); |
---|
951 | } |
---|
952 | } |
---|
953 | Py_DECREF(dict); |
---|
954 | PUnblock(G); |
---|
955 | return(result); |
---|
956 | } |
---|
957 | |
---|
958 | void PUnlockAPIAsGlut(PyMOLGlobals *G) /* must call with unblocked interpreter */ |
---|
959 | { |
---|
960 | PRINTFD(G,FB_Threads) |
---|
961 | " PUnlockAPIAsGlut-DEBUG: entered as thread 0x%x\n",PyThread_get_thread_ident() |
---|
962 | ENDFD; |
---|
963 | PBlock(G); |
---|
964 | PXDecRef(PyObject_CallFunction(P_unlock,NULL)); /* NOTE this may flush the command buffer! */ |
---|
965 | PLockStatus(); |
---|
966 | PyMOL_PopValidContext(G->PyMOL); |
---|
967 | PUnlockStatus(); |
---|
968 | PUnlockGLUT(); |
---|
969 | PUnblock(G); |
---|
970 | } |
---|
971 | |
---|
972 | void PUnlockAPIAsGlutNoFlush(PyMOLGlobals *G) /* must call with unblocked interpreter */ |
---|
973 | { |
---|
974 | PRINTFD(G,FB_Threads) |
---|
975 | " PUnlockAPIAsGlut-DEBUG: entered as thread 0x%x\n",PyThread_get_thread_ident() |
---|
976 | ENDFD; |
---|
977 | PBlock(G); |
---|
978 | PXDecRef(PyObject_CallFunction(P_unlock,"i",-1)); /* prevents flushing of the buffer */ |
---|
979 | PLockStatus(); |
---|
980 | PyMOL_PopValidContext(G->PyMOL); |
---|
981 | PUnlockStatus(); |
---|
982 | PUnlockGLUT(); |
---|
983 | PUnblock(G); |
---|
984 | } |
---|
985 | |
---|
986 | static int get_api_lock(PyMOLGlobals *G,int block_if_busy) |
---|
987 | { |
---|
988 | int result = true; |
---|
989 | |
---|
990 | if(block_if_busy) { |
---|
991 | |
---|
992 | PXDecRef(PyObject_CallFunction(P_lock,NULL)); |
---|
993 | |
---|
994 | } else { /* not blocking if PyMOL is busy */ |
---|
995 | |
---|
996 | PyObject *got_lock = PyObject_CallFunction(P_lock_attempt,NULL); |
---|
997 | |
---|
998 | if(got_lock) { |
---|
999 | if(!PyInt_AsLong(got_lock)) { |
---|
1000 | PLockStatus(); |
---|
1001 | if(PyMOL_GetBusy(G->PyMOL,false)) |
---|
1002 | result = false; |
---|
1003 | PUnlockStatus(); |
---|
1004 | |
---|
1005 | if(result) { /* didn't get lock, but not busy, so block and wait for lock */ |
---|
1006 | PXDecRef(PyObject_CallFunction(P_lock,NULL)); |
---|
1007 | } |
---|
1008 | } |
---|
1009 | Py_DECREF(got_lock); |
---|
1010 | } |
---|
1011 | } |
---|
1012 | return result; |
---|
1013 | } |
---|
1014 | |
---|
1015 | int PLockAPIAsGlut(PyMOLGlobals *G,int block_if_busy) |
---|
1016 | { |
---|
1017 | PRINTFD(G,FB_Threads) |
---|
1018 | "*PLockAPIAsGlut-DEBUG: entered as thread 0x%x\n",PyThread_get_thread_ident() |
---|
1019 | ENDFD; |
---|
1020 | |
---|
1021 | PBlock(G); |
---|
1022 | |
---|
1023 | PLockGLUT(); |
---|
1024 | |
---|
1025 | PLockStatus(); |
---|
1026 | PyMOL_PushValidContext(G->PyMOL); |
---|
1027 | PUnlockStatus(); |
---|
1028 | |
---|
1029 | PRINTFD(G,FB_Threads) |
---|
1030 | "#PLockAPIAsGlut-DEBUG: acquiring lock as thread 0x%x\n",PyThread_get_thread_ident() |
---|
1031 | ENDFD; |
---|
1032 | |
---|
1033 | if(!get_api_lock(G,block_if_busy)) { |
---|
1034 | PLockStatus(); |
---|
1035 | PyMOL_PopValidContext(G->PyMOL); |
---|
1036 | PUnlockStatus(); |
---|
1037 | PUnlockGLUT(); |
---|
1038 | PUnblock(G); |
---|
1039 | return false;/* busy -- so allow main to update busy status display (if any) */ |
---|
1040 | } |
---|
1041 | |
---|
1042 | while(P_glut_thread_keep_out) { |
---|
1043 | /* IMPORTANT: keeps the glut thread out of an API operation... */ |
---|
1044 | /* NOTE: the keep_out variable can only be changed or read by the thread |
---|
1045 | holding the API lock, therefore it is safe even through increment |
---|
1046 | isn't atomic. */ |
---|
1047 | PRINTFD(G,FB_Threads) |
---|
1048 | "-PLockAPIAsGlut-DEBUG: glut_thread_keep_out 0x%x\n",PyThread_get_thread_ident() |
---|
1049 | ENDFD; |
---|
1050 | |
---|
1051 | PXDecRef(PyObject_CallFunction(P_unlock,"i",-1)); /* prevent buffer flushing */ |
---|
1052 | #ifndef WIN32 |
---|
1053 | { |
---|
1054 | struct timeval tv; |
---|
1055 | |
---|
1056 | PUnblock(G); |
---|
1057 | tv.tv_sec=0; |
---|
1058 | tv.tv_usec=50000; |
---|
1059 | select(0,NULL,NULL,NULL,&tv); |
---|
1060 | PBlock(G); |
---|
1061 | } |
---|
1062 | #else |
---|
1063 | /* BEGIN PROPRIETARY CODE SEGMENT (see disclaimer in "os_proprietary.h") */ |
---|
1064 | PXDecRef(PyObject_CallFunction(P_sleep,"f",0.050)); |
---|
1065 | /* END PROPRIETARY CODE SEGMENT */ |
---|
1066 | #endif |
---|
1067 | |
---|
1068 | if(!get_api_lock(G,block_if_busy)) { |
---|
1069 | /* return false-- allow main to update busy status display (if any) */ |
---|
1070 | PLockStatus(); |
---|
1071 | PyMOL_PopValidContext(G->PyMOL); |
---|
1072 | PUnlockStatus(); |
---|
1073 | PUnlockGLUT(); |
---|
1074 | PUnblock(G); |
---|
1075 | return false; |
---|
1076 | } |
---|
1077 | } |
---|
1078 | |
---|
1079 | |
---|
1080 | PUnblock(G); /* API is now locked, so we can free up Python...*/ |
---|
1081 | |
---|
1082 | PRINTFD(G,FB_Threads) |
---|
1083 | "=PLockAPIAsGlut-DEBUG: acquired\n" |
---|
1084 | ENDFD; |
---|
1085 | return true; |
---|
1086 | } |
---|
1087 | |
---|
1088 | /* THESE CALLS ARE REQUIRED FOR MONOLITHIC COMPILATION TO SUCCEED UNDER WINDOWS. */ |
---|
1089 | #ifndef _PYMOL_ACTIVEX |
---|
1090 | #ifndef _PYMOL_EMBEDDED |
---|
1091 | void initExtensionClass(void); |
---|
1092 | void initsglite(void); |
---|
1093 | void init_champ(void); |
---|
1094 | void init_opengl(void); |
---|
1095 | void init_opengl_num(void); |
---|
1096 | void init_glu(void); |
---|
1097 | void init_glu_num(void); |
---|
1098 | void init_glut(void); |
---|
1099 | void initopenglutil(void); |
---|
1100 | void initopenglutil_num(void); |
---|
1101 | #endif |
---|
1102 | #endif |
---|
1103 | |
---|
1104 | #ifdef _PYMOL_MONOLITHIC |
---|
1105 | #ifndef _PYMOL_ACTIVEX |
---|
1106 | #ifndef _PYMOL_EMBEDDED |
---|
1107 | /* BEGIN PROPRIETARY CODE SEGMENT (see disclaimer in "os_proprietary.h") */ |
---|
1108 | #ifdef WIN32 |
---|
1109 | void init_numpy(); |
---|
1110 | void initmultiarray(); |
---|
1111 | void initarrayfns(); |
---|
1112 | void initlapack_lite(); |
---|
1113 | void initumath(); |
---|
1114 | void initranlib(); |
---|
1115 | void init_champ(); |
---|
1116 | #endif |
---|
1117 | /* END PROPRIETARY CODE SEGMENT */ |
---|
1118 | #endif |
---|
1119 | #endif |
---|
1120 | #endif |
---|
1121 | |
---|
1122 | #ifdef _PYMOL_MONOLITHIC |
---|
1123 | #ifndef _PYMOL_ACTIVEX |
---|
1124 | #ifndef _PYMOL_EMBEDDED |
---|
1125 | void initExtensionClass(void); |
---|
1126 | void initsglite(void); |
---|
1127 | void init_champ(void); |
---|
1128 | void init_opengl(void); |
---|
1129 | void init_opengl_num(void); |
---|
1130 | void init_glu(void); |
---|
1131 | void init_glu_num(void); |
---|
1132 | void init_glut(void); |
---|
1133 | void initopenglutil(void); |
---|
1134 | void initopenglutil_num(void); |
---|
1135 | #endif |
---|
1136 | #endif |
---|
1137 | #endif |
---|
1138 | /* BEGIN PROPRIETARY CODE SEGMENT (see disclaimer in "os_proprietary.h") */ |
---|
1139 | #ifdef WIN32 |
---|
1140 | static int IsSecurityRequired() |
---|
1141 | { |
---|
1142 | DWORD WindowsVersion = GetVersion(); |
---|
1143 | DWORD WindowsMajorVersion = (DWORD)(LOBYTE(LOWORD(WindowsVersion))); |
---|
1144 | DWORD WindowsMinorVersion = (DWORD)(HIBYTE(LOWORD(WindowsVersion))); |
---|
1145 | |
---|
1146 | if (WindowsVersion >= 0x80000000) return FALSE; |
---|
1147 | |
---|
1148 | return TRUE; |
---|
1149 | } |
---|
1150 | #endif |
---|
1151 | /* END PROPRIETARY CODE SEGMENT */ |
---|
1152 | |
---|
1153 | void PSetupEmbedded(PyMOLGlobals *G,int argc,char **argv) |
---|
1154 | { |
---|
1155 | /* This routine is called if we are running with an embedded Python interpreter */ |
---|
1156 | PyObject *args, *pymol; |
---|
1157 | |
---|
1158 | /* BEGIN PROPRIETARY CODE SEGMENT (see disclaimer in "os_proprietary.h") */ |
---|
1159 | #ifdef WIN32 |
---|
1160 | |
---|
1161 | { /* automatically hide the window if this process |
---|
1162 | was started as a vanilla console application */ |
---|
1163 | HWND hwndFound; |
---|
1164 | if(hwndFound=FindWindow(NULL, argv[0])) { |
---|
1165 | ShowWindow(hwndFound,SW_HIDE); |
---|
1166 | } |
---|
1167 | } |
---|
1168 | |
---|
1169 | {/* if PYMOL_PATH and/or PYTHONHOME isn't in the environment coming |
---|
1170 | in, then the user may simply have clicked PyMOL.exe, in which |
---|
1171 | case we need to consult the registry regarding the location of |
---|
1172 | the install */ |
---|
1173 | |
---|
1174 | /* embedded version of PyMOL currently ships with Python 2.4 */ |
---|
1175 | #define EMBEDDED_PYTHONHOME "\\py24" |
---|
1176 | |
---|
1177 | OrthoLineType path_buffer; |
---|
1178 | static char line1[8092]; |
---|
1179 | static char line2[8092]; |
---|
1180 | HKEY phkResult; |
---|
1181 | int lpcbData; |
---|
1182 | int lpType = REG_SZ; |
---|
1183 | int r1,r2; |
---|
1184 | char *pymol_path; |
---|
1185 | char *pythonhome; |
---|
1186 | int pythonhome_set = false; |
---|
1187 | int restart_flag = false; |
---|
1188 | |
---|
1189 | |
---|
1190 | pymol_path = getenv("PYMOL_PATH"); |
---|
1191 | pythonhome = getenv("PYTHONHOME"); |
---|
1192 | if((!pymol_path)||(!pythonhome)) { |
---|
1193 | lpcbData = sizeof(OrthoLineType)-1; |
---|
1194 | r1=RegOpenKeyEx(HKEY_CLASSES_ROOT, |
---|
1195 | "Software\\DeLano Scientific\\PyMOL\\PYMOL_PATH", |
---|
1196 | 0,KEY_EXECUTE,&phkResult); |
---|
1197 | if(r1!=ERROR_SUCCESS) { |
---|
1198 | r1=RegOpenKeyEx(HKEY_CURRENT_USER, |
---|
1199 | "Software\\DeLano Scientific\\PyMOL\\PYMOL_PATH", |
---|
1200 | 0,KEY_EXECUTE,&phkResult); |
---|
1201 | } |
---|
1202 | if(r1==ERROR_SUCCESS) { |
---|
1203 | r2 = RegQueryValueEx(phkResult,"",NULL, |
---|
1204 | &lpType,path_buffer,&lpcbData); |
---|
1205 | if (r2==ERROR_SUCCESS) { |
---|
1206 | /* use environment variable PYMOL_PATH first, registry entry |
---|
1207 | second */ |
---|
1208 | if(!pymol_path) { |
---|
1209 | strcpy(line1,"PYMOL_PATH="); |
---|
1210 | strcat(line1,path_buffer); |
---|
1211 | _putenv(line1); |
---|
1212 | if(!pythonhome) { /* only set PYTHONHOME if already |
---|
1213 | setting new PYMOL_PATH */ |
---|
1214 | pythonhome_set = true; |
---|
1215 | strcpy(line2,"PYTHONHOME="); |
---|
1216 | strcat(line2,path_buffer); |
---|
1217 | strcat(line2,EMBEDDED_PYTHONHOME); |
---|
1218 | restart_flag = true; |
---|
1219 | _putenv(line2); |
---|
1220 | } |
---|
1221 | } |
---|
1222 | } |
---|
1223 | RegCloseKey(phkResult); |
---|
1224 | } |
---|
1225 | /* this allows us to just specify PYMOL_PATH with no registry entries */ |
---|
1226 | if((!pythonhome_set)&&(pymol_path)&&(!pythonhome)) { |
---|
1227 | strcpy(line2,"PYTHONHOME="); |
---|
1228 | strcat(line2,pymol_path); |
---|
1229 | strcat(line2,EMBEDDED_PYTHONHOME); |
---|
1230 | _putenv(line2); |
---|
1231 | restart_flag = true; |
---|
1232 | } |
---|
1233 | } |
---|
1234 | if(restart_flag && getenv("PYMOL_PATH") && getenv("PYTHONHOME")) { |
---|
1235 | |
---|
1236 | /* now that we have the environment defined, restart the process |
---|
1237 | * so that Python can use the new environment. If we don't do |
---|
1238 | * this, then Python won't see the new environment vars. Why not? */ |
---|
1239 | |
---|
1240 | /* note that we use CreateProcesss to launch the console |
---|
1241 | * application instead of exec or spawn in order to hide the |
---|
1242 | * console window. Otherwise a console window might appear, and |
---|
1243 | * that would suck. */ |
---|
1244 | |
---|
1245 | char command[8092]; |
---|
1246 | static char cmd_line[8092]; |
---|
1247 | char *p,*q; |
---|
1248 | int a; |
---|
1249 | |
---|
1250 | /* copy arguments, installing quotes around them */ |
---|
1251 | |
---|
1252 | sprintf(command,"%s\\pymol.exe",getenv("PYMOL_PATH")); |
---|
1253 | p = cmd_line; |
---|
1254 | |
---|
1255 | sprintf(p,"\"%s\"",command); |
---|
1256 | p+=strlen(p); |
---|
1257 | *(p++)=' '; |
---|
1258 | *p=0; |
---|
1259 | |
---|
1260 | for(a=1;a<=argc;a++) { |
---|
1261 | q = argv[a]; |
---|
1262 | if(q) { |
---|
1263 | if(*q!='"') { /* add quotes if not present */ |
---|
1264 | *(p++)='"'; |
---|
1265 | while(*q) { |
---|
1266 | *(p++)=*(q++); |
---|
1267 | } |
---|
1268 | *(p++)='"'; |
---|
1269 | } else { |
---|
1270 | while(*q) { |
---|
1271 | *(p++)=*(q++); |
---|
1272 | } |
---|
1273 | } |
---|
1274 | *(p++)=32; |
---|
1275 | *p=0; |
---|
1276 | } |
---|
1277 | } |
---|
1278 | |
---|
1279 | { |
---|
1280 | LPSECURITY_ATTRIBUTES lpSA = NULL; |
---|
1281 | PSECURITY_DESCRIPTOR lpSD = NULL; |
---|
1282 | STARTUPINFO si; |
---|
1283 | PROCESS_INFORMATION pi; |
---|
1284 | HANDLE hProcess = GetCurrentProcess(); |
---|
1285 | |
---|
1286 | ZeroMemory(&si, sizeof(STARTUPINFO)); |
---|
1287 | si.cb = sizeof(STARTUPINFO); |
---|
1288 | si.dwFlags = STARTF_USESHOWWINDOW; |
---|
1289 | si.wShowWindow = SW_HIDE; |
---|
1290 | |
---|
1291 | if(IsSecurityRequired()) |
---|
1292 | { |
---|
1293 | lpSD = GlobalAlloc(GPTR, SECURITY_DESCRIPTOR_MIN_LENGTH); |
---|
1294 | InitializeSecurityDescriptor(lpSD, SECURITY_DESCRIPTOR_REVISION); |
---|
1295 | SetSecurityDescriptorDacl(lpSD, -1, 0, 0); |
---|
1296 | |
---|
1297 | lpSA = GlobalAlloc(GPTR, sizeof(SECURITY_ATTRIBUTES)); |
---|
1298 | lpSA->nLength = sizeof(SECURITY_ATTRIBUTES); |
---|
1299 | lpSA->lpSecurityDescriptor = lpSD; |
---|
1300 | lpSA->bInheritHandle = TRUE; |
---|
1301 | } |
---|
1302 | |
---|
1303 | if(CreateProcess(NULL, (LPTSTR)cmd_line, lpSA, NULL, TRUE, |
---|
1304 | 0, NULL, NULL, &si, &pi)) { |
---|
1305 | WaitForSingleObject(pi.hProcess, INFINITE); |
---|
1306 | } |
---|
1307 | if (lpSA != NULL) GlobalFree(lpSA); |
---|
1308 | if (lpSD != NULL) GlobalFree(lpSD); |
---|
1309 | _exit(0); |
---|
1310 | } |
---|
1311 | } |
---|
1312 | } |
---|
1313 | |
---|
1314 | #endif |
---|
1315 | /* END PROPRIETARY CODE SEGMENT */ |
---|
1316 | |
---|
1317 | |
---|
1318 | /* compatibility for old compile-time defines */ |
---|
1319 | |
---|
1320 | #ifdef _PYMOL_SETUP_PY21 |
---|
1321 | #ifndef _PYMOL_SETUP_PY_EXT |
---|
1322 | #define _PYMOL_SETUP_PY_EXT |
---|
1323 | #endif |
---|
1324 | #endif |
---|
1325 | #ifdef _PYMOL_SETUP_PY22 |
---|
1326 | #ifndef _PYMOL_SETUP_PY_EXT |
---|
1327 | #define _PYMOL_SETUP_PY_EXT |
---|
1328 | #endif |
---|
1329 | #endif |
---|
1330 | #ifdef _PYMOL_SETUP_PY23 |
---|
1331 | #ifndef _PYMOL_SETUP_PY_EXT |
---|
1332 | #define _PYMOL_SETUP_PY_EXT |
---|
1333 | #endif |
---|
1334 | #endif |
---|
1335 | #ifdef _PYMOL_SETUP_PY24 |
---|
1336 | #ifndef _PYMOL_SETUP_PY_EXT |
---|
1337 | #define _PYMOL_SETUP_PY_EXT |
---|
1338 | #endif |
---|
1339 | #endif |
---|
1340 | #ifdef _PYMOL_SETUP_PY25 |
---|
1341 | #ifndef _PYMOL_SETUP_PY_EXT |
---|
1342 | #define _PYMOL_SETUP_PY_EXT |
---|
1343 | #endif |
---|
1344 | #endif |
---|
1345 | |
---|
1346 | /* should we set up PYTHONHOME in the ext directory? */ |
---|
1347 | |
---|
1348 | #ifdef _PYMOL_SETUP_PY_EXT |
---|
1349 | { |
---|
1350 | static char line1[8092]; |
---|
1351 | static char line2[8092]; |
---|
1352 | |
---|
1353 | if(!getenv("PYMOL_PATH")) { /* if PYMOL_PATH isn't defined...*/ |
---|
1354 | |
---|
1355 | /* was our startup path absolute? */ |
---|
1356 | |
---|
1357 | if((argc>0) && (argv[0][0]=='/')) { |
---|
1358 | /* PYMOL was started with an absolute path, so try using that... */ |
---|
1359 | char *p; |
---|
1360 | strcpy(line1,"PYMOL_PATH="); |
---|
1361 | strcat(line1,argv[0]); |
---|
1362 | p=line1 + strlen(line1); |
---|
1363 | while(*p!='/') { |
---|
1364 | *p=0; |
---|
1365 | p--; |
---|
1366 | } |
---|
1367 | *p=0; |
---|
1368 | putenv(line1); |
---|
1369 | } else if((argc>0) && getenv("PWD") && ((argv[0][0]=='.')||(strstr(argv[0],"/")))) { |
---|
1370 | /* was the path relative? */ |
---|
1371 | char *p; |
---|
1372 | strcpy(line1,"PYMOL_PATH="); |
---|
1373 | strcat(line1,getenv("PWD")); |
---|
1374 | strcat(line1,"/"); |
---|
1375 | strcat(line1,argv[0]); |
---|
1376 | p=line1 + strlen(line1); |
---|
1377 | while(*p!='/') { |
---|
1378 | *p=0; |
---|
1379 | p--; |
---|
1380 | } |
---|
1381 | *p=0; |
---|
1382 | putenv(line1); |
---|
1383 | } else { /* otherwise, just try using the current working directory */ |
---|
1384 | if(getenv("PWD")) { |
---|
1385 | strcpy(line1,"PYMOL_PATH="); |
---|
1386 | strcat(line1,getenv("PWD")); |
---|
1387 | putenv(line1); |
---|
1388 | } |
---|
1389 | } |
---|
1390 | } |
---|
1391 | |
---|
1392 | /* now set PYTHONHOME so that we use the right binary libraries for |
---|
1393 | this executable */ |
---|
1394 | |
---|
1395 | if(getenv("PYMOL_PATH")) { |
---|
1396 | strcpy(line2,"PYTHONHOME="); |
---|
1397 | strcat(line2,getenv("PYMOL_PATH")); |
---|
1398 | strcat(line2,"/ext"); |
---|
1399 | putenv(line2); |
---|
1400 | } |
---|
1401 | } |
---|
1402 | #endif |
---|
1403 | |
---|
1404 | #ifndef _PYMOL_ACTIVEX |
---|
1405 | #ifndef _PYMOL_EMBEDDED |
---|
1406 | Py_Initialize(); |
---|
1407 | PyEval_InitThreads(); |
---|
1408 | PyUnicode_SetDefaultEncoding("utf-8"); /* is this safe & legal? */ |
---|
1409 | |
---|
1410 | #endif |
---|
1411 | #endif |
---|
1412 | |
---|
1413 | init_cmd(); |
---|
1414 | #ifdef _PYMOL_MONOLITHIC |
---|
1415 | #ifndef _PYMOL_ACTIVEX |
---|
1416 | #ifndef _PYMOL_EMBEDDED |
---|
1417 | initExtensionClass(); |
---|
1418 | initsglite(); |
---|
1419 | /* initialize champ */ |
---|
1420 | init_champ(); |
---|
1421 | /* BEGIN PROPRIETARY CODE SEGMENT (see disclaimer in "os_proprietary.h") */ |
---|
1422 | #ifdef WIN32 |
---|
1423 | /* initialize numeric python */ |
---|
1424 | init_numpy(); |
---|
1425 | initmultiarray(); |
---|
1426 | initarrayfns(); |
---|
1427 | initlapack_lite(); |
---|
1428 | initumath(); |
---|
1429 | initranlib(); |
---|
1430 | #endif |
---|
1431 | /* END PROPRIETARY CODE SEGMENT */ |
---|
1432 | init_opengl(); |
---|
1433 | init_opengl_num(); |
---|
1434 | init_glu(); |
---|
1435 | init_glu_num(); |
---|
1436 | init_glut(); |
---|
1437 | initopenglutil(); |
---|
1438 | initopenglutil_num(); |
---|
1439 | #endif |
---|
1440 | #endif |
---|
1441 | #endif |
---|
1442 | PyRun_SimpleString("import os\n"); |
---|
1443 | PyRun_SimpleString("import sys\n"); |
---|
1444 | /* BEGIN PROPRIETARY CODE SEGMENT (see disclaimer in "os_proprietary.h") */ |
---|
1445 | #ifdef WIN32 |
---|
1446 | #if 0 |
---|
1447 | { |
---|
1448 | OrthoLineType path_buffer,command; |
---|
1449 | HKEY phkResult; |
---|
1450 | int lpcbData; |
---|
1451 | int lpType = REG_SZ; |
---|
1452 | int r1,r2; |
---|
1453 | |
---|
1454 | lpcbData = sizeof(OrthoLineType)-1; |
---|
1455 | r1=RegOpenKeyEx(HKEY_CLASSES_ROOT,"Software\\DeLano Scientific\\PyMOL\\PYMOL_PATH",0,KEY_EXECUTE,&phkResult); |
---|
1456 | if(r1==ERROR_SUCCESS) { |
---|
1457 | r2 = RegQueryValueEx(phkResult,"",NULL,&lpType,path_buffer,&lpcbData); |
---|
1458 | if (r2==ERROR_SUCCESS) { |
---|
1459 | /* use environment variable PYMOL_PATH first, registry entry second */ |
---|
1460 | sprintf(command,"_registry_pymol_path = r'''%s'''\n",path_buffer); |
---|
1461 | PyRun_SimpleString(command); |
---|
1462 | PyRun_SimpleString("if not os.environ.has_key('PYMOL_PATH'): os.environ['PYMOL_PATH']=_registry_pymol_path\n"); |
---|
1463 | } |
---|
1464 | RegCloseKey(phkResult); |
---|
1465 | } |
---|
1466 | } |
---|
1467 | #endif |
---|
1468 | PyRun_SimpleString("if not os.environ.has_key('PYMOL_PATH'): os.environ['PYMOL_PATH']=os.getcwd()\n"); |
---|
1469 | #endif |
---|
1470 | /* END PROPRIETARY CODE SEGMENT */ |
---|
1471 | |
---|
1472 | #ifdef _PYMOL_SETUP_TCLTK83 |
---|
1473 | /* used by semistatic pymol */ |
---|
1474 | PyRun_SimpleString("if os.path.exists(os.environ['PYMOL_PATH']+'/ext/lib/tcl8.3'): os.environ['TCL_LIBRARY']=os.environ['PYMOL_PATH']+'/ext/lib/tcl8.3'\n"); |
---|
1475 | PyRun_SimpleString("if os.path.exists(os.environ['PYMOL_PATH']+'/ext/lib/tk8.3'): os.environ['TK_LIBRARY']=os.environ['PYMOL_PATH']+'/ext/lib/tk8.3'\n"); |
---|
1476 | #endif |
---|
1477 | |
---|
1478 | #ifdef _PYMOL_SETUP_TCLTK84 |
---|
1479 | /* used by semistatic pymol */ |
---|
1480 | PyRun_SimpleString("if os.path.exists(os.environ['PYMOL_PATH']+'/ext/lib/tcl8.4'): os.environ['TCL_LIBRARY']=os.environ['PYMOL_PATH']+'/ext/lib/tcl8.4'\n"); |
---|
1481 | PyRun_SimpleString("if os.path.exists(os.environ['PYMOL_PATH']+'/ext/lib/tk8.4'): os.environ['TK_LIBRARY']=os.environ['PYMOL_PATH']+'/ext/lib/tk8.4'\n"); |
---|
1482 | #endif |
---|
1483 | |
---|
1484 | #if 0 |
---|
1485 | /* no longer necessary since we're setting PYTHONHOME */ |
---|
1486 | #ifdef _PYMOL_SETUP_PY21 |
---|
1487 | /* used by semistatic pymol */ |
---|
1488 | PyRun_SimpleString("import string"); |
---|
1489 | PyRun_SimpleString("sys.path=filter(lambda x:string.find(x,'static/ext-static')<0,sys.path)"); /* clean bogus entries in sys.path */ |
---|
1490 | #endif |
---|
1491 | #ifdef _PYMOL_SETUP_PY22 |
---|
1492 | /* used by semistatic pymol */ |
---|
1493 | PyRun_SimpleString("import string"); |
---|
1494 | PyRun_SimpleString("sys.path=filter(lambda x:string.find(x,'static/ext')<0,sys.path)"); /* clean bogus entries in sys.path */ |
---|
1495 | #endif |
---|
1496 | #ifdef _PYMOL_SETUP_PY23 |
---|
1497 | /* used by semistatic pymol */ |
---|
1498 | PyRun_SimpleString("import string"); |
---|
1499 | PyRun_SimpleString("sys.path=filter(lambda x:string.find(x,'static/ext')<0,sys.path)"); /* clean bogus entries in sys.path */ |
---|
1500 | #endif |
---|
1501 | #endif |
---|
1502 | /* BEGIN PROPRIETARY CODE SEGMENT (see disclaimer in "os_proprietary.h") */ |
---|
1503 | #ifdef WIN32 |
---|
1504 | PyRun_SimpleString("if (os.environ['PYMOL_PATH']+'/modules') not in sys.path: sys.path.insert(0,os.environ['PYMOL_PATH']+'/modules')\n"); |
---|
1505 | #endif |
---|
1506 | /* END PROPRIETARY CODE SEGMENT */ |
---|
1507 | |
---|
1508 | P_main = PyImport_AddModule("__main__"); |
---|
1509 | if(!P_main) ErrFatal(G,"PyMOL","can't find '__main__'"); |
---|
1510 | |
---|
1511 | /* inform PyMOL's other half that we're launching embedded-style */ |
---|
1512 | PyObject_SetAttrString(P_main,"pymol_launch",PyInt_FromLong(4)); |
---|
1513 | |
---|
1514 | args = PConvStringListToPyList(argc,argv); /* prepare our argument list */ |
---|
1515 | if(!args) ErrFatal(G,"PyMOL","can't process arguments."); |
---|
1516 | |
---|
1517 | /* copy arguments to __main__.pymol_argv */ |
---|
1518 | PyObject_SetAttrString(P_main,"pymol_argv",args); |
---|
1519 | |
---|
1520 | PyRun_SimpleString("if (os.environ['PYMOL_PATH']+'/modules') not in sys.path: sys.path.insert(0,os.environ['PYMOL_PATH']+'/modules')\n"); /* needed for semistatic pymol */ |
---|
1521 | |
---|
1522 | PyRun_SimpleString("import pymol"); /* create the global PyMOL namespace */ |
---|
1523 | |
---|
1524 | pymol = PyImport_AddModule("pymol"); /* get it */ |
---|
1525 | if(!pymol) ErrFatal(G,"PyMOL","can't find module 'pymol'"); |
---|
1526 | |
---|
1527 | } |
---|
1528 | |
---|
1529 | void PGetOptions(CPyMOLOptions *rec) |
---|
1530 | { |
---|
1531 | PyObject *pymol,*invocation,*options; |
---|
1532 | char *load_str; |
---|
1533 | |
---|
1534 | pymol = PyImport_AddModule("pymol"); /* get it */ |
---|
1535 | if(!pymol) {fprintf(stderr,"PyMOL-ERROR: can't find module 'pymol'"); exit(EXIT_FAILURE);} |
---|
1536 | |
---|
1537 | invocation = PyObject_GetAttrString(pymol,"invocation"); /* get a handle to the invocation module */ |
---|
1538 | if(!invocation) {fprintf(stderr,"PyMOL-ERROR: can't find module 'invocation'"); exit(EXIT_FAILURE);} |
---|
1539 | |
---|
1540 | options = PyObject_GetAttrString(invocation,"options"); |
---|
1541 | if(!options) {fprintf(stderr,"PyMOL-ERROR: can't get 'invocation.options'.");exit(EXIT_FAILURE);} |
---|
1542 | |
---|
1543 | rec->pmgui = ! PyInt_AsLong(PyObject_GetAttrString(options,"no_gui")); |
---|
1544 | rec->internal_gui = PyInt_AsLong(PyObject_GetAttrString(options,"internal_gui")); |
---|
1545 | rec->internal_feedback = PyInt_AsLong(PyObject_GetAttrString(options,"internal_feedback")); |
---|
1546 | rec->show_splash = PyInt_AsLong(PyObject_GetAttrString(options,"show_splash")); |
---|
1547 | rec->security = PyInt_AsLong(PyObject_GetAttrString(options,"security")); |
---|
1548 | rec->game_mode = PyInt_AsLong(PyObject_GetAttrString(options,"game_mode")); |
---|
1549 | rec->force_stereo = PyInt_AsLong(PyObject_GetAttrString(options,"force_stereo")); |
---|
1550 | rec->winX = PyInt_AsLong(PyObject_GetAttrString(options,"win_x")); |
---|
1551 | rec->winY = PyInt_AsLong(PyObject_GetAttrString(options,"win_y")); |
---|
1552 | rec->winPX = PyInt_AsLong(PyObject_GetAttrString(options,"win_px")); |
---|
1553 | rec->winPY = PyInt_AsLong(PyObject_GetAttrString(options,"win_py")); |
---|
1554 | rec->blue_line = PyInt_AsLong(PyObject_GetAttrString(options,"blue_line")); |
---|
1555 | rec->external_gui = PyInt_AsLong(PyObject_GetAttrString(options,"external_gui")); |
---|
1556 | rec->siginthand = PyInt_AsLong(PyObject_GetAttrString(options,"sigint_handler")); |
---|
1557 | rec->reuse_helper = PyInt_AsLong(PyObject_GetAttrString(options,"reuse_helper")); |
---|
1558 | rec->auto_reinitialize = PyInt_AsLong(PyObject_GetAttrString(options,"auto_reinitialize")); |
---|
1559 | rec->keep_thread_alive = PyInt_AsLong(PyObject_GetAttrString(options,"keep_thread_alive")); |
---|
1560 | rec->quiet = PyInt_AsLong(PyObject_GetAttrString(options,"quiet")); |
---|
1561 | #ifdef _IPYMOL |
---|
1562 | rec->incentive_product = true; |
---|
1563 | #else |
---|
1564 | rec->incentive_product = PyInt_AsLong(PyObject_GetAttrString(options,"incentive_product")); |
---|
1565 | #endif |
---|
1566 | rec->multisample = PyInt_AsLong(PyObject_GetAttrString(options,"multisample")); |
---|
1567 | rec->window_visible = PyInt_AsLong(PyObject_GetAttrString(options,"window_visible")); |
---|
1568 | rec->read_stdin = PyInt_AsLong(PyObject_GetAttrString(options,"read_stdin")); |
---|
1569 | rec->presentation = PyInt_AsLong(PyObject_GetAttrString(options,"presentation")); |
---|
1570 | rec->defer_builds_mode = PyInt_AsLong(PyObject_GetAttrString(options,"defer_builds_mode")); |
---|
1571 | rec->full_screen = PyInt_AsLong(PyObject_GetAttrString(options,"full_screen")); |
---|
1572 | load_str = PyString_AsString(PyObject_GetAttrString(options,"after_load_script")); |
---|
1573 | rec->sphere_mode = PyInt_AsLong(PyObject_GetAttrString(options,"sphere_mode")); |
---|
1574 | rec->stereo_capable = PyInt_AsLong(PyObject_GetAttrString(options,"stereo_capable")); |
---|
1575 | rec->passive_stereo= PyInt_AsLong(PyObject_GetAttrString(options,"passive_stereo")); |
---|
1576 | rec->zoom_mode= PyInt_AsLong(PyObject_GetAttrString(options,"zoom_mode")); |
---|
1577 | if(load_str) { |
---|
1578 | if(load_str[0]) { |
---|
1579 | UtilNCopy(rec->after_load_script,load_str,PYMOL_MAX_OPT_STR); |
---|
1580 | } |
---|
1581 | } |
---|
1582 | if(PyErr_Occurred()) { |
---|
1583 | PyErr_Print(); |
---|
1584 | } |
---|
1585 | } |
---|
1586 | |
---|
1587 | void PRunStringModule(PyMOLGlobals *G,char *str) /* runs a string in the namespace of the pymol instance */ |
---|
1588 | { |
---|
1589 | PXDecRef(PyObject_CallFunction(G->P_inst->exec,"Os",P_pymol,str)); |
---|
1590 | } |
---|
1591 | |
---|
1592 | void PRunStringInstance(PyMOLGlobals *G,char *str) /* runs a string in the namespace of the pymol instance */ |
---|
1593 | { |
---|
1594 | PXDecRef(PyObject_CallFunction(G->P_inst->exec,"Os",G->P_inst->obj,str)); |
---|
1595 | } |
---|
1596 | |
---|
1597 | void PInit(PyMOLGlobals *G,int global_instance) |
---|
1598 | { |
---|
1599 | PyObject *sys,*pcatch; |
---|
1600 | int a; |
---|
1601 | |
---|
1602 | #ifdef PYMOL_NEW_THREADS |
---|
1603 | PyEval_InitThreads(); |
---|
1604 | #endif |
---|
1605 | |
---|
1606 | /* BEGIN PROPRIETARY CODE SEGMENT (see disclaimer in "os_proprietary.h") */ |
---|
1607 | #ifdef WIN32 |
---|
1608 | #ifdef _PYMOL_MONOLITHIC |
---|
1609 | #ifndef _PYMOL_ACTIVEX |
---|
1610 | #ifndef _PYMOL_EMBEDDED |
---|
1611 | #define _PYMOL_INIT_MODULES |
---|
1612 | #endif |
---|
1613 | #endif |
---|
1614 | #endif |
---|
1615 | #endif |
---|
1616 | /* END PROPRIETARY CODE SEGMENT */ |
---|
1617 | |
---|
1618 | #ifdef _PYMOL_INIT_MODULES |
---|
1619 | /* Win32 module build: includes pyopengl, numpy, and sglite */ |
---|
1620 | /* sglite */ |
---|
1621 | initExtensionClass(); |
---|
1622 | initsglite(); |
---|
1623 | init_champ(); |
---|
1624 | /* initialize numeric python */ |
---|
1625 | init_numpy(); |
---|
1626 | initmultiarray(); |
---|
1627 | initarrayfns(); |
---|
1628 | initlapack_lite(); |
---|
1629 | initumath(); |
---|
1630 | initranlib(); |
---|
1631 | /* initialize PyOpenGL */ |
---|
1632 | init_opengl(); |
---|
1633 | init_opengl_num(); |
---|
1634 | init_glu(); |
---|
1635 | init_glu_num(); |
---|
1636 | init_glut(); |
---|
1637 | initopenglutil(); |
---|
1638 | initopenglutil_num(); |
---|
1639 | #endif |
---|
1640 | |
---|
1641 | |
---|
1642 | for(a=0;a<MAX_SAVED_THREAD;a++) { |
---|
1643 | SavedThread[a].id=-1; |
---|
1644 | } |
---|
1645 | |
---|
1646 | if(global_instance) { |
---|
1647 | PCatchInit(); /* setup standard-output catch routine */ |
---|
1648 | } |
---|
1649 | |
---|
1650 | /* assumes that pymol module has been loaded via Python or PyRun_SimpleString */ |
---|
1651 | |
---|
1652 | P_pymol = PyImport_AddModule("pymol"); /* get it */ |
---|
1653 | if(!P_pymol) ErrFatal(G,"PyMOL","can't find module 'pymol'"); |
---|
1654 | P_pymol_dict = PyModule_GetDict(P_pymol); |
---|
1655 | if(!P_pymol_dict) ErrFatal(G,"PyMOL","can't find globals for 'pymol'"); |
---|
1656 | |
---|
1657 | if(global_instance) { /* if global singleton PyMOL... */ |
---|
1658 | G->P_inst = Calloc(CP_inst,1); |
---|
1659 | G->P_inst->obj = P_pymol; |
---|
1660 | G->P_inst->dict = P_pymol_dict; |
---|
1661 | } |
---|
1662 | |
---|
1663 | { |
---|
1664 | G->P_inst->exec = PyDict_GetItemString(P_pymol_dict,"exec_str"); |
---|
1665 | if(!G->P_inst->exec) ErrFatal(G,"PyMOL","can't find 'pymol.exec_str()'"); |
---|
1666 | |
---|
1667 | sys = PyDict_GetItemString(P_pymol_dict,"sys"); |
---|
1668 | if(!sys) ErrFatal(G,"PyMOL","can't find 'pymol.sys'"); |
---|
1669 | |
---|
1670 | if(global_instance) { |
---|
1671 | |
---|
1672 | /* implies global singleton pymol, so set up the global handle */ |
---|
1673 | PyDict_SetItemString(P_pymol_dict,"_COb",PyCObject_FromVoidPtr((void*)&TempPyMOLGlobals,NULL)); |
---|
1674 | |
---|
1675 | pcatch = PyImport_AddModule("pcatch"); |
---|
1676 | if(!pcatch) ErrFatal(G,"PyMOL","can't find module 'pcatch'"); |
---|
1677 | PyObject_SetAttrString(sys,"stdout",pcatch); |
---|
1678 | PyObject_SetAttrString(sys,"stderr",pcatch); |
---|
1679 | } |
---|
1680 | |
---|
1681 | PRunStringModule(G,"import traceback\n"); |
---|
1682 | P_traceback = PyDict_GetItemString(P_pymol_dict,"traceback"); |
---|
1683 | if(!P_traceback) ErrFatal(G,"PyMOL","can't find 'traceback'"); |
---|
1684 | |
---|
1685 | PRunStringModule(G,"import cmd\n"); |
---|
1686 | P_cmd = PyDict_GetItemString(P_pymol_dict,"cmd"); |
---|
1687 | if(!P_cmd) ErrFatal(G,"PyMOL","can't find 'cmd'"); |
---|
1688 | |
---|
1689 | if(global_instance) { |
---|
1690 | /* implies global singleton pymol, so set up the global handle */ |
---|
1691 | PyObject_SetAttrString(P_cmd,"_COb",PyCObject_FromVoidPtr((void*)&TempPyMOLGlobals,NULL)); |
---|
1692 | |
---|
1693 | /* cmd module is itself the api for the global PyMOL instance */ |
---|
1694 | G->P_inst->cmd = P_cmd; |
---|
1695 | } |
---|
1696 | |
---|
1697 | PyObject_SetAttrString(G->P_inst->cmd,"_pymol",G->P_inst->obj); |
---|
1698 | |
---|
1699 | /* right now, all locks are global -- eventually some of these may |
---|
1700 | become instance-specific in order to improve concurrency */ |
---|
1701 | |
---|
1702 | P_lock = PyObject_GetAttrString(P_cmd,"lock"); |
---|
1703 | if(!P_lock) ErrFatal(G,"PyMOL","can't find 'cmd.lock()'"); |
---|
1704 | |
---|
1705 | P_lock_attempt = PyObject_GetAttrString(P_cmd,"lock_attempt"); |
---|
1706 | if(!P_lock_attempt) ErrFatal(G,"PyMOL","can't find 'cmd.lock_attempt()'"); |
---|
1707 | |
---|
1708 | P_unlock = PyObject_GetAttrString(P_cmd,"unlock"); |
---|
1709 | if(!P_unlock) ErrFatal(G,"PyMOL","can't find 'cmd.unlock()'"); |
---|
1710 | |
---|
1711 | P_lock_c = PyObject_GetAttrString(P_cmd,"lock_c"); |
---|
1712 | if(!P_lock_c) ErrFatal(G,"PyMOL","can't find 'cmd.lock_c()'"); |
---|
1713 | |
---|
1714 | P_unlock_c = PyObject_GetAttrString(P_cmd,"unlock_c"); |
---|
1715 | if(!P_unlock_c) ErrFatal(G,"PyMOL","can't find 'cmd.unlock_c()'"); |
---|
1716 | |
---|
1717 | P_lock_status = PyObject_GetAttrString(P_cmd,"lock_status"); |
---|
1718 | if(!P_lock_status) ErrFatal(G,"PyMOL","can't find 'cmd.lock_status()'"); |
---|
1719 | |
---|
1720 | P_lock_status_attempt = PyObject_GetAttrString(P_cmd,"lock_status_attempt"); |
---|
1721 | if(!P_lock_status_attempt) ErrFatal(G,"PyMOL","can't find 'cmd.lock_status_attempt()'"); |
---|
1722 | |
---|
1723 | P_unlock_status = PyObject_GetAttrString(P_cmd,"unlock_status"); |
---|
1724 | if(!P_unlock_status) ErrFatal(G,"PyMOL","can't find 'cmd.unlock_status()'"); |
---|
1725 | |
---|
1726 | P_lock_glut = PyObject_GetAttrString(P_cmd,"lock_glut"); |
---|
1727 | if(!P_lock_glut) ErrFatal(G,"PyMOL","can't find 'cmd.lock_glut()'"); |
---|
1728 | |
---|
1729 | P_unlock_glut = PyObject_GetAttrString(P_cmd,"unlock_glut"); |
---|
1730 | if(!P_unlock_glut) ErrFatal(G,"PyMOL","can't find 'cmd.unlock_glut()'"); |
---|
1731 | |
---|
1732 | /* 'do' command */ |
---|
1733 | |
---|
1734 | G->P_inst->cmd_do = PyObject_GetAttrString(G->P_inst->cmd,"do"); |
---|
1735 | if(!G->P_inst->cmd_do) ErrFatal(G,"PyMOL","can't find 'cmd.do()'"); |
---|
1736 | |
---|
1737 | /* invariant stuff */ |
---|
1738 | |
---|
1739 | PRunStringModule(G,"import menu\n"); |
---|
1740 | P_menu = PyDict_GetItemString(P_pymol_dict,"menu"); |
---|
1741 | if(!P_menu) ErrFatal(G,"PyMOL","can't find module 'menu'"); |
---|
1742 | |
---|
1743 | PRunStringModule(G,"import setting\n"); |
---|
1744 | P_setting = PyDict_GetItemString(P_pymol_dict,"setting"); |
---|
1745 | if(!P_setting) ErrFatal(G,"PyMOL","can't find module 'setting'"); |
---|
1746 | |
---|
1747 | PRunStringModule(G,"import povray\n"); |
---|
1748 | P_povray = PyDict_GetItemString(P_pymol_dict,"povray"); |
---|
1749 | if(!P_povray) ErrFatal(G,"PyMOL","can't find module 'povray'"); |
---|
1750 | |
---|
1751 | #ifdef _PYMOL_XRAY |
---|
1752 | PRunStringModule(G,"import xray\n"); |
---|
1753 | P_xray = PyDict_GetItemString(P_pymol_dict,"xray"); |
---|
1754 | if(!P_xray) ErrFatal(G,"PyMOL","can't find module 'xray'"); |
---|
1755 | #endif |
---|
1756 | |
---|
1757 | /* BEGIN PROPRIETARY CODE SEGMENT (see disclaimer in "os_proprietary.h") */ |
---|
1758 | #ifdef WIN32 |
---|
1759 | PRunStringModule(G,"import time\n"); |
---|
1760 | P_time = PyDict_GetItemString(P_pymol_dict,"time"); |
---|
1761 | if(!P_time) ErrFatal(G,"PyMOL","can't find module 'time'"); |
---|
1762 | |
---|
1763 | P_sleep = PyObject_GetAttrString(P_time,"sleep"); |
---|
1764 | if(!P_sleep) ErrFatal(G,"PyMOL","can't find 'time.sleep()'"); |
---|
1765 | #endif |
---|
1766 | /* END PROPRIETARY CODE SEGMENT */ |
---|
1767 | |
---|
1768 | PRunStringModule(G,"import parser\n"); |
---|
1769 | P_parser = PyDict_GetItemString(P_pymol_dict,"parser"); |
---|
1770 | if(!P_parser) ErrFatal(G,"PyMOL","can't find module 'parser'"); |
---|
1771 | |
---|
1772 | { |
---|
1773 | PyObject *fn_closure = PyObject_GetAttrString(P_parser,"new_parse_closure"); |
---|
1774 | G->P_inst->parse = PyObject_CallFunction(fn_closure,"O",G->P_inst->cmd); |
---|
1775 | PXDecRef(fn_closure); |
---|
1776 | if(!G->P_inst->parse) ErrFatal(G,"PyMOL","can't create 'parse' function closure"); |
---|
1777 | } |
---|
1778 | |
---|
1779 | { |
---|
1780 | PyObject *fn_closure = PyObject_GetAttrString(P_parser,"new_complete_closure"); |
---|
1781 | G->P_inst->complete = PyObject_CallFunction(fn_closure,"O",G->P_inst->cmd); |
---|
1782 | PXDecRef(fn_closure); |
---|
1783 | if(!G->P_inst->complete) ErrFatal(G,"PyMOL","can't create 'complete' function closure"); |
---|
1784 | } |
---|
1785 | |
---|
1786 | PRunStringModule(G,"import chempy"); |
---|
1787 | P_chempy = PyDict_GetItemString(P_pymol_dict,"chempy"); |
---|
1788 | if(!P_chempy) ErrFatal(G,"PyMOL","can't find 'chempy'"); |
---|
1789 | |
---|
1790 | PRunStringModule(G,"from chempy.bonds import bonds"); /* load bond dictionary */ |
---|
1791 | |
---|
1792 | PRunStringModule(G,"from chempy import models"); |
---|
1793 | P_models = PyDict_GetItemString(P_pymol_dict,"models"); |
---|
1794 | if(!P_models) ErrFatal(G,"PyMOL","can't find 'chempy.models'"); |
---|
1795 | |
---|
1796 | PRunStringModule(G,"import util\n"); |
---|
1797 | PRunStringModule(G,"import preset\n"); |
---|
1798 | PRunStringModule(G,"import contrib\n"); |
---|
1799 | |
---|
1800 | PRunStringModule(G,"import string\n"); |
---|
1801 | |
---|
1802 | /* backwards compatibility */ |
---|
1803 | |
---|
1804 | PRunStringModule(G,"pm = cmd\n"); |
---|
1805 | PRunStringModule(G,"pmu = util\n"); |
---|
1806 | |
---|
1807 | PRunStringModule(G,"glutThread = thread.get_ident()"); |
---|
1808 | |
---|
1809 | P_glut_thread_id = PyThread_get_thread_ident(); |
---|
1810 | |
---|
1811 | #ifndef WIN32 |
---|
1812 | if(G->Option->siginthand) { |
---|
1813 | signal(SIGINT,my_interrupt); |
---|
1814 | } |
---|
1815 | #endif |
---|
1816 | |
---|
1817 | /* required environment variables */ |
---|
1818 | |
---|
1819 | PyRun_SimpleString("import os"); |
---|
1820 | PyRun_SimpleString( |
---|
1821 | "if not os.environ.has_key('PYMOL_DATA'): os.environ['PYMOL_DATA']=os.environ['PYMOL_PATH']+'/data'"); |
---|
1822 | PyRun_SimpleString( |
---|
1823 | "os.environ['TUT']=os.environ['PYMOL_DATA']+'/tut'"); |
---|
1824 | |
---|
1825 | PyRun_SimpleString( |
---|
1826 | "if not os.environ.has_key('PYMOL_SCRIPTS'): os.environ['PYMOL_SCRIPTS']=os.environ['PYMOL_PATH']+'/scripts'"); |
---|
1827 | |
---|
1828 | } |
---|
1829 | } |
---|
1830 | |
---|
1831 | int PPovrayRender(PyMOLGlobals *G,char *header,char *inp,char *file,int width,int height,int antialias) |
---|
1832 | { |
---|
1833 | PyObject *result; |
---|
1834 | int ok; |
---|
1835 | PBlock(G); |
---|
1836 | result = PyObject_CallMethod(P_povray,"render_from_string","sssiii",header,inp,file,width,height,antialias); |
---|
1837 | ok = PyObject_IsTrue(result); |
---|
1838 | Py_DECREF(result); |
---|
1839 | PUnblock(G); |
---|
1840 | return(ok); |
---|
1841 | } |
---|
1842 | |
---|
1843 | void PSGIStereo(PyMOLGlobals *G,int flag) |
---|
1844 | { |
---|
1845 | int blocked; |
---|
1846 | blocked = PAutoBlock(G); |
---|
1847 | if(flag) |
---|
1848 | PRunStringModule(G,"cmd._sgi_stereo(1)"); |
---|
1849 | else |
---|
1850 | PRunStringModule(G,"cmd._sgi_stereo(0)"); |
---|
1851 | if(blocked) PUnblock(G); |
---|
1852 | } |
---|
1853 | |
---|
1854 | void PFree(void) |
---|
1855 | { |
---|
1856 | } |
---|
1857 | |
---|
1858 | void PExit(PyMOLGlobals *G,int code) |
---|
1859 | { |
---|
1860 | ExecutiveDelete(G,"all"); |
---|
1861 | PBlock(G); |
---|
1862 | #ifndef _PYMOL_NO_MAIN |
---|
1863 | MainFree(); |
---|
1864 | #endif |
---|
1865 | |
---|
1866 | /* we're having trouble with threading errors after calling Py_Exit, |
---|
1867 | so for the time being, let's just take the process down at this |
---|
1868 | point, instead of allowing PyExit to be called. */ |
---|
1869 | |
---|
1870 | exit(EXIT_SUCCESS); |
---|
1871 | |
---|
1872 | Py_Exit(code); |
---|
1873 | } |
---|
1874 | |
---|
1875 | void PParse(PyMOLGlobals *G,char *str) |
---|
1876 | { |
---|
1877 | OrthoCommandIn(G,str); |
---|
1878 | } |
---|
1879 | |
---|
1880 | void PDo(PyMOLGlobals *G,char *str) /* assumes we already hold the re-entrant API lock */ |
---|
1881 | { |
---|
1882 | int blocked; |
---|
1883 | blocked = PAutoBlock(G); |
---|
1884 | Py_XDECREF(PyObject_CallFunction(G->P_inst->cmd_do,"s",str)); |
---|
1885 | PAutoUnblock(G,blocked); |
---|
1886 | } |
---|
1887 | |
---|
1888 | void PLog(PyMOLGlobals *G,char *str,int format) |
---|
1889 | /* general log routine can write PML |
---|
1890 | or PYM commands to appropriate log file */ |
---|
1891 | { |
---|
1892 | int mode; |
---|
1893 | int a; |
---|
1894 | int blocked; |
---|
1895 | PyObject *log; |
---|
1896 | OrthoLineType buffer=""; |
---|
1897 | mode = (int)SettingGet(G,cSetting_logging); |
---|
1898 | if(mode) |
---|
1899 | { |
---|
1900 | blocked = PAutoBlock(G); |
---|
1901 | log = PyDict_GetItemString(P_pymol_dict,P_log_file_str); |
---|
1902 | if(log&&(log!=Py_None)) { |
---|
1903 | if(format==cPLog_no_flush) { |
---|
1904 | PyObject_CallMethod(log,"write","s",str); /* maximize responsiveness (for real-time) */ |
---|
1905 | } else { |
---|
1906 | switch(mode) { |
---|
1907 | case cPLog_pml: /* .pml file */ |
---|
1908 | switch(format) { |
---|
1909 | case cPLog_pml_lf: |
---|
1910 | strcpy(buffer,str); |
---|
1911 | break; |
---|
1912 | case cPLog_pml: |
---|
1913 | case cPLog_pym: |
---|
1914 | strcpy(buffer,str); |
---|
1915 | strcat(buffer,"\n"); |
---|
1916 | break; |
---|
1917 | } |
---|
1918 | break; |
---|
1919 | case cPLog_pym: /* .pym file */ |
---|
1920 | if((str[0]=='_')&&(str[1])==' ') |
---|
1921 | str+=2; |
---|
1922 | switch(format) { |
---|
1923 | case cPLog_pml_lf: |
---|
1924 | a =strlen(str); |
---|
1925 | while(a) { /* trim CR/LF etc. */ |
---|
1926 | if(*(str+a)>=32) break; |
---|
1927 | *(str+a)=0; |
---|
1928 | a--; |
---|
1929 | } |
---|
1930 | case cPLog_pml: |
---|
1931 | strcpy(buffer,"cmd.do('''"); |
---|
1932 | strcat(buffer,str); |
---|
1933 | strcat(buffer,"''')\n"); |
---|
1934 | break; |
---|
1935 | case cPLog_pym: |
---|
1936 | strcpy(buffer,str); |
---|
1937 | strcat(buffer,"\n"); |
---|
1938 | break; |
---|
1939 | } |
---|
1940 | } |
---|
1941 | PyObject_CallMethod(log,"write","s",buffer); |
---|
1942 | PyObject_CallMethod(log,"flush",""); |
---|
1943 | } |
---|
1944 | } |
---|
1945 | PAutoUnblock(G,blocked); |
---|
1946 | } |
---|
1947 | } |
---|
1948 | |
---|
1949 | void PLogFlush(PyMOLGlobals *G) |
---|
1950 | { |
---|
1951 | int mode; |
---|
1952 | PyObject *log; |
---|
1953 | int blocked; |
---|
1954 | mode = (int)SettingGet(G,cSetting_logging); |
---|
1955 | if(mode) |
---|
1956 | { |
---|
1957 | blocked = PAutoBlock(G); |
---|
1958 | log = PyDict_GetItemString(P_pymol_dict,P_log_file_str); |
---|
1959 | if(log&&(log!=Py_None)) { |
---|
1960 | PyObject_CallMethod(log,"flush",""); |
---|
1961 | } |
---|
1962 | PAutoUnblock(G,blocked); |
---|
1963 | } |
---|
1964 | } |
---|
1965 | |
---|
1966 | void PFlush(PyMOLGlobals *G) { |
---|
1967 | /* NOTE: ASSUMES unblocked Python threads and a locked API */ |
---|
1968 | PyObject *err; |
---|
1969 | char buffer[OrthoLineLength+1]; |
---|
1970 | while(OrthoCommandOut(G,buffer)) { |
---|
1971 | PBlockAndUnlockAPI(G); |
---|
1972 | |
---|
1973 | PXDecRef(PyObject_CallFunction(G->P_inst->parse,"si",buffer,0)); |
---|
1974 | err = PyErr_Occurred(); |
---|
1975 | if(err) { |
---|
1976 | PyErr_Print(); |
---|
1977 | PRINTFB(G,FB_Python,FB_Errors) |
---|
1978 | " PFlush: Uncaught exception. PyMOL may have a bug.\n" |
---|
1979 | ENDFB(G); |
---|
1980 | } |
---|
1981 | PLockAPIAndUnblock(G); |
---|
1982 | } |
---|
1983 | } |
---|
1984 | |
---|
1985 | void PFlushFast(PyMOLGlobals *G) { |
---|
1986 | /* NOTE: ASSUMES we currently have blocked Python threads and an unlocked API */ |
---|
1987 | PyObject *err; |
---|
1988 | char buffer[OrthoLineLength+1]; |
---|
1989 | while(OrthoCommandOut(G,buffer)) { |
---|
1990 | PRINTFD(G,FB_Threads) |
---|
1991 | " PFlushFast-DEBUG: executing '%s' as thread 0x%x\n",buffer, |
---|
1992 | PyThread_get_thread_ident() |
---|
1993 | ENDFD; |
---|
1994 | PXDecRef(PyObject_CallFunction(G->P_inst->parse,"si",buffer,0)); |
---|
1995 | err = PyErr_Occurred(); |
---|
1996 | if(err) { |
---|
1997 | PyErr_Print(); |
---|
1998 | PRINTFB(G,FB_Python,FB_Errors) |
---|
1999 | " PFlushFast: Uncaught exception. PyMOL may have a bug.\n" |
---|
2000 | ENDFB(G); |
---|
2001 | } |
---|
2002 | } |
---|
2003 | } |
---|
2004 | |
---|
2005 | |
---|
2006 | void PBlockLegacy() |
---|
2007 | { |
---|
2008 | PBlock(TempPyMOLGlobals); |
---|
2009 | } |
---|
2010 | |
---|
2011 | void PUnblockLegacy() |
---|
2012 | { |
---|
2013 | PUnblock(TempPyMOLGlobals); |
---|
2014 | } |
---|
2015 | |
---|
2016 | void PBlock(PyMOLGlobals *G) |
---|
2017 | { |
---|
2018 | |
---|
2019 | if(!PAutoBlock(G)) { |
---|
2020 | ErrFatal(G,"PBlock","Threading error detected. Terminating..."); |
---|
2021 | } |
---|
2022 | } |
---|
2023 | |
---|
2024 | |
---|
2025 | int PAutoBlock(PyMOLGlobals *G) |
---|
2026 | { |
---|
2027 | #ifndef _PYMOL_ACTIVEX |
---|
2028 | #ifndef _PYMOL_EMBEDDED |
---|
2029 | int a,id; |
---|
2030 | /* synchronize python */ |
---|
2031 | |
---|
2032 | id = PyThread_get_thread_ident(); |
---|
2033 | PRINTFD(G,FB_Threads) |
---|
2034 | " PAutoBlock-DEBUG: search 0x%x (0x%x, 0x%x, 0x%x)\n",id, |
---|
2035 | SavedThread[MAX_SAVED_THREAD-1].id, |
---|
2036 | SavedThread[MAX_SAVED_THREAD-2].id, |
---|
2037 | SavedThread[MAX_SAVED_THREAD-3].id |
---|
2038 | ENDFD; |
---|
2039 | a = MAX_SAVED_THREAD-1; |
---|
2040 | while(a) { |
---|
2041 | if(!((SavedThread+a)->id-id)) { |
---|
2042 | /* astoundingly, equality test fails on ALPHA even |
---|
2043 | * though the ints are equal. Must be some kind of optimizer bug |
---|
2044 | * or mis-assumption */ |
---|
2045 | |
---|
2046 | PRINTFD(G,FB_Threads) |
---|
2047 | " PAutoBlock-DEBUG: seeking global lock 0x%x\n",id |
---|
2048 | ENDFD; |
---|
2049 | |
---|
2050 | #ifdef PYMOL_NEW_THREADS |
---|
2051 | |
---|
2052 | PyEval_AcquireLock(); |
---|
2053 | |
---|
2054 | PRINTFD(G,FB_Threads) |
---|
2055 | " PAutoBlock-DEBUG: restoring 0x%x\n",id |
---|
2056 | ENDFD; |
---|
2057 | |
---|
2058 | PyThreadState_Swap((SavedThread+a)->state); |
---|
2059 | |
---|
2060 | #else |
---|
2061 | PRINTFD(G,FB_Threads) |
---|
2062 | " PAutoBlock-DEBUG: restoring 0x%x\n",id |
---|
2063 | ENDFD; |
---|
2064 | |
---|
2065 | PyEval_RestoreThread((SavedThread+a)->state); |
---|
2066 | #endif |
---|
2067 | |
---|
2068 | PRINTFD(G,FB_Threads) |
---|
2069 | " PAutoBlock-DEBUG: restored 0x%x\n",id |
---|
2070 | ENDFD; |
---|
2071 | |
---|
2072 | PRINTFD(G,FB_Threads) |
---|
2073 | " PAutoBlock-DEBUG: clearing 0x%x\n",id |
---|
2074 | ENDFD; |
---|
2075 | |
---|
2076 | PXDecRef(PyObject_CallFunction(P_lock_c,NULL)); |
---|
2077 | SavedThread[a].id = -1; |
---|
2078 | /* this is the only safe time we can change things */ |
---|
2079 | PXDecRef(PyObject_CallFunction(P_unlock_c,NULL)); |
---|
2080 | |
---|
2081 | PRINTFD(G,FB_Threads) |
---|
2082 | " PAutoBlock-DEBUG: blocked 0x%x (0x%x, 0x%x, 0x%x)\n",PyThread_get_thread_ident(), |
---|
2083 | SavedThread[MAX_SAVED_THREAD-1].id, |
---|
2084 | SavedThread[MAX_SAVED_THREAD-2].id, |
---|
2085 | SavedThread[MAX_SAVED_THREAD-3].id |
---|
2086 | ENDFD; |
---|
2087 | |
---|
2088 | return 1; |
---|
2089 | } |
---|
2090 | a--; |
---|
2091 | } |
---|
2092 | PRINTFD(G,FB_Threads) |
---|
2093 | " PAutoBlock-DEBUG: 0x%x not found, thus already blocked.\n",PyThread_get_thread_ident() |
---|
2094 | ENDFD; |
---|
2095 | return 0; |
---|
2096 | #else |
---|
2097 | return 1; |
---|
2098 | #endif |
---|
2099 | #else |
---|
2100 | return 1; |
---|
2101 | #endif |
---|
2102 | } |
---|
2103 | |
---|
2104 | int PIsGlutThread(void) |
---|
2105 | { |
---|
2106 | return(PyThread_get_thread_ident()==P_glut_thread_id); |
---|
2107 | } |
---|
2108 | |
---|
2109 | void PUnblock(PyMOLGlobals *G) |
---|
2110 | { |
---|
2111 | #ifndef _PYMOL_ACTIVEX |
---|
2112 | #ifndef _PYMOL_EMBEDDED |
---|
2113 | int a; |
---|
2114 | /* NOTE: ASSUMES a locked API */ |
---|
2115 | |
---|
2116 | PRINTFD(G,FB_Threads) |
---|
2117 | " PUnblock-DEBUG: entered as thread 0x%x\n",PyThread_get_thread_ident() |
---|
2118 | ENDFD; |
---|
2119 | |
---|
2120 | /* reserve a space while we have a lock */ |
---|
2121 | PXDecRef(PyObject_CallFunction(P_lock_c,NULL)); |
---|
2122 | a = MAX_SAVED_THREAD-1; |
---|
2123 | while(a) { |
---|
2124 | if((SavedThread+a)->id == -1 ) { |
---|
2125 | (SavedThread+a)->id = PyThread_get_thread_ident(); |
---|
2126 | #ifdef PYMOL_NEW_THREADS |
---|
2127 | (SavedThread+a)->state = PyThreadState_Get(); |
---|
2128 | #endif |
---|
2129 | break; |
---|
2130 | } |
---|
2131 | a--; |
---|
2132 | } |
---|
2133 | PRINTFD(G,FB_Threads) |
---|
2134 | " PUnblock-DEBUG: 0x%x stored in slot %d\n",(SavedThread+a)->id,a |
---|
2135 | ENDFD; |
---|
2136 | PXDecRef(PyObject_CallFunction(P_unlock_c,NULL)); |
---|
2137 | #ifdef PYMOL_NEW_THREADS |
---|
2138 | PyThreadState_Swap(NULL); |
---|
2139 | PyEval_ReleaseLock(); |
---|
2140 | #else |
---|
2141 | (SavedThread+a)->state = PyEval_SaveThread(); |
---|
2142 | #endif |
---|
2143 | |
---|
2144 | #endif |
---|
2145 | #endif |
---|
2146 | |
---|
2147 | } |
---|
2148 | |
---|
2149 | |
---|
2150 | void PAutoUnblock(PyMOLGlobals *G,int flag) |
---|
2151 | { |
---|
2152 | if(flag) PUnblock(G); |
---|
2153 | } |
---|
2154 | |
---|
2155 | void PBlockAndUnlockAPI(PyMOLGlobals *G) |
---|
2156 | { |
---|
2157 | PBlock(G); |
---|
2158 | PXDecRef(PyObject_CallFunction(P_unlock,NULL)); |
---|
2159 | } |
---|
2160 | |
---|
2161 | void PLockAPIAndUnblock(PyMOLGlobals *G) |
---|
2162 | { |
---|
2163 | PXDecRef(PyObject_CallFunction(P_lock,NULL)); |
---|
2164 | PUnblock(G); |
---|
2165 | } |
---|
2166 | |
---|
2167 | void PDefineFloat(PyMOLGlobals *G,char *name,float value) { |
---|
2168 | char buffer[OrthoLineLength]; |
---|
2169 | sprintf(buffer,"%s = %f\n",name,value); |
---|
2170 | PBlock(G); |
---|
2171 | PRunStringModule(G,buffer); |
---|
2172 | PUnblock(G); |
---|
2173 | } |
---|
2174 | |
---|
2175 | |
---|
2176 | /* This function is called by the interpreter to get its own name */ |
---|
2177 | char *getprogramname(void) |
---|
2178 | { |
---|
2179 | return("PyMOL"); |
---|
2180 | } |
---|
2181 | |
---|
2182 | /* A static module */ |
---|
2183 | |
---|
2184 | static PyObject *PCatchWrite(PyObject *self, PyObject *args) |
---|
2185 | { |
---|
2186 | char *str; |
---|
2187 | PyArg_ParseTuple(args,"s",&str); |
---|
2188 | if(str[0]) { |
---|
2189 | if(TempPyMOLGlobals) { |
---|
2190 | if(Feedback(TempPyMOLGlobals,FB_Python,FB_Output)) { |
---|
2191 | OrthoAddOutput(TempPyMOLGlobals,str); |
---|
2192 | } |
---|
2193 | } |
---|
2194 | } |
---|
2195 | Py_INCREF(Py_None); |
---|
2196 | return Py_None; |
---|
2197 | } |
---|
2198 | |
---|
2199 | static PyObject *PCatchFlush(PyObject *self, PyObject *args) |
---|
2200 | { |
---|
2201 | fflush(stdout); |
---|
2202 | fflush(stderr); |
---|
2203 | Py_INCREF(Py_None); |
---|
2204 | return Py_None; |
---|
2205 | } |
---|
2206 | |
---|
2207 | static PyMethodDef PCatch_methods[] = { |
---|
2208 | {"write", PCatchWrite, METH_VARARGS}, |
---|
2209 | {"flush", PCatchFlush, METH_VARARGS}, |
---|
2210 | {NULL, NULL} /* sentinel */ |
---|
2211 | }; |
---|
2212 | |
---|
2213 | void PCatchInit(void) |
---|
2214 | { |
---|
2215 | PyImport_AddModule("pcatch"); |
---|
2216 | Py_InitModule("pcatch", PCatch_methods); |
---|
2217 | } |
---|
2218 | #else |
---|
2219 | typedef int this_source_file_is_not_empty; |
---|
2220 | #endif |
---|
2221 | |
---|
2222 | |
---|