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