1 | |
---|
2 | /* |
---|
3 | * ---------------------------------------------------------------------- |
---|
4 | * proxypymol.c |
---|
5 | * |
---|
6 | * This module creates the Tcl interface to the pymol server. It acts as |
---|
7 | * a go-between establishing communication between a molvisviewer widget |
---|
8 | * and the pymol server. The communication protocol from the molvisviewer |
---|
9 | * widget is the Tcl language. Commands are then relayed to the pymol |
---|
10 | * server. Responses from the pymol server are translated into Tcl |
---|
11 | * commands * and send to the molvisviewer widget. For example, resulting |
---|
12 | * image rendered offscreen is returned as BMP-formatted image data. |
---|
13 | * |
---|
14 | * Copyright (c) 2004-2006 Purdue Research Foundation |
---|
15 | * |
---|
16 | * See the file "license.terms" for information on usage and |
---|
17 | * redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES. |
---|
18 | * ====================================================================== |
---|
19 | */ |
---|
20 | |
---|
21 | #include <stdio.h> |
---|
22 | #include <assert.h> |
---|
23 | #include <unistd.h> |
---|
24 | #include <stdlib.h> |
---|
25 | #include <string.h> |
---|
26 | #include <signal.h> |
---|
27 | #include <sys/types.h> |
---|
28 | #include <sys/socket.h> |
---|
29 | #include <sys/wait.h> |
---|
30 | #include <sys/select.h> |
---|
31 | #include <poll.h> |
---|
32 | #include <sys/time.h> |
---|
33 | #include <fcntl.h> |
---|
34 | #include <netinet/in.h> |
---|
35 | #include <getopt.h> |
---|
36 | #include <errno.h> |
---|
37 | #include <sys/ioctl.h> |
---|
38 | #include <net/if.h> |
---|
39 | #include <tcl.h> |
---|
40 | |
---|
41 | #undef INLINE |
---|
42 | #ifdef __GNUC__ |
---|
43 | # define INLINE __inline__ |
---|
44 | #else |
---|
45 | # define INLINE |
---|
46 | #endif |
---|
47 | |
---|
48 | #define IO_TIMEOUT (30000) |
---|
49 | |
---|
50 | static FILE *flog; |
---|
51 | static int debug = 1; |
---|
52 | |
---|
53 | static void |
---|
54 | trace TCL_VARARGS_DEF(char *, arg1) |
---|
55 | { |
---|
56 | if (debug) { |
---|
57 | char *format; |
---|
58 | va_list args; |
---|
59 | |
---|
60 | format = TCL_VARARGS_START(char *, arg1, args); |
---|
61 | vfprintf(flog, format, args); |
---|
62 | fprintf(flog, "\n"); |
---|
63 | fflush(flog); |
---|
64 | } |
---|
65 | } |
---|
66 | |
---|
67 | typedef struct { |
---|
68 | char *data; |
---|
69 | int used; |
---|
70 | int allocated; |
---|
71 | } DyBuffer; |
---|
72 | |
---|
73 | typedef struct { |
---|
74 | int p_stdin; |
---|
75 | int p_stdout; |
---|
76 | int p_stderr; |
---|
77 | int c_stdin; |
---|
78 | int c_stdout; |
---|
79 | DyBuffer image; |
---|
80 | int need_update; |
---|
81 | int can_update; |
---|
82 | int immediate_update; |
---|
83 | int sync; |
---|
84 | int labels; |
---|
85 | int frame; |
---|
86 | int rock_offset; |
---|
87 | int cacheid; |
---|
88 | int invalidate_cache; |
---|
89 | int error; |
---|
90 | int status; |
---|
91 | } PymolProxy; |
---|
92 | |
---|
93 | INLINE static void |
---|
94 | dyBufferInit(DyBuffer *buffer) |
---|
95 | { |
---|
96 | buffer->data = NULL; |
---|
97 | buffer->used = 0; |
---|
98 | buffer->allocated = 0; |
---|
99 | } |
---|
100 | |
---|
101 | INLINE static void |
---|
102 | dyBufferFree(DyBuffer *buffer) |
---|
103 | { |
---|
104 | assert(buffer != NULL); |
---|
105 | free(buffer->data); |
---|
106 | dyBufferInit(buffer); |
---|
107 | } |
---|
108 | |
---|
109 | void |
---|
110 | dyBufferSetLength(DyBuffer *buffer, int length) |
---|
111 | { |
---|
112 | assert(buffer != NULL); |
---|
113 | if (length == 0) { |
---|
114 | dyBufferFree(buffer); |
---|
115 | } else if (length > buffer->used) { |
---|
116 | char *newdata; |
---|
117 | |
---|
118 | newdata = realloc(buffer->data, length); |
---|
119 | if (newdata != NULL) { |
---|
120 | buffer->data = newdata; |
---|
121 | buffer->used = length; |
---|
122 | buffer->allocated = length; |
---|
123 | } |
---|
124 | } else { |
---|
125 | buffer->used = length; |
---|
126 | } |
---|
127 | } |
---|
128 | |
---|
129 | static void |
---|
130 | dyBufferAppend(DyBuffer *buffer, const char *data, int length) |
---|
131 | { |
---|
132 | int offset; |
---|
133 | |
---|
134 | assert(buffer != NULL); |
---|
135 | offset = buffer->used; |
---|
136 | dyBufferSetLength(buffer, offset + length); |
---|
137 | memcpy(buffer->data + offset, data, length); |
---|
138 | } |
---|
139 | |
---|
140 | static int |
---|
141 | bwrite(int sock, char *buffer, int size) |
---|
142 | { |
---|
143 | int result; |
---|
144 | int total = 0; |
---|
145 | int left = size; |
---|
146 | |
---|
147 | trace("bwrite: want to write %d bytes\n", size); |
---|
148 | while(1) { |
---|
149 | result = write(sock,buffer+total,left); |
---|
150 | |
---|
151 | if (result <= 0) |
---|
152 | break; |
---|
153 | |
---|
154 | total += result; |
---|
155 | left -= result; |
---|
156 | |
---|
157 | if (total == size) |
---|
158 | break; |
---|
159 | } |
---|
160 | trace("bwrite: wrote %d bytes\n", total); |
---|
161 | return(total); |
---|
162 | } |
---|
163 | |
---|
164 | static int |
---|
165 | bread(int sock, char *buffer, int size) |
---|
166 | { |
---|
167 | int result, total, left; |
---|
168 | |
---|
169 | for( total = 0, left = size; left > 0; left -= result) { |
---|
170 | result = read(sock,buffer+total,left); |
---|
171 | |
---|
172 | if (result > 0) { |
---|
173 | total += result; |
---|
174 | continue; |
---|
175 | } |
---|
176 | |
---|
177 | if ((result < 0) && (errno != EAGAIN) && (errno != EINTR)) { |
---|
178 | trace("pymolproxy: Error reading sock(%d), %d/%s\n", |
---|
179 | sock, errno,strerror(errno)); |
---|
180 | break; |
---|
181 | } |
---|
182 | |
---|
183 | result = 0; |
---|
184 | } |
---|
185 | return(total); |
---|
186 | } |
---|
187 | |
---|
188 | #ifdef notdef |
---|
189 | |
---|
190 | static int |
---|
191 | bflush(int sock, char *buffer, int size, int bytes) |
---|
192 | { |
---|
193 | int bsize; |
---|
194 | |
---|
195 | while(bytes) { |
---|
196 | if (bytes > size) |
---|
197 | bsize = size; |
---|
198 | else |
---|
199 | bsize = bytes; |
---|
200 | |
---|
201 | bsize = bread(sock,buffer,bsize); |
---|
202 | |
---|
203 | bytes -= bsize; |
---|
204 | } |
---|
205 | } |
---|
206 | |
---|
207 | #undef timersub |
---|
208 | static void |
---|
209 | timersub(struct timeval *a, struct timeval *b, struct timeval *result) |
---|
210 | { |
---|
211 | result->tv_sec = a->tv_sec - b->tv_sec; |
---|
212 | result->tv_usec = a->tv_usec - b->tv_usec; |
---|
213 | |
---|
214 | while(result->tv_usec < 0) { |
---|
215 | result->tv_sec -= 1; |
---|
216 | result->tv_usec += 1000000; |
---|
217 | } |
---|
218 | } |
---|
219 | |
---|
220 | #endif |
---|
221 | |
---|
222 | static void |
---|
223 | timersub_ms(struct timeval *a, struct timeval *b, int *result) |
---|
224 | { |
---|
225 | struct timeval tmp; |
---|
226 | |
---|
227 | tmp.tv_sec = a->tv_sec - b->tv_sec; |
---|
228 | tmp.tv_usec = a->tv_usec - b->tv_usec; |
---|
229 | |
---|
230 | while(tmp.tv_usec < 0) { |
---|
231 | tmp.tv_sec -= 1; |
---|
232 | tmp.tv_usec += 1000000; |
---|
233 | } |
---|
234 | |
---|
235 | *result = (tmp.tv_sec * 1000) + (tmp.tv_usec / 1000); |
---|
236 | } |
---|
237 | |
---|
238 | #undef timeradd |
---|
239 | static void |
---|
240 | timeradd (struct timeval *a, struct timeval *b, struct timeval *result) |
---|
241 | { |
---|
242 | result->tv_sec = a->tv_sec + b->tv_sec; |
---|
243 | result->tv_usec = a->tv_usec + b->tv_usec; |
---|
244 | |
---|
245 | while (result->tv_usec >= 1000000) { |
---|
246 | result->tv_sec += 1; |
---|
247 | result->tv_usec -= 1000000; |
---|
248 | } |
---|
249 | } |
---|
250 | |
---|
251 | static void |
---|
252 | timerset_ms(struct timeval *result, int timeout) |
---|
253 | { |
---|
254 | result->tv_sec = timeout / 1000; |
---|
255 | result->tv_usec = (timeout % 1000) * 1000; |
---|
256 | } |
---|
257 | |
---|
258 | static int |
---|
259 | getline(int sock, char *buffer, int size, long timeout) |
---|
260 | { |
---|
261 | int pos = 0, status, timeo; |
---|
262 | struct timeval now, end, tmo; |
---|
263 | struct pollfd ufd; |
---|
264 | |
---|
265 | gettimeofday(&now,NULL); |
---|
266 | timerset_ms(&tmo, timeout); |
---|
267 | timeradd(&now,&tmo,&end); |
---|
268 | |
---|
269 | ufd.fd = sock; |
---|
270 | ufd.events = POLLIN; |
---|
271 | |
---|
272 | size--; |
---|
273 | |
---|
274 | while(pos < size) { |
---|
275 | if (timeout > 0) { |
---|
276 | gettimeofday(&now,NULL); |
---|
277 | timersub_ms(&now,&end,&timeo); |
---|
278 | } |
---|
279 | else |
---|
280 | timeo = -1; |
---|
281 | |
---|
282 | status = poll(&ufd, 1, timeo); |
---|
283 | |
---|
284 | if (status > 0) |
---|
285 | status = read(sock,&buffer[pos],1); |
---|
286 | |
---|
287 | if ( (status < 0) && ( (errno == EINTR) || (errno == EAGAIN) ) ) |
---|
288 | continue; /* try again, if interrupted/blocking */ |
---|
289 | |
---|
290 | if (status <= 0) |
---|
291 | break; |
---|
292 | |
---|
293 | if (buffer[pos] == '\n') { |
---|
294 | pos++; |
---|
295 | break; |
---|
296 | } |
---|
297 | pos++; |
---|
298 | } |
---|
299 | |
---|
300 | buffer[pos]=0; |
---|
301 | |
---|
302 | return(pos); |
---|
303 | } |
---|
304 | |
---|
305 | static int |
---|
306 | waitForString(PymolProxy *pymol, char *string, char *buffer, int length) |
---|
307 | { |
---|
308 | int sock; |
---|
309 | |
---|
310 | assert(buffer != NULL); |
---|
311 | if (pymol->status != TCL_OK) |
---|
312 | return pymol->status; |
---|
313 | |
---|
314 | sock = pymol->p_stdout; |
---|
315 | trace("want to match (%s)\n", string); |
---|
316 | while(1) { |
---|
317 | if (getline(sock,buffer,length,IO_TIMEOUT) == 0) { |
---|
318 | pymol->error = 2; |
---|
319 | pymol->status = TCL_ERROR; |
---|
320 | break; |
---|
321 | } |
---|
322 | trace("stdout-u>read(%s)", buffer); |
---|
323 | if (strncmp(buffer, string, strlen(string)) == 0) { |
---|
324 | trace("stdout-e> %s",buffer); |
---|
325 | pymol->error = 0; |
---|
326 | pymol->status = TCL_OK; |
---|
327 | break; |
---|
328 | } |
---|
329 | } |
---|
330 | |
---|
331 | return pymol->status; |
---|
332 | } |
---|
333 | |
---|
334 | INLINE static int |
---|
335 | clear_error(PymolProxy *pymol) |
---|
336 | { |
---|
337 | pymol->error = 0; |
---|
338 | pymol->status = TCL_OK; |
---|
339 | return pymol->status; |
---|
340 | } |
---|
341 | |
---|
342 | static int |
---|
343 | send_expect(PymolProxy *pymol, char *expect, char *cmd) |
---|
344 | { |
---|
345 | if (pymol->error) { |
---|
346 | return(TCL_ERROR); |
---|
347 | } |
---|
348 | trace("to-pymol>(%s)", cmd); |
---|
349 | write(pymol->p_stdin, cmd, strlen(cmd)); |
---|
350 | if (waitForString(pymol, expect, cmd, 800)) { |
---|
351 | trace("pymolproxy: Timeout reading data [%s]\n",cmd); |
---|
352 | pymol->error = 1; |
---|
353 | pymol->status = TCL_ERROR; |
---|
354 | return pymol->status; |
---|
355 | } |
---|
356 | return( pymol->status ); |
---|
357 | } |
---|
358 | |
---|
359 | static int |
---|
360 | sendf(PymolProxy *pymol, char *format, ...) |
---|
361 | { |
---|
362 | va_list ap; |
---|
363 | char buffer[800]; |
---|
364 | |
---|
365 | if (pymol->error) |
---|
366 | return(TCL_ERROR); |
---|
367 | |
---|
368 | va_start(ap, format); |
---|
369 | vsnprintf(buffer, 800, format, ap); |
---|
370 | va_end(ap); |
---|
371 | trace("to-pymol>(%s)", buffer); |
---|
372 | write(pymol->p_stdin, buffer, strlen(buffer)); |
---|
373 | |
---|
374 | if (waitForString(pymol, "PyMOL>", buffer, 800)) { |
---|
375 | trace("pymolproxy: Timeout reading data [%s]\n",buffer); |
---|
376 | pymol->error = 1; |
---|
377 | pymol->status = TCL_ERROR; |
---|
378 | return pymol->status; |
---|
379 | } |
---|
380 | |
---|
381 | return( pymol->status ); |
---|
382 | } |
---|
383 | |
---|
384 | static int |
---|
385 | BallNStickCmd(ClientData cdata, Tcl_Interp *interp, int argc, const char *argv[]) |
---|
386 | { |
---|
387 | int ghost = 0, defer = 0, push = 0, arg; |
---|
388 | const char *model = "all"; |
---|
389 | PymolProxy *pymol = (PymolProxy *) cdata; |
---|
390 | |
---|
391 | clear_error(pymol); |
---|
392 | |
---|
393 | for(arg = 1; arg < argc; arg++) { |
---|
394 | if ( strcmp(argv[arg],"-defer") == 0 ) |
---|
395 | defer = 1; |
---|
396 | else if (strcmp(argv[arg],"-push") == 0) |
---|
397 | push = 1; |
---|
398 | else if (strcmp(argv[arg],"-ghost") == 0) |
---|
399 | ghost = 1; |
---|
400 | else if (strcmp(argv[arg],"-normal") == 0) |
---|
401 | ghost = 0; |
---|
402 | else if (strcmp(argv[arg],"-model") == 0) { |
---|
403 | if (++arg < argc) |
---|
404 | model = argv[arg]; |
---|
405 | } |
---|
406 | else |
---|
407 | model = argv[arg]; |
---|
408 | } |
---|
409 | |
---|
410 | pymol->invalidate_cache = 1; |
---|
411 | pymol->need_update = !defer || push; |
---|
412 | pymol->immediate_update |= push; |
---|
413 | |
---|
414 | sendf(pymol, "hide everything,%s\n",model); |
---|
415 | sendf(pymol, "set stick_color,white,%s\n",model); |
---|
416 | |
---|
417 | if (ghost) |
---|
418 | sendf(pymol, "set stick_radius,0.1,%s\n",model); |
---|
419 | else |
---|
420 | sendf(pymol, "set stick_radius,0.14,%s\n",model); |
---|
421 | |
---|
422 | sendf(pymol, "set sphere_scale=0.25,%s\n", model); |
---|
423 | |
---|
424 | if (ghost) { |
---|
425 | sendf(pymol, "set sphere_transparency,0.75,%s\n", model); |
---|
426 | sendf(pymol, "set stick_transparency,0.75,%s\n", model); |
---|
427 | } |
---|
428 | else { |
---|
429 | sendf(pymol, "set sphere_transparency,0,%s\n", model); |
---|
430 | sendf(pymol, "set stick_transparency,0,%s\n", model); |
---|
431 | } |
---|
432 | |
---|
433 | sendf(pymol, "show sticks,%s\n",model); |
---|
434 | sendf(pymol, "show spheres,%s\n",model); |
---|
435 | |
---|
436 | if (pymol->labels) |
---|
437 | sendf(pymol, "show labels,%s\n", model); |
---|
438 | |
---|
439 | return( pymol->status ); |
---|
440 | } |
---|
441 | |
---|
442 | static int |
---|
443 | SpheresCmd(ClientData cdata, Tcl_Interp *interp, int argc, const char *argv[]) |
---|
444 | { |
---|
445 | int defer = 0, ghost = 0, push = 0, arg; |
---|
446 | const char *model = "all"; |
---|
447 | PymolProxy *pymol = (PymolProxy *) cdata; |
---|
448 | |
---|
449 | clear_error(pymol); |
---|
450 | |
---|
451 | for(arg = 1; arg < argc; arg++) { |
---|
452 | if ( strcmp(argv[arg],"-defer") == 0 ) |
---|
453 | defer = 1; |
---|
454 | else if (strcmp(argv[arg],"-push") == 0) |
---|
455 | push = 1; |
---|
456 | else if (strcmp(argv[arg],"-ghost") == 0) |
---|
457 | ghost = 1; |
---|
458 | else if (strcmp(argv[arg],"-normal") == 0) |
---|
459 | ghost = 0; |
---|
460 | else if (strcmp(argv[arg],"-model") == 0) { |
---|
461 | if (++arg < argc) |
---|
462 | model = argv[arg]; |
---|
463 | } |
---|
464 | else |
---|
465 | model = argv[arg]; |
---|
466 | } |
---|
467 | |
---|
468 | pymol->invalidate_cache = 1; |
---|
469 | pymol->need_update = !defer || push; |
---|
470 | pymol->immediate_update |= push; |
---|
471 | |
---|
472 | sendf(pymol, "hide everything, %s\n", model); |
---|
473 | sendf(pymol, "set sphere_scale,0.41,%s\n", model); |
---|
474 | //sendf(pymol, "set sphere_quality,2,%s\n", model); |
---|
475 | sendf(pymol, "set ambient,.2,%s\n", model); |
---|
476 | |
---|
477 | if (ghost) |
---|
478 | sendf(pymol, "set sphere_transparency,.75,%s\n", model); |
---|
479 | else |
---|
480 | sendf(pymol, "set sphere_transparency,0,%s\n", model); |
---|
481 | |
---|
482 | sendf(pymol, "show spheres,%s\n", model); |
---|
483 | |
---|
484 | if (pymol->labels) |
---|
485 | sendf(pymol, "show labels,%s\n", model); |
---|
486 | |
---|
487 | return pymol->status; |
---|
488 | } |
---|
489 | |
---|
490 | static int |
---|
491 | LinesCmd(ClientData cdata, Tcl_Interp *interp, int argc, const char *argv[]) |
---|
492 | { |
---|
493 | int ghost = 0, defer = 0, push = 0, arg; |
---|
494 | const char *model = "all"; |
---|
495 | PymolProxy *pymol = (PymolProxy *) cdata; |
---|
496 | |
---|
497 | clear_error(pymol); |
---|
498 | |
---|
499 | for(arg = 1; arg < argc; arg++) { |
---|
500 | if ( strcmp(argv[arg],"-defer") == 0 ) |
---|
501 | defer = 1; |
---|
502 | else if (strcmp(argv[arg],"-push") == 0) |
---|
503 | push = 1; |
---|
504 | else if (strcmp(argv[arg],"-ghost") == 0) |
---|
505 | ghost = 1; |
---|
506 | else if (strcmp(argv[arg],"-normal") == 0) |
---|
507 | ghost = 0; |
---|
508 | else if (strcmp(argv[arg],"-model") == 0) { |
---|
509 | if (++arg < argc) |
---|
510 | model = argv[arg]; |
---|
511 | } |
---|
512 | else |
---|
513 | model = argv[arg]; |
---|
514 | } |
---|
515 | |
---|
516 | pymol->invalidate_cache = 1; |
---|
517 | pymol->need_update = !defer || push; |
---|
518 | pymol->immediate_update |= push; |
---|
519 | |
---|
520 | sendf(pymol, "hide everything,%s\n",model); |
---|
521 | |
---|
522 | if (ghost) |
---|
523 | sendf(pymol, "set line_width,.25,%s\n",model); |
---|
524 | else |
---|
525 | sendf(pymol, "set line_width,1,%s\n",model); |
---|
526 | |
---|
527 | sendf(pymol, "show lines,%s\n",model); |
---|
528 | |
---|
529 | if (pymol->labels) |
---|
530 | sendf(pymol, "show labels,%s\n",model); |
---|
531 | |
---|
532 | return pymol->status; |
---|
533 | } |
---|
534 | |
---|
535 | static int |
---|
536 | DisableCmd(ClientData cdata, Tcl_Interp *interp, int argc, const char *argv[]) |
---|
537 | { |
---|
538 | PymolProxy *pymol = (PymolProxy *) cdata; |
---|
539 | const char *model = "all"; |
---|
540 | int arg, defer = 0, push = 0; |
---|
541 | |
---|
542 | clear_error(pymol); |
---|
543 | |
---|
544 | for(arg = 1; arg < argc; arg++) { |
---|
545 | |
---|
546 | if (strcmp(argv[arg], "-defer") == 0 ) |
---|
547 | defer = 1; |
---|
548 | else if (strcmp(argv[arg], "-push") == 0 ) |
---|
549 | push = 1; |
---|
550 | else |
---|
551 | model = argv[arg]; |
---|
552 | |
---|
553 | } |
---|
554 | |
---|
555 | pymol->need_update = !defer || push; |
---|
556 | pymol->immediate_update |= push; |
---|
557 | pymol->invalidate_cache = 1; |
---|
558 | |
---|
559 | sendf( pymol, "disable %s\n", model); |
---|
560 | |
---|
561 | return pymol->status; |
---|
562 | } |
---|
563 | |
---|
564 | static int |
---|
565 | EnableCmd(ClientData cdata, Tcl_Interp *interp, int argc, const char *argv[]) |
---|
566 | { |
---|
567 | PymolProxy *pymol = (PymolProxy *) cdata; |
---|
568 | const char *model = "all"; |
---|
569 | int arg, defer = 0, push = 0; |
---|
570 | |
---|
571 | clear_error(pymol); |
---|
572 | |
---|
573 | for(arg = 1; arg < argc; arg++) { |
---|
574 | |
---|
575 | if (strcmp(argv[arg],"-defer") == 0) |
---|
576 | defer = 1; |
---|
577 | else if (strcmp(argv[arg], "-push") == 0 ) |
---|
578 | push = 1; |
---|
579 | else |
---|
580 | model = argv[arg]; |
---|
581 | |
---|
582 | } |
---|
583 | |
---|
584 | pymol->need_update = !defer || push; |
---|
585 | pymol->immediate_update |= push; |
---|
586 | pymol->invalidate_cache = 1; |
---|
587 | |
---|
588 | sendf( pymol, "enable %s\n", model); |
---|
589 | |
---|
590 | return pymol->status; |
---|
591 | } |
---|
592 | |
---|
593 | static int |
---|
594 | VMouseCmd(ClientData cdata, Tcl_Interp *interp, int argc, const char *argv[]) |
---|
595 | { |
---|
596 | PymolProxy *pymol = (PymolProxy *) cdata; |
---|
597 | int arg, defer = 0, push = 0, varg = 1; |
---|
598 | int arg1 = 0, arg2 = 0, arg3 = 0, arg4 = 0, arg5 = 0; |
---|
599 | |
---|
600 | clear_error(pymol); |
---|
601 | |
---|
602 | for(arg = 1; arg < argc; arg++) { |
---|
603 | if (strcmp(argv[arg], "-defer") == 0) |
---|
604 | defer = 1; |
---|
605 | else if (strcmp(argv[arg], "-push") == 0) |
---|
606 | push = 1; |
---|
607 | else if (varg == 1) { |
---|
608 | arg1 = atoi(argv[arg]); |
---|
609 | varg++; |
---|
610 | } |
---|
611 | else if (varg == 2) { |
---|
612 | arg2 = atoi(argv[arg]); |
---|
613 | varg++; |
---|
614 | } |
---|
615 | else if (varg == 3) { |
---|
616 | arg3 = atoi(argv[arg]); |
---|
617 | varg++; |
---|
618 | } |
---|
619 | else if (varg == 4) { |
---|
620 | arg4 = atoi(argv[arg]); |
---|
621 | varg++; |
---|
622 | } |
---|
623 | else if (varg == 5) { |
---|
624 | arg5 = atoi(argv[arg]); |
---|
625 | varg++; |
---|
626 | } |
---|
627 | } |
---|
628 | |
---|
629 | pymol->need_update = !defer || push; |
---|
630 | pymol->immediate_update |= push; |
---|
631 | pymol->invalidate_cache = 1; |
---|
632 | |
---|
633 | sendf(pymol, "vmouse %d,%d,%d,%d,%d\n", arg1,arg2,arg3,arg4,arg5); |
---|
634 | |
---|
635 | return pymol->status; |
---|
636 | } |
---|
637 | |
---|
638 | static int |
---|
639 | RawCmd(ClientData cdata, Tcl_Interp *interp, int argc, const char *argv[]) |
---|
640 | { |
---|
641 | PymolProxy *pymol = (PymolProxy *) cdata; |
---|
642 | DyBuffer buffer; |
---|
643 | int arg, defer = 0, push = 0; |
---|
644 | const char *cmd; |
---|
645 | clear_error(pymol); |
---|
646 | |
---|
647 | dyBufferInit(&buffer); |
---|
648 | |
---|
649 | cmd = NULL; |
---|
650 | for(arg = 1; arg < argc; arg++) { |
---|
651 | if (strcmp(argv[arg], "-defer") == 0) |
---|
652 | defer = 1; |
---|
653 | else if (strcmp(argv[arg], "-push") == 0) |
---|
654 | push = 1; |
---|
655 | else { |
---|
656 | cmd = argv[arg]; |
---|
657 | } |
---|
658 | } |
---|
659 | |
---|
660 | pymol->need_update = !defer || push; |
---|
661 | pymol->immediate_update |= push; |
---|
662 | pymol->invalidate_cache = 1; |
---|
663 | |
---|
664 | sendf(pymol,"%s\n", cmd); |
---|
665 | dyBufferFree(&buffer); |
---|
666 | |
---|
667 | return pymol->status; |
---|
668 | } |
---|
669 | |
---|
670 | static int |
---|
671 | LabelCmd(ClientData cdata, Tcl_Interp *interp, int argc, const char *argv[]) |
---|
672 | { |
---|
673 | PymolProxy *pymol = (PymolProxy *) cdata; |
---|
674 | int state = 1; |
---|
675 | int arg, push = 0, defer = 0; |
---|
676 | |
---|
677 | clear_error(pymol); |
---|
678 | |
---|
679 | for(arg = 1; arg < argc; arg++) { |
---|
680 | if ( strcmp(argv[arg],"-defer") == 0 ) |
---|
681 | defer = 1; |
---|
682 | else if (strcmp(argv[arg],"-push") == 0 ) |
---|
683 | push = 1; |
---|
684 | else if (strcmp(argv[arg],"on") == 0 ) |
---|
685 | state = 1; |
---|
686 | else if (strcmp(argv[arg],"off") == 0 ) |
---|
687 | state = 0; |
---|
688 | else if (strcmp(argv[arg],"toggle") == 0 ) |
---|
689 | state = !pymol->labels; |
---|
690 | } |
---|
691 | |
---|
692 | pymol->need_update = !defer || push; |
---|
693 | pymol->immediate_update |= push; |
---|
694 | pymol->invalidate_cache = 1; |
---|
695 | |
---|
696 | if (state) { |
---|
697 | sendf(pymol, "set label_color,white,all\n"); |
---|
698 | sendf(pymol, "set label_size,14,all\n"); |
---|
699 | sendf(pymol, "label all,\"%%s%%s\" %% (ID,name)\n"); |
---|
700 | } |
---|
701 | else |
---|
702 | sendf(pymol, "label all\n"); |
---|
703 | |
---|
704 | pymol->labels = state; |
---|
705 | |
---|
706 | return pymol->status; |
---|
707 | } |
---|
708 | |
---|
709 | static int |
---|
710 | FrameCmd(ClientData cdata, Tcl_Interp *interp, int argc, const char *argv[]) |
---|
711 | { |
---|
712 | PymolProxy *pymol = (PymolProxy *) cdata; |
---|
713 | int frame = 0; |
---|
714 | int arg, push = 0, defer = 0; |
---|
715 | |
---|
716 | clear_error(pymol); |
---|
717 | |
---|
718 | for(arg = 1; arg < argc; arg++) { |
---|
719 | if ( strcmp(argv[arg],"-defer") == 0 ) |
---|
720 | defer = 1; |
---|
721 | else if (strcmp(argv[arg],"-push") == 0 ) |
---|
722 | push = 1; |
---|
723 | else |
---|
724 | frame = atoi(argv[arg]); |
---|
725 | } |
---|
726 | |
---|
727 | pymol->need_update = !defer || push; |
---|
728 | pymol->immediate_update |= push; |
---|
729 | |
---|
730 | pymol->frame = frame; |
---|
731 | |
---|
732 | sendf(pymol,"frame %d\n", frame); |
---|
733 | |
---|
734 | return pymol->status; |
---|
735 | } |
---|
736 | |
---|
737 | static int |
---|
738 | ResetCmd(ClientData cdata, Tcl_Interp *interp, int argc, const char *argv[]) |
---|
739 | { |
---|
740 | PymolProxy *pymol = (PymolProxy *) cdata; |
---|
741 | int arg, push = 0, defer = 0; |
---|
742 | |
---|
743 | clear_error(pymol); |
---|
744 | |
---|
745 | for(arg = 1; arg < argc; arg++) { |
---|
746 | if ( strcmp(argv[arg],"-defer") == 0 ) |
---|
747 | defer = 1; |
---|
748 | else if (strcmp(argv[arg],"-push") == 0 ) |
---|
749 | push = 1; |
---|
750 | } |
---|
751 | |
---|
752 | pymol->need_update = !defer || push; |
---|
753 | pymol->immediate_update |= push; |
---|
754 | pymol->invalidate_cache = 1; |
---|
755 | |
---|
756 | sendf(pymol, "reset\n"); |
---|
757 | sendf(pymol, "zoom buffer=2\n"); |
---|
758 | |
---|
759 | return pymol->status; |
---|
760 | } |
---|
761 | |
---|
762 | static int |
---|
763 | RockCmd(ClientData cdata, Tcl_Interp *interp, int argc, const char *argv[]) |
---|
764 | { |
---|
765 | PymolProxy *pymol = (PymolProxy *) cdata; |
---|
766 | float y = 0.0; |
---|
767 | int arg, push = 0, defer = 0; |
---|
768 | |
---|
769 | clear_error(pymol); |
---|
770 | |
---|
771 | for(arg = 1; arg < argc; arg++) { |
---|
772 | if ( strcmp(argv[arg],"-defer") == 0 ) |
---|
773 | defer = 1; |
---|
774 | else if (strcmp(argv[arg],"-push") == 0 ) |
---|
775 | push = 1; |
---|
776 | else |
---|
777 | y = atof( argv[arg] ); |
---|
778 | } |
---|
779 | |
---|
780 | pymol->need_update = !defer || push; |
---|
781 | pymol->immediate_update |= push; |
---|
782 | |
---|
783 | sendf(pymol,"turn y, %f\n", y - pymol->rock_offset); |
---|
784 | |
---|
785 | pymol->rock_offset = y; |
---|
786 | |
---|
787 | return pymol->status; |
---|
788 | } |
---|
789 | |
---|
790 | static int |
---|
791 | ViewportCmd(ClientData cdata, Tcl_Interp *interp, int argc, const char *argv[]) |
---|
792 | { |
---|
793 | PymolProxy *pymol = (PymolProxy *) cdata; |
---|
794 | int width = 640, height = 480; |
---|
795 | int defer = 0, push = 0, arg, varg = 1; |
---|
796 | |
---|
797 | clear_error(pymol); |
---|
798 | |
---|
799 | for(arg = 1; arg < argc; arg++) { |
---|
800 | if ( strcmp(argv[arg],"-defer") == 0 ) |
---|
801 | defer = 1; |
---|
802 | else if ( strcmp(argv[arg], "-push") == 0 ) |
---|
803 | push = 1; |
---|
804 | else if (varg == 1) { |
---|
805 | width = atoi(argv[arg]); |
---|
806 | height = width; |
---|
807 | varg++; |
---|
808 | } |
---|
809 | else if (varg == 2) { |
---|
810 | height = atoi(argv[arg]); |
---|
811 | varg++; |
---|
812 | } |
---|
813 | } |
---|
814 | |
---|
815 | pymol->need_update = !defer || push; |
---|
816 | pymol->immediate_update |= push; |
---|
817 | pymol->invalidate_cache = 1; |
---|
818 | |
---|
819 | sendf(pymol, "viewport %d,%d\n", width, height); |
---|
820 | |
---|
821 | //usleep(205000); // .2s delay for pymol to update its geometry *HACK ALERT* |
---|
822 | |
---|
823 | return pymol->status; |
---|
824 | } |
---|
825 | |
---|
826 | static int |
---|
827 | LoadPDBCmd(ClientData cdata, Tcl_Interp *interp, int argc, const char *argv[]) |
---|
828 | { |
---|
829 | const char *pdbdata, *name; |
---|
830 | PymolProxy *pymol = (PymolProxy *) cdata; |
---|
831 | int state = 1; |
---|
832 | int arg, defer = 0, push = 0, varg = 1; |
---|
833 | |
---|
834 | clear_error(pymol); |
---|
835 | |
---|
836 | pdbdata = name = NULL; /* Suppress compiler warning. */ |
---|
837 | for(arg = 1; arg < argc; arg++) { |
---|
838 | if ( strcmp(argv[arg],"-defer") == 0 ) |
---|
839 | defer = 1; |
---|
840 | else if (strcmp(argv[arg],"-push") == 0) |
---|
841 | push = 1; |
---|
842 | else if (varg == 1) { |
---|
843 | pdbdata = argv[arg]; |
---|
844 | varg++; |
---|
845 | } |
---|
846 | else if (varg == 2) { |
---|
847 | name = argv[arg]; |
---|
848 | varg++; |
---|
849 | } |
---|
850 | else if (varg == 3) { |
---|
851 | state = atoi( argv[arg] ); |
---|
852 | varg++; |
---|
853 | } |
---|
854 | } |
---|
855 | |
---|
856 | pymol->need_update = !defer || push; |
---|
857 | pymol->immediate_update |= push; |
---|
858 | |
---|
859 | { |
---|
860 | int count; |
---|
861 | const char *p; |
---|
862 | char *q, *newdata; |
---|
863 | |
---|
864 | count = 0; |
---|
865 | for (p = pdbdata; *p != '\0'; p++) { |
---|
866 | if (*p == '\n') { |
---|
867 | count++; |
---|
868 | } |
---|
869 | count++; |
---|
870 | } |
---|
871 | |
---|
872 | q = newdata = malloc(count + 100); |
---|
873 | strcpy(newdata, "cmd.read_pdbstr(\"\"\"\\\n"); |
---|
874 | q = newdata + strlen(newdata); |
---|
875 | for (p = pdbdata; *p != '\0'; p++, q++) { |
---|
876 | if (*p == '\n') { |
---|
877 | *q++ = '\\'; |
---|
878 | } |
---|
879 | *q = *p; |
---|
880 | } |
---|
881 | sprintf(q, "\\\n\"\"\",\"%s\",%d)\n", name, state); |
---|
882 | { |
---|
883 | char expect[800]; |
---|
884 | |
---|
885 | sprintf(expect, "PyMOL>\"\"\",\"%s\",%d)\n", name, state); |
---|
886 | send_expect(pymol, expect, newdata); |
---|
887 | } |
---|
888 | free(newdata); |
---|
889 | } |
---|
890 | sendf(pymol, "zoom buffer=2\n"); |
---|
891 | |
---|
892 | return pymol->status; |
---|
893 | } |
---|
894 | |
---|
895 | static int |
---|
896 | RotateCmd(ClientData cdata, Tcl_Interp *interp, int argc, const char *argv[]) |
---|
897 | { |
---|
898 | double turnx = 0.0; |
---|
899 | double turny = 0.0; |
---|
900 | double turnz = 0.0; |
---|
901 | PymolProxy *pymol = (PymolProxy *) cdata; |
---|
902 | int defer = 0, push = 0, arg, varg = 1; |
---|
903 | |
---|
904 | clear_error(pymol); |
---|
905 | |
---|
906 | for(arg = 1; arg < argc; arg++) |
---|
907 | { |
---|
908 | if (strcmp(argv[arg],"-defer") == 0) |
---|
909 | defer = 1; |
---|
910 | else if (strcmp(argv[arg],"-push") == 0) |
---|
911 | push = 1; |
---|
912 | else if (varg == 1) { |
---|
913 | turnx = atof(argv[arg]); |
---|
914 | varg++; |
---|
915 | } |
---|
916 | else if (varg == 2) { |
---|
917 | turny = atof(argv[arg]); |
---|
918 | varg++; |
---|
919 | } |
---|
920 | else if (varg == 3) { |
---|
921 | turnz = atof(argv[arg]); |
---|
922 | varg++; |
---|
923 | } |
---|
924 | } |
---|
925 | |
---|
926 | pymol->need_update = !defer || push; |
---|
927 | pymol->immediate_update |= push; |
---|
928 | pymol->invalidate_cache = 1; |
---|
929 | |
---|
930 | if (turnx != 0.0) |
---|
931 | sendf(pymol,"turn x, %f\n", turnx); |
---|
932 | |
---|
933 | if (turny != 0.0) |
---|
934 | sendf(pymol,"turn y, %f\n", turny); |
---|
935 | |
---|
936 | if (turnz != 0.0) |
---|
937 | sendf(pymol,"turn z, %f\n", turnz); |
---|
938 | |
---|
939 | return pymol->status; |
---|
940 | } |
---|
941 | |
---|
942 | static int |
---|
943 | ZoomCmd(ClientData cdata, Tcl_Interp *interp, int argc, const char *argv[]) |
---|
944 | { |
---|
945 | double factor = 0.0; |
---|
946 | double zmove = 0.0; |
---|
947 | PymolProxy *pymol = (PymolProxy *) cdata; |
---|
948 | int defer = 0, push = 0, arg, varg = 1; |
---|
949 | |
---|
950 | clear_error(pymol); |
---|
951 | |
---|
952 | for(arg = 1; arg < argc; arg++) |
---|
953 | { |
---|
954 | if (strcmp(argv[arg],"-defer") == 0) |
---|
955 | defer = 1; |
---|
956 | else if (strcmp(argv[arg],"-push") == 0) |
---|
957 | push = 1; |
---|
958 | else if (varg == 1) { |
---|
959 | factor = atof(argv[arg]); |
---|
960 | varg++; |
---|
961 | } |
---|
962 | } |
---|
963 | |
---|
964 | zmove = factor * -75; |
---|
965 | |
---|
966 | pymol->need_update = !defer || push; |
---|
967 | pymol->immediate_update |= push; |
---|
968 | pymol->invalidate_cache = 1; |
---|
969 | |
---|
970 | if (zmove != 0.0) |
---|
971 | sendf(pymol,"move z, %f\n", factor); |
---|
972 | |
---|
973 | return pymol->status; |
---|
974 | } |
---|
975 | |
---|
976 | static int |
---|
977 | PNGCmd(ClientData cdata, Tcl_Interp *interp, int argc, const char *argv[]) |
---|
978 | { |
---|
979 | char buffer[800]; |
---|
980 | unsigned int bytes=0; |
---|
981 | float samples = 0.0; |
---|
982 | PymolProxy *pymol = (PymolProxy *) cdata; |
---|
983 | |
---|
984 | clear_error(pymol); |
---|
985 | |
---|
986 | if (pymol->invalidate_cache) |
---|
987 | pymol->cacheid++; |
---|
988 | |
---|
989 | pymol->need_update = 0; |
---|
990 | pymol->immediate_update = 0; |
---|
991 | pymol->invalidate_cache = 0; |
---|
992 | |
---|
993 | sendf(pymol,"png -\n"); |
---|
994 | |
---|
995 | waitForString(pymol, "image follows: ", buffer, 800); |
---|
996 | |
---|
997 | sscanf(buffer, "image follows: %d %f\n", &bytes, &samples); |
---|
998 | |
---|
999 | write(3,&samples,sizeof(samples)); |
---|
1000 | |
---|
1001 | dyBufferSetLength(&pymol->image, bytes); |
---|
1002 | |
---|
1003 | bread(pymol->p_stdout, pymol->image.data, pymol->image.used); |
---|
1004 | |
---|
1005 | waitForString(pymol, " ScenePNG", buffer,800); |
---|
1006 | |
---|
1007 | if (bytes && (pymol->image.used == bytes)) { |
---|
1008 | sprintf(buffer, "nv>image %d %d %d %d\n", |
---|
1009 | bytes, pymol->cacheid, pymol->frame, pymol->rock_offset); |
---|
1010 | trace("to-molvis> %s", buffer); |
---|
1011 | write(pymol->c_stdin, buffer, strlen(buffer)); |
---|
1012 | bwrite(pymol->c_stdin, pymol->image.data, bytes); |
---|
1013 | } |
---|
1014 | return pymol->status; |
---|
1015 | } |
---|
1016 | |
---|
1017 | static int |
---|
1018 | BMPCmd(ClientData cdata, Tcl_Interp *interp, int argc, const char *argv[]) |
---|
1019 | { |
---|
1020 | char buffer[800]; |
---|
1021 | unsigned int bytes=0; |
---|
1022 | float samples = 0.0; |
---|
1023 | PymolProxy *pymol = (PymolProxy *) cdata; |
---|
1024 | |
---|
1025 | clear_error(pymol); |
---|
1026 | |
---|
1027 | if (pymol->invalidate_cache) |
---|
1028 | pymol->cacheid++; |
---|
1029 | |
---|
1030 | pymol->need_update = 0; |
---|
1031 | pymol->immediate_update = 0; |
---|
1032 | pymol->invalidate_cache = 0; |
---|
1033 | |
---|
1034 | sendf(pymol,"bmp -\n"); |
---|
1035 | |
---|
1036 | waitForString(pymol, "image follows: ", buffer, 800); |
---|
1037 | |
---|
1038 | sscanf(buffer, "image follows: %d %f\n", &bytes, &samples); |
---|
1039 | write(3,&samples,sizeof(samples)); |
---|
1040 | |
---|
1041 | dyBufferSetLength(&pymol->image, bytes); |
---|
1042 | |
---|
1043 | bread(pymol->p_stdout, pymol->image.data, pymol->image.used); |
---|
1044 | |
---|
1045 | if (bytes && (pymol->image.used == bytes)) { |
---|
1046 | sprintf(buffer, "nv>image %d %d %d %d\n", |
---|
1047 | bytes, pymol->cacheid, pymol->frame, pymol->rock_offset); |
---|
1048 | write(pymol->c_stdin, buffer, strlen(buffer)); |
---|
1049 | trace("to-molvis buffer=%s\n", buffer); |
---|
1050 | bwrite(pymol->c_stdin, pymol->image.data, bytes); |
---|
1051 | } |
---|
1052 | return pymol->status; |
---|
1053 | } |
---|
1054 | |
---|
1055 | static int |
---|
1056 | ProxyInit(int c_in, int c_out, char *const *argv) |
---|
1057 | { |
---|
1058 | int flags, status, result = 0; |
---|
1059 | int pairIn[2]; |
---|
1060 | int pairOut[2]; |
---|
1061 | int pairErr[2]; |
---|
1062 | Tcl_Interp *interp; |
---|
1063 | Tcl_DString cmdbuffer; |
---|
1064 | DyBuffer dybuffer, dybuffer2; |
---|
1065 | struct pollfd ufd[3]; |
---|
1066 | int pid; |
---|
1067 | PymolProxy pymol; |
---|
1068 | struct timeval now,end; |
---|
1069 | int timeout; |
---|
1070 | |
---|
1071 | /* Create three pipes for communication with the external application. One |
---|
1072 | * each for the applications's: stdin, stdout, and stderr */ |
---|
1073 | |
---|
1074 | if (pipe(pairIn) == -1) |
---|
1075 | return(-1); |
---|
1076 | |
---|
1077 | if (pipe(pairOut) == -1) { |
---|
1078 | close(pairIn[0]); |
---|
1079 | close(pairIn[1]); |
---|
1080 | return(-1); |
---|
1081 | } |
---|
1082 | |
---|
1083 | if (pipe(pairErr) == -1) { |
---|
1084 | close(pairIn[0]); |
---|
1085 | close(pairIn[1]); |
---|
1086 | close(pairOut[0]); |
---|
1087 | close(pairOut[1]); |
---|
1088 | return(-1); |
---|
1089 | } |
---|
1090 | |
---|
1091 | /* Fork the new process. Connect i/o to the new socket. */ |
---|
1092 | |
---|
1093 | pid = fork(); |
---|
1094 | |
---|
1095 | if (pid < 0) { |
---|
1096 | fprintf(stderr, "can't fork process: %s\n", strerror(errno)); |
---|
1097 | return(-3); |
---|
1098 | } |
---|
1099 | if (pid == 0) { |
---|
1100 | int fd; |
---|
1101 | |
---|
1102 | /* Child process */ |
---|
1103 | |
---|
1104 | /* |
---|
1105 | * Create a new process group, so we can later kill this process and |
---|
1106 | * all its children without affecting the process that created this |
---|
1107 | * one. |
---|
1108 | */ |
---|
1109 | setpgid(pid, 0); |
---|
1110 | |
---|
1111 | /* Redirect stdin, stdout, and stderr to pipes before execing */ |
---|
1112 | dup2(pairIn[0] ,0); // stdin |
---|
1113 | dup2(pairOut[1],1); // stdout |
---|
1114 | dup2(pairErr[1],2); // stderr |
---|
1115 | |
---|
1116 | for(fd = 3; fd < FD_SETSIZE; fd++) /* close all other descriptors */ |
---|
1117 | close(fd); |
---|
1118 | |
---|
1119 | execvp(argv[0], argv); |
---|
1120 | trace("pymolproxy: Failed to start pyMol %s\n", argv[0]); |
---|
1121 | exit(-1); |
---|
1122 | } |
---|
1123 | |
---|
1124 | /* close opposite end of pipe, these now belong to the child process */ |
---|
1125 | close(pairIn[0]); |
---|
1126 | close(pairOut[1]); |
---|
1127 | close(pairErr[1]); |
---|
1128 | |
---|
1129 | signal(SIGPIPE, SIG_IGN); // ignore SIGPIPE (ie if nanoscale terminates) |
---|
1130 | |
---|
1131 | pymol.p_stdin = pairIn[1]; |
---|
1132 | pymol.p_stdout = pairOut[0]; |
---|
1133 | pymol.p_stderr = pairErr[0]; |
---|
1134 | pymol.c_stdin = c_in; |
---|
1135 | pymol.c_stdout = c_out; |
---|
1136 | pymol.labels = 0; |
---|
1137 | pymol.need_update = 0; |
---|
1138 | pymol.can_update = 1; |
---|
1139 | pymol.immediate_update = 0; |
---|
1140 | pymol.sync = 0; |
---|
1141 | pymol.frame = 1; |
---|
1142 | pymol.rock_offset = 0; |
---|
1143 | pymol.cacheid = 0; |
---|
1144 | pymol.invalidate_cache = 0; |
---|
1145 | |
---|
1146 | ufd[0].fd = pymol.c_stdout; |
---|
1147 | ufd[0].events = POLLIN | POLLHUP; /* ensure catching EOF */ |
---|
1148 | ufd[1].fd = pymol.p_stdout; |
---|
1149 | ufd[1].events = POLLIN | POLLHUP; |
---|
1150 | ufd[2].fd = pymol.p_stderr; |
---|
1151 | ufd[2].events = POLLIN | POLLHUP; |
---|
1152 | |
---|
1153 | flags = fcntl(pymol.p_stdout, F_GETFL); |
---|
1154 | fcntl(pymol.p_stdout, F_SETFL, flags|O_NONBLOCK); |
---|
1155 | |
---|
1156 | interp = Tcl_CreateInterp(); |
---|
1157 | Tcl_MakeSafe(interp); |
---|
1158 | |
---|
1159 | Tcl_DStringInit(&cmdbuffer); |
---|
1160 | dyBufferInit(&pymol.image); |
---|
1161 | dyBufferInit(&dybuffer); |
---|
1162 | dyBufferInit(&dybuffer2); |
---|
1163 | |
---|
1164 | Tcl_CreateCommand(interp, "bmp", BMPCmd, &pymol, NULL); |
---|
1165 | Tcl_CreateCommand(interp, "png", PNGCmd, &pymol, NULL); |
---|
1166 | Tcl_CreateCommand(interp, "screen", ViewportCmd, &pymol, NULL); |
---|
1167 | Tcl_CreateCommand(interp, "viewport",ViewportCmd, &pymol, NULL); |
---|
1168 | Tcl_CreateCommand(interp, "rotate", RotateCmd, &pymol, NULL); |
---|
1169 | Tcl_CreateCommand(interp, "zoom", ZoomCmd, &pymol, NULL); |
---|
1170 | Tcl_CreateCommand(interp, "loadpdb", LoadPDBCmd, &pymol, NULL); |
---|
1171 | Tcl_CreateCommand(interp, "ballnstick",BallNStickCmd, &pymol, NULL); |
---|
1172 | Tcl_CreateCommand(interp, "spheres", SpheresCmd, &pymol, NULL); |
---|
1173 | Tcl_CreateCommand(interp, "lines", LinesCmd, &pymol, NULL); |
---|
1174 | Tcl_CreateCommand(interp, "raw", RawCmd, &pymol, NULL); |
---|
1175 | Tcl_CreateCommand(interp, "label", LabelCmd, &pymol, NULL); |
---|
1176 | Tcl_CreateCommand(interp, "reset", ResetCmd, &pymol, NULL); |
---|
1177 | Tcl_CreateCommand(interp, "rock", RockCmd, &pymol, NULL); |
---|
1178 | Tcl_CreateCommand(interp, "frame", FrameCmd, &pymol, NULL); |
---|
1179 | Tcl_CreateCommand(interp, "vmouse", VMouseCmd, &pymol, NULL); |
---|
1180 | Tcl_CreateCommand(interp, "disable", DisableCmd, &pymol, NULL); |
---|
1181 | Tcl_CreateCommand(interp, "enable", EnableCmd, &pymol, NULL); |
---|
1182 | |
---|
1183 | // Main Proxy Loop |
---|
1184 | // accept tcl commands from socket |
---|
1185 | // translate them into pyMol commands, and issue them to child proccess |
---|
1186 | // send images back |
---|
1187 | |
---|
1188 | gettimeofday(&end, NULL); |
---|
1189 | |
---|
1190 | while(1) |
---|
1191 | { |
---|
1192 | char ch; |
---|
1193 | |
---|
1194 | gettimeofday(&now,NULL); |
---|
1195 | |
---|
1196 | if ( (!pymol.need_update) ) |
---|
1197 | timeout = -1; |
---|
1198 | else if ((now.tv_sec > end.tv_sec) || ( (now.tv_sec == end.tv_sec) && (now.tv_usec >= end.tv_usec)) ) |
---|
1199 | timeout = 0; |
---|
1200 | else |
---|
1201 | { |
---|
1202 | timeout = (end.tv_sec - now.tv_sec) * 1000; |
---|
1203 | |
---|
1204 | if (end.tv_usec > now.tv_usec) |
---|
1205 | timeout += (end.tv_usec - now.tv_usec) / 1000; |
---|
1206 | else |
---|
1207 | timeout += (((1000000 + end.tv_usec) - now.tv_usec) / 1000) - 1000; |
---|
1208 | |
---|
1209 | } |
---|
1210 | |
---|
1211 | if (!pymol.immediate_update) |
---|
1212 | status = poll(ufd, 3, timeout); |
---|
1213 | else |
---|
1214 | status = 0; |
---|
1215 | |
---|
1216 | if ( status < 0 ) |
---|
1217 | { |
---|
1218 | trace("pymolproxy: POLL ERROR: status = %d, errno = %d, %s \n", status,errno,strerror(errno)); |
---|
1219 | } |
---|
1220 | else if (status > 0) |
---|
1221 | { |
---|
1222 | gettimeofday(&now,NULL); |
---|
1223 | |
---|
1224 | if (ufd[0].revents) { /* Client Stdout Connection: command input */ |
---|
1225 | if (read(ufd[0].fd,&ch,1) <= 0) |
---|
1226 | { |
---|
1227 | if (errno != EINTR) |
---|
1228 | { |
---|
1229 | trace("pymolproxy: lost client connection (%d).\n", errno); |
---|
1230 | break; |
---|
1231 | } |
---|
1232 | } |
---|
1233 | else |
---|
1234 | { |
---|
1235 | Tcl_DStringAppend(&cmdbuffer, &ch, 1); |
---|
1236 | |
---|
1237 | if (ch == '\n' && Tcl_CommandComplete(Tcl_DStringValue(&cmdbuffer))) { |
---|
1238 | Tcl_Eval(interp, Tcl_DStringValue(&cmdbuffer)); |
---|
1239 | trace("Executed(%d,%d): %s", pymol.need_update, pymol.immediate_update, Tcl_DStringValue(&cmdbuffer)); |
---|
1240 | Tcl_DStringSetLength(&cmdbuffer, 0); |
---|
1241 | |
---|
1242 | if (timeout == 0) status = 0; // send update |
---|
1243 | } |
---|
1244 | } |
---|
1245 | } |
---|
1246 | |
---|
1247 | if (ufd[1].revents ) { /* pyMol Stdout Connection: pymol (unexpected) output */ |
---|
1248 | if (read(ufd[1].fd, &ch, 1) <= 0) |
---|
1249 | { |
---|
1250 | if (errno != EINTR) { |
---|
1251 | trace("pymolproxy: lost connection (stdout) to pymol server\n"); |
---|
1252 | break; |
---|
1253 | } |
---|
1254 | } |
---|
1255 | else |
---|
1256 | { |
---|
1257 | dyBufferAppend(&dybuffer, &ch, 1); |
---|
1258 | |
---|
1259 | if (ch == '\n') { |
---|
1260 | ch = 0; |
---|
1261 | dyBufferAppend(&dybuffer, &ch, 1); |
---|
1262 | trace("STDOUT>%s",dybuffer.data); |
---|
1263 | dyBufferSetLength(&dybuffer,0); |
---|
1264 | } |
---|
1265 | } |
---|
1266 | } |
---|
1267 | |
---|
1268 | if (ufd[2].revents) { /* pyMol Stderr Connection: pymol standard error output */ |
---|
1269 | if (read(ufd[2].fd, &ch, 1) <= 0) |
---|
1270 | { |
---|
1271 | if (errno != EINTR) { |
---|
1272 | trace("pymolproxy: lost connection (stderr) to pymol server\n"); |
---|
1273 | break; |
---|
1274 | } |
---|
1275 | } |
---|
1276 | else { |
---|
1277 | dyBufferAppend(&dybuffer2, &ch, 1); |
---|
1278 | |
---|
1279 | if (ch == '\n') { |
---|
1280 | ch = 0; |
---|
1281 | dyBufferAppend(&dybuffer2, &ch, 1); |
---|
1282 | trace("stderr>%s", dybuffer2.data); |
---|
1283 | dyBufferSetLength(&dybuffer2,0); |
---|
1284 | } |
---|
1285 | } |
---|
1286 | } |
---|
1287 | } |
---|
1288 | |
---|
1289 | if (status == 0) |
---|
1290 | { |
---|
1291 | gettimeofday(&now,NULL); |
---|
1292 | |
---|
1293 | if (pymol.need_update && pymol.can_update) |
---|
1294 | Tcl_Eval(interp, "bmp -\n"); |
---|
1295 | |
---|
1296 | end.tv_sec = now.tv_sec; |
---|
1297 | end.tv_usec = now.tv_usec + 150000; |
---|
1298 | |
---|
1299 | if (end.tv_usec >= 1000000) |
---|
1300 | { |
---|
1301 | end.tv_sec++; |
---|
1302 | end.tv_usec -= 1000000; |
---|
1303 | } |
---|
1304 | |
---|
1305 | } |
---|
1306 | |
---|
1307 | } |
---|
1308 | |
---|
1309 | status = waitpid(pid, &result, WNOHANG); |
---|
1310 | |
---|
1311 | if (status == -1) { |
---|
1312 | trace("pymolproxy: error waiting on pymol server to exit (%d)\n", errno); |
---|
1313 | } else if (status == 0) { |
---|
1314 | trace("pymolproxy: attempting to SIGTERM pymol server\n"); |
---|
1315 | kill(-pid, SIGTERM); // kill process group |
---|
1316 | alarm(5); |
---|
1317 | status = waitpid(pid, &result, 0); |
---|
1318 | alarm(0); |
---|
1319 | |
---|
1320 | while ((status == -1) && (errno == EINTR)) |
---|
1321 | { |
---|
1322 | trace("pymolproxy: Attempting to SIGKILL process.\n"); |
---|
1323 | kill(-pid, SIGKILL); // kill process group |
---|
1324 | alarm(10); |
---|
1325 | status = waitpid(pid, &result, 0); |
---|
1326 | alarm(0); |
---|
1327 | } |
---|
1328 | } |
---|
1329 | |
---|
1330 | trace("pymolproxy: pymol server process ended (%d)\n", result); |
---|
1331 | |
---|
1332 | dyBufferFree(&pymol.image); |
---|
1333 | |
---|
1334 | Tcl_DeleteInterp(interp); |
---|
1335 | |
---|
1336 | return( (status == pid) ? 0 : 1); |
---|
1337 | } |
---|
1338 | |
---|
1339 | #ifdef STANDALONE |
---|
1340 | |
---|
1341 | int |
---|
1342 | main(int argc, char *argv[]) |
---|
1343 | { |
---|
1344 | if (debug) { |
---|
1345 | flog = stderr; |
---|
1346 | flog = fopen("/tmp/pymolproxy.log", "w"); |
---|
1347 | } |
---|
1348 | ProxyInit(fileno(stdout), fileno(stdin), argv + 1); |
---|
1349 | return 0; |
---|
1350 | } |
---|
1351 | |
---|
1352 | #endif |
---|
1353 | |
---|