source: trunk/vizservers/pymolproxy/pymolproxy.c @ 749

Last change on this file since 749 was 721, checked in by nkissebe, 17 years ago

ignore SIGPIPE signal (ie, if nanoscale terminated)

File size: 29.3 KB
Line 
1#include <stdio.h>
2#include <unistd.h>
3#include <stdlib.h>
4#include <string.h>
5#include <signal.h>
6#include <sys/types.h>
7#include <sys/socket.h>
8#include <sys/wait.h>
9#include <sys/select.h>
10#include <poll.h>
11#include <sys/time.h>
12#include <fcntl.h>
13#include <netinet/in.h>
14#include <getopt.h>
15#include <errno.h>
16#include <sys/ioctl.h>
17#include <net/if.h>
18#include <tcl.h>
19
20#define IO_TIMEOUT (30000)
21
22struct dyBuffer
23{
24    char *data;
25        int   used;
26        int   allocated;
27};
28
29struct 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};
49
50void
51dyBufferInit(struct dyBuffer *buffer)
52{
53    buffer->data = NULL;
54        buffer->used = 0;
55        buffer->allocated = 0;
56}
57
58void
59dyBufferFree(struct dyBuffer *buffer)
60{
61    if (buffer == NULL)
62            return;
63
64        free(buffer->data);
65
66        dyBufferInit(buffer);
67
68        return;
69}
70
71void
72dyBufferSetLength(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                }
89        }
90        else
91            buffer->used = length;
92}
93
94void
95dyBufferAppend(struct dyBuffer *buffer, const char *data, int length)
96{
97    int offset;
98
99    offset = buffer->used;
100
101    dyBufferSetLength(buffer, offset + length);
102
103    memcpy(buffer->data + offset, data, length);
104}
105
106int
107bwrite(int sock, char *buffer, int size)
108{
109    int result;
110    int total = 0;
111    int left = size;
112
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
126    return(total);
127}
128
129int
130bread(int sock, char *buffer, int size)
131{
132    int result, total, left;
133
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        }
151
152    return(total);
153}
154
155int
156bflush(int sock, char *buffer, int size, int bytes)
157{
158        int bsize;
159
160        while(bytes)
161        {
162                if (bytes > size)
163                        bsize = size;
164                else
165                        bsize = bytes;
166
167                bsize = bread(sock,buffer,bsize);
168       
169                bytes -= bsize;
170        }
171}
172
173#undef timersub
174#undef timeradd
175
176void
177timersub(struct timeval *a, struct timeval *b, struct timeval *result)
178{
179    result->tv_sec = a->tv_sec - b->tv_sec;
180        result->tv_usec = a->tv_usec - b->tv_usec;
181
182    while(result->tv_usec < 0) {
183                result->tv_sec -= 1;
184                result->tv_usec += 1000000;
185        }
186}
187
188void
189timersub_ms(struct timeval *a, struct timeval *b, int *result)
190{
191        struct timeval tmp;
192
193    tmp.tv_sec = a->tv_sec - b->tv_sec;
194        tmp.tv_usec = a->tv_usec - b->tv_usec;
195
196    while(tmp.tv_usec < 0) {
197                tmp.tv_sec -= 1;
198                tmp.tv_usec += 1000000;
199        }
200
201        *result = (tmp.tv_sec * 1000) + (tmp.tv_usec / 1000);
202}
203
204
205void
206timeradd(struct timeval *a, struct timeval *b, struct timeval *result)
207{
208        result->tv_sec = a->tv_sec + b->tv_sec;
209    result->tv_usec = a->tv_usec + b->tv_usec;
210
211        while(result->tv_usec >= 1000000) {
212                result->tv_sec += 1;
213                result->tv_usec -= 1000000;
214        }
215}
216
217void
218timerset_ms(struct timeval *result, int timeout)
219{
220    result->tv_sec = timeout / 1000;
221    result->tv_usec = (timeout % 1000) * 1000;
222}
223
224int
225getline(int sock, char *buffer, int size, long timeout)
226{
227    int pos = 0, status, timeo;
228        struct timeval now, end, tmo;
229    struct pollfd ufd;
230
231        gettimeofday(&now,NULL);
232        timerset_ms(&tmo, timeout);
233    timeradd(&now,&tmo,&end);
234
235        ufd.fd = sock;
236        ufd.events = POLLIN;
237
238    size--;
239
240        while(pos < size) {
241                if (timeout > 0) {
242                        gettimeofday(&now,NULL);
243                        timersub_ms(&now,&end,&timeo);
244                }
245                else
246                        timeo = -1;
247
248        status = poll(&ufd, 1, timeo);
249
250        if (status > 0)
251                        status = read(sock,&buffer[pos],1);
252
253                if ( (status < 0) && ( (errno == EINTR) || (errno == EAGAIN) ) )
254                        continue; /* try again, if interrupted/blocking */
255
256                if (status <= 0)
257                        break;
258                       
259                if (buffer[pos] == '\n')
260                {
261                        pos++;
262                        break;
263                }
264
265                pos++;
266
267    }
268
269        buffer[pos]=0;
270
271        return(pos);
272}
273
274int
275waitForString(struct pymol_proxy *pymol, char *string, char *buffer, int length)
276{
277    int sock;
278
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
287    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
307int
308clear_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
319int
320sendf(struct pymol_proxy *pymol, char *format, ...)
321{
322    va_list ap;
323    char buffer[800];
324
325        if (pymol == NULL)
326                return(TCL_ERROR);
327
328        if (pymol->error)
329            return(TCL_ERROR);
330
331    va_start(ap, format);
332    vsnprintf(buffer, 800, format, ap);
333    va_end(ap);
334    //fprintf(stderr,"stdin> %s", buffer);
335    write(pymol->p_stdin, buffer, strlen(buffer));
336
337    if (waitForString(pymol, "PyMOL>", buffer, 800)) {
338        fprintf(stderr,"pymolproxy: Timeout reading data [%s]\n",buffer);
339                pymol->error = 1;
340                pymol->status = TCL_ERROR;
341        return(pymol->status);
342    }
343
344        return( pymol->status );
345}
346
347int
348BallAndStickCmd(ClientData cdata, Tcl_Interp *interp, int argc, const char *argv[])
349{
350    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);
358
359    for(arg = 1; arg < argc; arg++) {
360                if ( strcmp(argv[arg],"-defer") == 0 )
361                    defer = 1;
362                else if (strcmp(argv[arg],"-push") == 0)
363                    push = 1;
364                else if (strcmp(argv[arg],"-ghost") == 0)
365                    ghost = 1;
366                else if (strcmp(argv[arg],"-normal") == 0)
367                    ghost = 0;
368                else if (strcmp(argv[arg],"-model") == 0) {
369                        if (++arg < argc)
370                                model = argv[arg];
371                }
372                else
373                    model = argv[arg];
374        }
375
376        pymol->invalidate_cache = 1;
377        pymol->need_update = !defer || push;
378    pymol->immediate_update |= push;
379
380        sendf(pymol, "hide everything,%s\n",model);
381        sendf(pymol, "set stick_color,white,%s\n",model);
382       
383        if (ghost)
384                sendf(pymol, "set stick_radius,0.1,%s\n",model);
385        else
386                sendf(pymol, "set stick_radius,0.14,%s\n",model);
387
388        sendf(pymol, "set sphere_scale=0.25,%s\n", model);
389
390    if (ghost) {
391        sendf(pymol, "set sphere_transparency,0.75,%s\n", model);
392        sendf(pymol, "set stick_transparency,0.75,%s\n", model);
393    }
394        else {
395        sendf(pymol, "set sphere_transparency,0,%s\n", model);
396        sendf(pymol, "set stick_transparency,0,%s\n", model);
397    }
398
399        sendf(pymol, "show sticks,%s\n",model);
400        sendf(pymol, "show spheres,%s\n",model);
401
402        if (pymol->labels)
403                sendf(pymol, "show labels,%s\n", model);
404
405        return( pymol->status );
406}
407
408int
409SpheresCmd(ClientData cdata, Tcl_Interp *interp, int argc, const char *argv[])
410{
411    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);
419
420    for(arg = 1; arg < argc; arg++) {
421                if ( strcmp(argv[arg],"-defer") == 0 )
422                    defer = 1;
423                else if (strcmp(argv[arg],"-push") == 0)
424                    push = 1;
425                else if (strcmp(argv[arg],"-ghost") == 0)
426                    ghost = 1;
427                else if (strcmp(argv[arg],"-normal") == 0)
428                    ghost = 0;
429                else if (strcmp(argv[arg],"-model") == 0) {
430                        if (++arg < argc)
431                                model = argv[arg];
432                }
433                else
434                    model = argv[arg];
435        }
436
437        pymol->invalidate_cache = 1;
438        pymol->need_update = !defer || push;
439        pymol->immediate_update |= push;
440
441    sendf(pymol, "hide everything, %s\n", model);
442    sendf(pymol, "set sphere_scale,0.41,%s\n", model);
443    //sendf(pymol, "set sphere_quality,2,%s\n", model);
444    sendf(pymol, "set ambient,.2,%s\n", model);
445
446    if (ghost)
447        sendf(pymol, "set sphere_transparency,.75,%s\n", model);
448        else
449        sendf(pymol, "set sphere_transparency,0,%s\n", model);
450
451    sendf(pymol, "show spheres,%s\n", model);
452
453        if (pymol->labels)
454                sendf(pymol, "show labels,%s\n", model);
455
456        return(pymol->status);
457}
458
459int
460LinesCmd(ClientData cdata, Tcl_Interp *interp, int argc, const char *argv[])
461{
462    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);
470
471    for(arg = 1; arg < argc; arg++) {
472                if ( strcmp(argv[arg],"-defer") == 0 )
473                    defer = 1;
474                else if (strcmp(argv[arg],"-push") == 0)
475                    push = 1;
476                else if (strcmp(argv[arg],"-ghost") == 0)
477                    ghost = 1;
478                else if (strcmp(argv[arg],"-normal") == 0)
479                    ghost = 0;
480                else if (strcmp(argv[arg],"-model") == 0) {
481                        if (++arg < argc)
482                                model = argv[arg];
483                }
484                else
485                    model = argv[arg];
486        }
487
488        pymol->invalidate_cache = 1;
489        pymol->need_update = !defer || push;
490        pymol->immediate_update |= push;
491
492    sendf(pymol, "hide everything,%s\n",model);
493
494    if (ghost)
495            sendf(pymol, "set line_width,.25,%s\n",model);
496        else
497            sendf(pymol, "set line_width,1,%s\n",model);
498
499    sendf(pymol, "show lines,%s\n",model);
500
501        if (pymol->labels)
502                sendf(pymol, "show labels,%s\n",model);
503
504        return(pymol->status);
505}
506
507int
508DisableCmd(ClientData cdata, Tcl_Interp *interp, int argc, const char *argv[])
509{
510        struct pymol_proxy *pymol = (struct pymol_proxy *) cdata;
511    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);
518
519    for(arg = 1; arg < argc; arg++) {
520
521            if (strcmp(argv[arg], "-defer") == 0 )
522                        defer = 1;
523                else if (strcmp(argv[arg], "-push") == 0 )
524                    push = 1;
525                else
526                        model = argv[arg];
527       
528        }
529
530        pymol->need_update = !defer || push;
531        pymol->immediate_update |= push;
532        pymol->invalidate_cache = 1;
533
534        sendf( pymol, "disable %s\n", model);
535
536        return(pymol->status);
537}
538
539int
540EnableCmd(ClientData cdata, Tcl_Interp *interp, int argc, const char *argv[])
541{
542        struct pymol_proxy *pymol = (struct pymol_proxy *) cdata;
543    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
571int
572VMouseCmd(ClientData cdata, Tcl_Interp *interp, int argc, const char *argv[])
573{
574        struct pymol_proxy *pymol = (struct pymol_proxy *) cdata;
575    int arg, defer = 0, push = 0, varg = 1;
576    int arg1 = 0, arg2 = 0, arg3 = 0, arg4 = 0, arg5 = 0;
577
578        if (pymol == NULL)
579            return(TCL_ERROR);
580
581        clear_error(pymol);
582
583    for(arg = 1; arg < argc; arg++) {
584                if (strcmp(argv[arg], "-defer") == 0)
585                    defer = 1;
586                else if (strcmp(argv[arg], "-push") == 0)
587                    push = 1;
588                else if (varg == 1) {
589                        arg1 = atoi(argv[arg]);
590                        varg++;
591                }
592                else if (varg == 2) {
593                        arg2 = atoi(argv[arg]);
594                        varg++;
595                }
596                else if (varg == 3) {
597                        arg3 = atoi(argv[arg]);
598                        varg++;
599                }
600                else if (varg == 4) {
601                        arg4 = atoi(argv[arg]);
602                        varg++;
603                }
604                else if (varg == 5) {
605                        arg5 = atoi(argv[arg]);
606                        varg++;
607                }
608    }
609
610    pymol->need_update = !defer || push;
611    pymol->immediate_update |= push;
612        pymol->invalidate_cache = 1;
613
614    sendf(pymol, "vmouse %d,%d,%d,%d,%d\n", arg1,arg2,arg3,arg4,arg5);
615
616        return(pymol->status);
617}
618
619int
620RawCmd(ClientData cdata, Tcl_Interp *interp, int argc, const char *argv[])
621{
622        struct pymol_proxy *pymol = (struct pymol_proxy *) cdata;
623    struct dyBuffer buffer;
624    int arg, defer = 0, push = 0;
625   
626    if (pymol == NULL)
627            return(TCL_ERROR);
628
629        clear_error(pymol);
630
631    dyBufferInit(&buffer);
632
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
655int
656LabelCmd(ClientData cdata, Tcl_Interp *interp, int argc, const char *argv[])
657{
658        struct pymol_proxy *pymol = (struct pymol_proxy *) cdata;
659    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;
683
684    if (state) {
685                sendf(pymol, "set label_color,white,all\n");
686                sendf(pymol, "set label_size,14,all\n");
687                sendf(pymol, "label all,\"%%s%%s\" %% (ID,name)\n");
688    }
689        else
690                sendf(pymol, "label all\n");
691
692        pymol->labels = state;
693
694    return(pymol->status);
695}
696
697int
698FrameCmd(ClientData cdata, Tcl_Interp *interp, int argc, const char *argv[])
699{
700        struct pymol_proxy *pymol = (struct pymol_proxy *) cdata;
701    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;
719    pymol->immediate_update |= push;
720
721    pymol->frame = frame;
722
723        sendf(pymol,"frame %d\n", frame);
724       
725        return(pymol->status);
726}
727
728int
729ResetCmd(ClientData cdata, Tcl_Interp *interp, int argc, const char *argv[])
730{
731        struct pymol_proxy *pymol = (struct pymol_proxy *) cdata;
732    int arg, push = 0, defer = 0;
733
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
756int
757RockCmd(ClientData cdata, Tcl_Interp *interp, int argc, const char *argv[])
758{
759        struct pymol_proxy *pymol = (struct pymol_proxy *) cdata;
760        float y = 0.0;
761    int arg, push = 0, defer = 0;
762
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;
778    pymol->immediate_update |= push;
779
780        sendf(pymol,"turn y, %f\n", y - pymol->rock_offset);
781
782        pymol->rock_offset = y;
783
784        return(pymol->status);
785}
786
787int
788ViewportCmd(ClientData cdata, Tcl_Interp *interp, int argc, const char *argv[])
789{
790        struct pymol_proxy *pymol = (struct pymol_proxy *) cdata;
791    int width = 640, height = 480;
792    int defer = 0, push = 0, arg, varg = 1;
793
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                }
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
826int
827LoadPDBStrCmd(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                }
860        }
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
879int
880RotateCmd(ClientData cdata, Tcl_Interp *interp, int argc, const char *argv[])
881{
882        double turnx = 0.0;
883        double turny = 0.0;
884        double turnz = 0.0;
885        struct pymol_proxy *pymol = (struct pymol_proxy *) cdata;
886    int defer = 0, push = 0, arg, varg = 1;
887
888        if (pymol == NULL)
889                return(TCL_ERROR);
890
891        clear_error(pymol);
892
893    for(arg = 1; arg < argc; arg++)
894        {
895            if (strcmp(argv[arg],"-defer") == 0)
896                    defer = 1;
897                else if (strcmp(argv[arg],"-push") == 0)
898                    push = 1;
899        else  if (varg == 1) {
900                        turnx = atof(argv[arg]);
901                        varg++;
902                }
903                else if (varg == 2) {
904                    turny = atof(argv[arg]);
905                        varg++;
906                }
907        else if (varg == 3) {
908                        turnz = atof(argv[arg]);
909                        varg++;
910                }
911    }
912 
913    pymol->need_update = !defer || push;
914        pymol->immediate_update  |= push;
915        pymol->invalidate_cache = 1;
916
917        if (turnx != 0.0)
918                sendf(pymol,"turn x, %f\n", turnx);
919       
920        if (turny != 0.0)
921                sendf(pymol,"turn y, %f\n", turny);
922       
923        if (turnz != 0.0)
924                sendf(pymol,"turn z, %f\n", turnz);
925
926        return(pymol->status);
927}
928
929int
930ZoomCmd(ClientData cdata, Tcl_Interp *interp, int argc, const char *argv[])
931{
932    double factor = 0.0;
933    double zmove = 0.0;
934        struct pymol_proxy *pymol = (struct pymol_proxy *) cdata;
935    int defer = 0, push = 0, arg, varg = 1;
936
937        if (pymol == NULL)
938                return(TCL_ERROR);
939
940        clear_error(pymol);
941
942    for(arg = 1; arg < argc; arg++)
943        {
944            if (strcmp(argv[arg],"-defer") == 0)
945                    defer = 1;
946                else if (strcmp(argv[arg],"-push") == 0)
947                    push = 1;
948                else if (varg == 1) {
949                factor = atof(argv[arg]);
950                        varg++;
951                }
952    }
953
954        zmove = factor * -75;
955 
956    pymol->need_update = !defer || push;
957        pymol->immediate_update  |= push;
958        pymol->invalidate_cache = 1;
959
960        if (zmove != 0.0)
961                sendf(pymol,"move z, %f\n", factor);
962
963        return(pymol->status);
964}
965
966int
967PNGCmd(ClientData cdata, Tcl_Interp *interp, int argc, const char *argv[])
968{
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);
978
979    if (pymol->invalidate_cache)
980            pymol->cacheid++;
981
982        pymol->need_update = 0;
983        pymol->immediate_update = 0;
984        pymol->invalidate_cache = 0;
985
986        sendf(pymol,"png -\n");
987
988        waitForString(pymol, "image follows: ", buffer, 800);
989
990        sscanf(buffer, "image follows: %d %f\n", &bytes, &samples);
991 
992        write(3,&samples,sizeof(samples));
993 
994    dyBufferSetLength(&pymol->image, bytes);
995
996        bread(pymol->p_stdout, pymol->image.data, pymol->image.used);
997
998        waitForString(pymol, " ScenePNG", buffer,800);
999
1000    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
1011int
1012BMPCmd(ClientData cdata, Tcl_Interp *interp, int argc, const char *argv[])
1013{
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);
1023
1024    if (pymol->invalidate_cache)
1025            pymol->cacheid++;
1026
1027        pymol->need_update = 0;
1028        pymol->immediate_update = 0;
1029        pymol->invalidate_cache = 0;
1030
1031        sendf(pymol,"bmp -\n");
1032
1033        waitForString(pymol, "image follows: ", buffer, 800);
1034
1035        sscanf(buffer, "image follows: %d %f\n", &bytes, &samples);
1036        write(3,&samples,sizeof(samples));
1037
1038    dyBufferSetLength(&pymol->image, bytes);
1039
1040        bread(pymol->p_stdout, pymol->image.data, pymol->image.used);
1041
1042    if (bytes && (pymol->image.used == bytes)) {
1043            sprintf(buffer, "nv>image %d %d,%d,%d\n",
1044                    bytes, pymol->cacheid, pymol->frame, pymol->rock_offset);
1045            write(pymol->c_stdin, buffer, strlen(buffer));
1046                //fprintf(stderr,buffer);
1047            bwrite(pymol->c_stdin, pymol->image.data, bytes);
1048    }
1049
1050        return(pymol->status);
1051}
1052       
1053int pyMol_Proxy(int c_in, int c_out, char *command, char *argv[])
1054{
1055    int flags, status, result = 0;
1056        int pairIn[2];
1057        int pairOut[2];
1058        int pairErr[2];
1059        char buffer[800];
1060        Tcl_Interp *interp;
1061        Tcl_DString cmdbuffer;
1062        struct dyBuffer dybuffer, dybuffer2;
1063        struct pollfd ufd[3];
1064        int pid;
1065        struct pymol_proxy pymol;
1066        struct timeval now,end;
1067        int timeout;
1068
1069        /* Create three pipes for communication with the external application   */
1070        /* One each for the applications's: stdin, stdout, and stderr                   */
1071
1072        if (pipe(pairIn) == -1)
1073                return(-1);
1074
1075        if (pipe(pairOut) == -1) {
1076                close(pairIn[0]);
1077                close(pairIn[1]);
1078                return(-1);
1079        }
1080
1081        if (pipe(pairErr) == -1) {
1082                close(pairIn[0]);
1083                close(pairIn[1]);
1084                close(pairOut[0]);
1085                close(pairOut[1]);
1086                return(-1);
1087        }
1088
1089        /* Fork the new process.  Connect i/o to the new socket.                                */
1090
1091        pid = fork();
1092       
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        }
1119       
1120        /* close opposite end of pipe, these now belong to the child process    */
1121    close(pairIn[0]);
1122    close(pairOut[1]);
1123    close(pairErr[1]);
1124
1125        signal(SIGPIPE, SIG_IGN); // ignore SIGPIPE (ie if nanoscale terminates)
1126
1127        pymol.p_stdin = pairIn[1];
1128        pymol.p_stdout = pairOut[0];
1129        pymol.p_stderr = pairErr[0];
1130        pymol.c_stdin  = c_in;
1131        pymol.c_stdout = c_out;
1132        pymol.labels = 0;
1133        pymol.need_update = 0;
1134        pymol.can_update = 1;
1135        pymol.immediate_update = 0;
1136        pymol.sync = 0;
1137    pymol.frame = 1;
1138        pymol.rock_offset = 0;
1139        pymol.cacheid = 0;
1140        pymol.invalidate_cache = 0;
1141
1142        ufd[0].fd = pymol.c_stdout;
1143        ufd[0].events = POLLIN | POLLHUP; /* ensure catching EOF */
1144        ufd[1].fd = pymol.p_stdout;
1145        ufd[1].events = POLLIN | POLLHUP;
1146        ufd[2].fd = pymol.p_stderr;
1147        ufd[2].events = POLLIN | POLLHUP;
1148
1149    flags = fcntl(pymol.p_stdout, F_GETFL);
1150    fcntl(pymol.p_stdout, F_SETFL, flags|O_NONBLOCK);
1151
1152        interp = Tcl_CreateInterp();
1153        Tcl_MakeSafe(interp);
1154
1155        Tcl_DStringInit(&cmdbuffer);
1156        dyBufferInit(&pymol.image);
1157    dyBufferInit(&dybuffer);
1158    dyBufferInit(&dybuffer2);
1159
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
1197        {
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;
1202            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);
1333}
1334
1335#ifdef STANDALONE
1336
1337#define MAX_ARGS 100
1338
1339int
1340main(int argc, char *argv[])
1341{
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);
1356}
1357
1358#endif
1359
Note: See TracBrowser for help on using the repository browser.