Ignore:
Timestamp:
Mar 17, 2009, 1:59:17 PM (16 years ago)
Author:
gah
Message:

Fixes for overlapping images

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/packages/vizservers/pymolproxy/pymolproxy.c

    r1278 r1334  
    99 *      widget is the Tcl language.  Commands are then relayed to the pymol
    1010 *      server.  Responses from the pymol server are translated into Tcl
    11  *      commands * and send to the molvisviewer widget. For example, resulting
     11 *      commands and send to the molvisviewer widget. For example, resulting
    1212 *      image rendered offscreen is returned as BMP-formatted image data.
    1313 *
     
    106106#endif
    107107
    108 typedef struct {
    109     char *data;
     108typedef struct Image {
     109    struct Image *next;
    110110    int   used;
    111111    int   allocated;
    112112    ssize_t nWritten;
    113113    size_t bytesLeft;
    114 } DyBuffer;
     114    char data[1];
     115} Image;
    115116
    116117#define BUFFER_SIZE             4096
     
    134135    int clientInput;
    135136    int clientOutput;
    136     DyBuffer image;
    137137    Tcl_Interp *interp;
    138138    int updatePending;
     
    153153    float xAngle, yAngle, zAngle;
    154154    float atomScale;
     155    Image *head, *current;
    155156} PymolProxy;
    156157
     
    510511}
    511512
     513static Image *
     514NewImage(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
    512531INLINE 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)
     532FreeImage(Image *imgPtr)
    524533{
    525534    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);
    561536}
    562537
     
    564539WriteImage(PymolProxy *proxyPtr, int fd)
    565540{
    566     DyBuffer *imgPtr;
     541    Image *imgPtr, *img2Ptr, *nextPtr;
    567542    ssize_t bytesLeft;
    568543
    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       
    570550    trace("WriteImage: want to write %d bytes.", imgPtr->bytesLeft);
    571551    for (bytesLeft = imgPtr->bytesLeft; bytesLeft > 0; /*empty*/) {
     
    589569        imgPtr->nWritten += nWritten;
    590570    }
    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;
    592589}
    593590
     
    618615}
    619616#endif
    620 
    621 static int
    622 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 int
    646 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 notdef
    670 
    671 static int
    672 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         else
    680             bsize = bytes;
    681        
    682         bsize = bread(fd,buffer,bsize);
    683        
    684         bytes -= bsize;     
    685     }
    686 }
    687 
    688 #undef timersub
    689 static void
    690 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 #endif
    702 
    703 static void
    704 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 timeradd
    720 static void
    721 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 void
    733 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 int
    741 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         else
    762             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 
    787617
    788618static int
     
    952782    unsigned int nBytes=0;
    953783    PymolProxy *proxyPtr = clientData;
    954     DyBuffer *imgPtr;
     784    Image *imgPtr;
    955785    int nScanned;
    956786    size_t length;
     
    987817
    988818    length = strlen(buffer);
    989     imgPtr = &proxyPtr->image;
    990     dyBufferSetLength(imgPtr, nBytes + length);
     819    imgPtr = NewImage(proxyPtr, nBytes + length);
    991820    strcpy(imgPtr->data, buffer);
    992821    if (GetBytes(&proxyPtr->server, imgPtr->data + length, nBytes)!=BUFFER_OK){
     
    994823        return  TCL_ERROR;
    995824    }
    996     imgPtr->bytesLeft = nBytes + length;
    997     imgPtr->nWritten = 0;
    998825    stats.nFrames++;
    999826    stats.nBytes += nBytes;
     
    13171144{
    13181145    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
    13211151#ifdef notdef
    13221152    float samples = 10.0;
     
    13441174    nWritten = write(3, &samples, sizeof(samples));
    13451175#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
    13521188    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;
    13681192    return proxyPtr->status;
    13691193}
     
    13731197{
    13741198    PymolProxy *proxyPtr = clientData;
    1375     DyBuffer buffer;
    13761199    int arg, defer = 0, push = 0;
    13771200    const char *cmd;
    13781201    clear_error(proxyPtr);
    1379 
    1380     dyBufferInit(&buffer);
    13811202
    13821203    cmd = NULL;
     
    13961217
    13971218    Pymol(proxyPtr,"%s\n", cmd);
    1398     dyBufferFree(&buffer);
    1399 
    14001219    return proxyPtr->status;
    14011220}
     
    17841603    signal(SIGPIPE, SIG_IGN); /* ignore SIGPIPE (e.g. nanoscale terminates)*/
    17851604
     1605    memset(&proxy, 0, sizeof(PymolProxy));
    17861606    proxy.serverInput  = serverIn[1];
    17871607    proxy.serverOutput = serverOut[0];
     
    17891609    proxy.clientInput  = c_in;
    17901610    proxy.clientOutput = c_out;
    1791     proxy.showLabels = FALSE;
    1792     proxy.updatePending = FALSE;
    1793     proxy.forceUpdate = FALSE;
    1794     proxy.rotatePending = FALSE;
    1795     proxy.scalePending = FALSE;
    17961611    proxy.can_update = TRUE;
    1797     proxy.sync = 0;
    17981612    proxy.frame = 1;
    1799     proxy.rock_offset = 0;
    1800     proxy.cacheid = 0;
    1801     proxy.invalidate_cache = FALSE;
    18021613    interp = Tcl_CreateInterp();
    18031614    Tcl_MakeSafe(interp);
    18041615    proxy.interp = interp;
    1805     proxy.xAngle = proxy.yAngle = proxy.zAngle = 0.0f;
    1806     dyBufferInit(&proxy.image);
    18071616
    18081617    Tcl_CreateCommand(interp, "atomscale",   AtomscaleCmd,   &proxy, NULL);
     
    18651674    trace("pymol server process ended (result=%d)", result);
    18661675   
    1867     dyBufferFree(&proxy.image);
    1868    
    18691676    Tcl_DeleteInterp(interp);
    18701677    if (WIFEXITED(result)) {
     
    18971704PollForEvents(PymolProxy *proxyPtr)
    18981705{
    1899     DyBuffer *imgPtr;
    19001706    Tcl_DString clientCmds;
    19011707    struct pollfd pollResults[4];
     
    19231729
    19241730    Tcl_DStringInit(&clientCmds);
    1925     imgPtr = &proxyPtr->image;
    19261731    for (;;) {
    19271732        int timeout, nChannels;
    19281733
    1929         nChannels =  (imgPtr->bytesLeft > 0) ? 4 : 3;
     1734        nChannels =  (proxyPtr->head != NULL) ? 4 : 3;
    19301735
    19311736#define PENDING_TIMEOUT         10  /* milliseconds. */
     
    20281833
    20291834        /* Write the current image buffer. */
    2030         if (imgPtr->nWritten == 0) {
     1835        if (proxyPtr->head == NULL) {
    20311836            /* We might want to refresh the image if we're not currently
    20321837             * transmitting an image back to the client. The image will be
     
    20411846            }
    20421847        }
    2043         if ((imgPtr->bytesLeft > 0) && (pollResults[3].revents & POLLOUT)) {
     1848        if ((proxyPtr->head != NULL) && (pollResults[3].revents & POLLOUT)) {
    20441849            WriteImage(proxyPtr, pollResults[3].fd);
    20451850        }
Note: See TracChangeset for help on using the changeset viewer.