Changeset 1334 for trunk/packages/vizservers/pymolproxy
- Timestamp:
- Mar 17, 2009, 1:59:17 PM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/packages/vizservers/pymolproxy/pymolproxy.c
r1278 r1334 9 9 * widget is the Tcl language. Commands are then relayed to the pymol 10 10 * server. Responses from the pymol server are translated into Tcl 11 * commands *and send to the molvisviewer widget. For example, resulting11 * commands and send to the molvisviewer widget. For example, resulting 12 12 * image rendered offscreen is returned as BMP-formatted image data. 13 13 * … … 106 106 #endif 107 107 108 typedef struct {109 char *data;108 typedef struct Image { 109 struct Image *next; 110 110 int used; 111 111 int allocated; 112 112 ssize_t nWritten; 113 113 size_t bytesLeft; 114 } DyBuffer; 114 char data[1]; 115 } Image; 115 116 116 117 #define BUFFER_SIZE 4096 … … 134 135 int clientInput; 135 136 int clientOutput; 136 DyBuffer image;137 137 Tcl_Interp *interp; 138 138 int updatePending; … … 153 153 float xAngle, yAngle, zAngle; 154 154 float atomScale; 155 Image *head, *current; 155 156 } PymolProxy; 156 157 … … 510 511 } 511 512 513 static Image * 514 NewImage(PymolProxy *proxyPtr, size_t dataLength) 515 { 516 Image *imgPtr; 517 518 imgPtr = malloc(sizeof(Image) + dataLength); 519 if (imgPtr == NULL) { 520 fprintf(stderr, "can't allocate image of %d bytes", 521 sizeof(Image) + dataLength); 522 abort(); 523 } 524 imgPtr->bytesLeft = imgPtr->allocated = dataLength; 525 imgPtr->next = proxyPtr->head; 526 proxyPtr->head = imgPtr; 527 imgPtr->used = imgPtr->nWritten = 0; 528 return imgPtr; 529 } 530 512 531 INLINE static void 513 dyBufferInit(DyBuffer *imgPtr) 514 { 515 imgPtr->data = NULL; 516 imgPtr->used = 0; 517 imgPtr->allocated = 0; 518 imgPtr->nWritten = 0; 519 imgPtr->bytesLeft = 0; 520 } 521 522 INLINE static void 523 dyBufferFree(DyBuffer *imgPtr) 532 FreeImage(Image *imgPtr) 524 533 { 525 534 assert(imgPtr != NULL); 526 if (imgPtr->data != NULL) { 527 free(imgPtr->data); 528 } 529 dyBufferInit(imgPtr); 530 } 531 532 static void 533 dyBufferSetLength(DyBuffer *buffer, int length) 534 { 535 assert(buffer != NULL); 536 if (length == 0) { 537 dyBufferFree(buffer); 538 } else if (length > buffer->used) { 539 char *newdata; 540 541 newdata = realloc(buffer->data, length); 542 if (newdata != NULL) { 543 buffer->data = newdata; 544 buffer->used = length; 545 buffer->allocated = length; 546 } 547 } else { 548 buffer->used = length; 549 } 550 } 551 552 static void 553 dyBufferAppend(DyBuffer *buffer, const char *data, int length) 554 { 555 int offset; 556 557 assert(buffer != NULL); 558 offset = buffer->used; 559 dyBufferSetLength(buffer, offset + length); 560 memcpy(buffer->data + offset, data, length); 535 free(imgPtr); 561 536 } 562 537 … … 564 539 WriteImage(PymolProxy *proxyPtr, int fd) 565 540 { 566 DyBuffer *imgPtr;541 Image *imgPtr, *img2Ptr, *nextPtr; 567 542 ssize_t bytesLeft; 568 543 569 imgPtr = &proxyPtr->image; 544 imgPtr = (proxyPtr->current == NULL) ? proxyPtr->head : proxyPtr->current; 545 if (imgPtr == NULL) { 546 trace("Should not be here: no image available to write"); 547 return; 548 } 549 570 550 trace("WriteImage: want to write %d bytes.", imgPtr->bytesLeft); 571 551 for (bytesLeft = imgPtr->bytesLeft; bytesLeft > 0; /*empty*/) { … … 589 569 imgPtr->nWritten += nWritten; 590 570 } 591 dyBufferFree(imgPtr); 571 /* Check if image is on the head. */ 572 if (proxyPtr->head == imgPtr) { 573 proxyPtr->head = NULL; 574 } else { 575 /* Otherwise find it in the list of images and disconnect it. */ 576 for (img2Ptr = proxyPtr->head; img2Ptr != NULL; img2Ptr = nextPtr) { 577 nextPtr = img2Ptr->next; 578 if (nextPtr == imgPtr) { 579 img2Ptr->next = NULL; 580 } 581 } 582 } 583 /* Remove add images from this image on down. */ 584 for (/*empty*/; imgPtr != NULL; imgPtr = nextPtr) { 585 nextPtr = imgPtr->next; 586 FreeImage(imgPtr); 587 } 588 proxyPtr->current = NULL; 592 589 } 593 590 … … 618 615 } 619 616 #endif 620 621 static int622 bwrite(int fd, char *buffer, int size)623 {624 int result;625 int total = 0;626 int left = size;627 628 trace("bwrite: want to write %d bytes.", size);629 while(1) {630 result = write(fd,buffer+total,left);631 632 if (result <= 0)633 break;634 635 total += result;636 left -= result;637 638 if (total == size)639 break;640 }641 trace("bwrite: wrote %d bytes.", total);642 return total;643 }644 645 static int646 bread(int fd, char *buffer, int size)647 {648 int result, total, left;649 650 for( total = 0, left = size; left > 0; left -= result) {651 result = read(fd, buffer+total, left);652 653 if (result > 0) {654 total += result;655 continue;656 }657 658 if ((result < 0) && (errno != EAGAIN) && (errno != EINTR)) {659 trace("Error reading fd(%d), %d/%s.", fd, errno,660 strerror(errno));661 break;662 }663 664 result = 0;665 }666 return total;667 }668 669 #ifdef notdef670 671 static int672 bflush(int fd, char *buffer, int size, int bytes)673 {674 int bsize;675 676 while(bytes) {677 if (bytes > size)678 bsize = size;679 else680 bsize = bytes;681 682 bsize = bread(fd,buffer,bsize);683 684 bytes -= bsize;685 }686 }687 688 #undef timersub689 static void690 timersub(struct timeval *a, struct timeval *b, struct timeval *result)691 {692 result->tv_sec = a->tv_sec - b->tv_sec;693 result->tv_usec = a->tv_usec - b->tv_usec;694 695 while(result->tv_usec < 0) {696 result->tv_sec -= 1;697 result->tv_usec += 1000000;698 }699 }700 701 #endif702 703 static void704 timersub_ms(struct timeval *a, struct timeval *b, int *result)705 {706 struct timeval tmp;707 708 tmp.tv_sec = a->tv_sec - b->tv_sec;709 tmp.tv_usec = a->tv_usec - b->tv_usec;710 711 while(tmp.tv_usec < 0) {712 tmp.tv_sec -= 1;713 tmp.tv_usec += 1000000;714 }715 716 *result = (tmp.tv_sec * 1000) + (tmp.tv_usec / 1000);717 }718 719 #undef timeradd720 static void721 timeradd (struct timeval *a, struct timeval *b, struct timeval *result)722 {723 result->tv_sec = a->tv_sec + b->tv_sec;724 result->tv_usec = a->tv_usec + b->tv_usec;725 726 while (result->tv_usec >= 1000000) {727 result->tv_sec += 1;728 result->tv_usec -= 1000000;729 }730 }731 732 static void733 timerset_ms(struct timeval *result, int timeout)734 {735 result->tv_sec = timeout / 1000;736 result->tv_usec = (timeout % 1000) * 1000;737 }738 739 740 static int741 getline(int fd, char *buffer, int size, int timeout)742 {743 int pos = 0, status, timeo;744 struct timeval now, end, tmo;745 struct pollfd ufd;746 747 gettimeofday(&now,NULL);748 timerset_ms(&tmo, timeout);749 timeradd(&now,&tmo,&end);750 751 ufd.fd = fd;752 ufd.events = POLLIN;753 754 size--;755 756 while(pos < size) {757 if (timeout > 0) {758 gettimeofday(&now,NULL);759 timersub_ms(&now,&end,&timeo);760 }761 else762 timeo = -1;763 764 status = poll(&ufd, 1, timeo);765 766 if (status > 0)767 status = read(fd,&buffer[pos],1);768 769 if ( (status < 0) && ( (errno == EINTR) || (errno == EAGAIN) ) )770 continue; /* try again, if interrupted/blocking */771 772 if (status <= 0) {773 trace("getline: status=%d, errno=%d", status, errno);774 break;775 }776 if (buffer[pos] == '\n') {777 pos++;778 break;779 }780 pos++;781 }782 783 buffer[pos]=0;784 return pos;785 }786 787 617 788 618 static int … … 952 782 unsigned int nBytes=0; 953 783 PymolProxy *proxyPtr = clientData; 954 DyBuffer*imgPtr;784 Image *imgPtr; 955 785 int nScanned; 956 786 size_t length; … … 987 817 988 818 length = strlen(buffer); 989 imgPtr = &proxyPtr->image; 990 dyBufferSetLength(imgPtr, nBytes + length); 819 imgPtr = NewImage(proxyPtr, nBytes + length); 991 820 strcpy(imgPtr->data, buffer); 992 821 if (GetBytes(&proxyPtr->server, imgPtr->data + length, nBytes)!=BUFFER_OK){ … … 994 823 return TCL_ERROR; 995 824 } 996 imgPtr->bytesLeft = nBytes + length;997 imgPtr->nWritten = 0;998 825 stats.nFrames++; 999 826 stats.nBytes += nBytes; … … 1317 1144 { 1318 1145 char buffer[800]; 1319 unsigned int nBytes=0; 1320 PymolProxy *proxyPtr = clientData; 1146 size_t nBytes=0; 1147 PymolProxy *proxyPtr = clientData; 1148 size_t length; 1149 Image *imgPtr; 1150 1321 1151 #ifdef notdef 1322 1152 float samples = 10.0; … … 1344 1174 nWritten = write(3, &samples, sizeof(samples)); 1345 1175 #endif 1346 dyBufferSetLength(&proxyPtr->image, nBytes); 1347 1348 bread(proxyPtr->serverOutput, proxyPtr->image.data, proxyPtr->image.used); 1349 proxyPtr->image.bytesLeft = proxyPtr->image.used; 1350 proxyPtr->image.nWritten = 0; 1351 1176 if (nBytes == 0) { 1177 } 1178 sprintf(buffer, "nv>image %d %d %d %d\n", nBytes, proxyPtr->cacheid, 1179 proxyPtr->frame, proxyPtr->rock_offset); 1180 length = strlen(buffer); 1181 imgPtr = NewImage(proxyPtr, nBytes + length); 1182 strcpy(imgPtr->data, buffer); 1183 if (GetBytes(&proxyPtr->server, imgPtr->data + length, nBytes)!=BUFFER_OK){ 1184 trace("can't read %d bytes for \"image follows\" buffer", nBytes); 1185 return TCL_ERROR; 1186 } 1187 #ifdef notdef 1352 1188 Expect(proxyPtr, " ScenePNG", buffer,800); 1353 1354 if ((nBytes > 0) && (proxyPtr->image.used == nBytes)) { 1355 ssize_t nWritten; 1356 1357 sprintf(buffer, "nv>image %d %d %d %d\n", 1358 nBytes, proxyPtr->cacheid, proxyPtr->frame, proxyPtr->rock_offset); 1359 trace("to-molvis> %s", buffer); 1360 /* Write the header */ 1361 nWritten = write(proxyPtr->clientInput, buffer, strlen(buffer)); 1362 /* and the data. */ 1363 bwrite(proxyPtr->clientInput, proxyPtr->image.data, nBytes); 1364 1365 stats.nFrames++; 1366 stats.nBytes += nBytes; 1367 } 1189 #endif 1190 stats.nFrames++; 1191 stats.nBytes += nBytes; 1368 1192 return proxyPtr->status; 1369 1193 } … … 1373 1197 { 1374 1198 PymolProxy *proxyPtr = clientData; 1375 DyBuffer buffer;1376 1199 int arg, defer = 0, push = 0; 1377 1200 const char *cmd; 1378 1201 clear_error(proxyPtr); 1379 1380 dyBufferInit(&buffer);1381 1202 1382 1203 cmd = NULL; … … 1396 1217 1397 1218 Pymol(proxyPtr,"%s\n", cmd); 1398 dyBufferFree(&buffer);1399 1400 1219 return proxyPtr->status; 1401 1220 } … … 1784 1603 signal(SIGPIPE, SIG_IGN); /* ignore SIGPIPE (e.g. nanoscale terminates)*/ 1785 1604 1605 memset(&proxy, 0, sizeof(PymolProxy)); 1786 1606 proxy.serverInput = serverIn[1]; 1787 1607 proxy.serverOutput = serverOut[0]; … … 1789 1609 proxy.clientInput = c_in; 1790 1610 proxy.clientOutput = c_out; 1791 proxy.showLabels = FALSE;1792 proxy.updatePending = FALSE;1793 proxy.forceUpdate = FALSE;1794 proxy.rotatePending = FALSE;1795 proxy.scalePending = FALSE;1796 1611 proxy.can_update = TRUE; 1797 proxy.sync = 0;1798 1612 proxy.frame = 1; 1799 proxy.rock_offset = 0;1800 proxy.cacheid = 0;1801 proxy.invalidate_cache = FALSE;1802 1613 interp = Tcl_CreateInterp(); 1803 1614 Tcl_MakeSafe(interp); 1804 1615 proxy.interp = interp; 1805 proxy.xAngle = proxy.yAngle = proxy.zAngle = 0.0f;1806 dyBufferInit(&proxy.image);1807 1616 1808 1617 Tcl_CreateCommand(interp, "atomscale", AtomscaleCmd, &proxy, NULL); … … 1865 1674 trace("pymol server process ended (result=%d)", result); 1866 1675 1867 dyBufferFree(&proxy.image);1868 1869 1676 Tcl_DeleteInterp(interp); 1870 1677 if (WIFEXITED(result)) { … … 1897 1704 PollForEvents(PymolProxy *proxyPtr) 1898 1705 { 1899 DyBuffer *imgPtr;1900 1706 Tcl_DString clientCmds; 1901 1707 struct pollfd pollResults[4]; … … 1923 1729 1924 1730 Tcl_DStringInit(&clientCmds); 1925 imgPtr = &proxyPtr->image;1926 1731 for (;;) { 1927 1732 int timeout, nChannels; 1928 1733 1929 nChannels = ( imgPtr->bytesLeft > 0) ? 4 : 3;1734 nChannels = (proxyPtr->head != NULL) ? 4 : 3; 1930 1735 1931 1736 #define PENDING_TIMEOUT 10 /* milliseconds. */ … … 2028 1833 2029 1834 /* Write the current image buffer. */ 2030 if ( imgPtr->nWritten == 0) {1835 if (proxyPtr->head == NULL) { 2031 1836 /* We might want to refresh the image if we're not currently 2032 1837 * transmitting an image back to the client. The image will be … … 2041 1846 } 2042 1847 } 2043 if (( imgPtr->bytesLeft > 0) && (pollResults[3].revents & POLLOUT)) {1848 if ((proxyPtr->head != NULL) && (pollResults[3].revents & POLLOUT)) { 2044 1849 WriteImage(proxyPtr, pollResults[3].fd); 2045 1850 }
Note: See TracChangeset
for help on using the changeset viewer.