diff options
Diffstat (limited to 'apps/plugins/pdbox/PDa/src/t_tkcmd.c')
-rw-r--r-- | apps/plugins/pdbox/PDa/src/t_tkcmd.c | 398 |
1 files changed, 0 insertions, 398 deletions
diff --git a/apps/plugins/pdbox/PDa/src/t_tkcmd.c b/apps/plugins/pdbox/PDa/src/t_tkcmd.c index 136412cad7..ff12a28494 100644 --- a/apps/plugins/pdbox/PDa/src/t_tkcmd.c +++ b/apps/plugins/pdbox/PDa/src/t_tkcmd.c | |||
@@ -396,401 +396,3 @@ int Pdtcl_SafeInit(Tcl_Interp *interp) { | |||
396 | return (TCL_OK); | 396 | return (TCL_OK); |
397 | } | 397 | } |
398 | 398 | ||
399 | /* Copyright (c) 1997-1999 Miller Puckette. | ||
400 | * For information on usage and redistribution, and for a DISCLAIMER OF ALL | ||
401 | * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ | ||
402 | |||
403 | #ifdef UNIX /* in unix this only works first; in NT it only works last. */ | ||
404 | #include "tk.h" | ||
405 | #endif | ||
406 | |||
407 | #include "t_tk.h" | ||
408 | #include <stdlib.h> | ||
409 | #include <string.h> | ||
410 | #include <stdio.h> | ||
411 | #include <stdarg.h> | ||
412 | #include <sys/types.h> | ||
413 | #ifdef UNIX | ||
414 | #include <unistd.h> | ||
415 | #include <sys/socket.h> | ||
416 | #include <netinet/in.h> | ||
417 | #include <netdb.h> | ||
418 | #ifdef HAVE_BSTRING_H | ||
419 | #include <bstring.h> | ||
420 | #endif | ||
421 | #include <sys/time.h> | ||
422 | #include <errno.h> | ||
423 | #endif | ||
424 | #ifdef MSW | ||
425 | #include <winsock.h> | ||
426 | #include <io.h> | ||
427 | #endif | ||
428 | #ifdef MSW | ||
429 | #pragma warning( disable : 4305 ) /* uncast const double to float */ | ||
430 | #pragma warning( disable : 4244 ) /* uncast double to float */ | ||
431 | #pragma warning( disable : 4101 ) /* unused local variables */ | ||
432 | #endif | ||
433 | |||
434 | #ifdef MSW | ||
435 | #include "tk.h" | ||
436 | #endif | ||
437 | |||
438 | void tcl_mess(char *s); | ||
439 | |||
440 | /***************** the socket setup code ********************/ | ||
441 | |||
442 | static int portno = 5400; | ||
443 | |||
444 | /* some installations of linux don't know about "localhost" so give | ||
445 | the loopback address; NT, on the other hand, can't understand the | ||
446 | hostname "127.0.0.1". */ | ||
447 | char hostname[100] = | ||
448 | #ifdef __linux__ | ||
449 | "127.0.0.1"; | ||
450 | #else | ||
451 | "localhost"; | ||
452 | #endif | ||
453 | |||
454 | void pdgui_setsock(int port) | ||
455 | { | ||
456 | portno = port; | ||
457 | } | ||
458 | |||
459 | void pdgui_sethost(char *name) | ||
460 | { | ||
461 | strncpy(hostname, name, 100); | ||
462 | hostname[99] = 0; | ||
463 | } | ||
464 | |||
465 | static void pdgui_sockerror(char *s) | ||
466 | { | ||
467 | #ifdef MSW | ||
468 | int err = WSAGetLastError(); | ||
469 | #endif | ||
470 | #ifdef UNIX | ||
471 | int err = errno; | ||
472 | #endif | ||
473 | |||
474 | fprintf(stderr, "%s: %s (%d)\n", s, strerror(err), err); | ||
475 | tcl_mess("exit\n"); | ||
476 | exit(1); | ||
477 | } | ||
478 | |||
479 | static int sockfd; | ||
480 | |||
481 | /* The "pd_suck" command, which polls the socket. | ||
482 | FIXME: if Pd sends something bigger than SOCKSIZE we're in trouble! | ||
483 | This has to be set bigger than any array update message for instance. | ||
484 | */ | ||
485 | #define SOCKSIZE 20000 | ||
486 | |||
487 | static char pd_tkbuf[SOCKSIZE+1]; | ||
488 | int pd_spillbytes = 0; | ||
489 | |||
490 | static void pd_readsocket(ClientData cd, int mask) | ||
491 | { | ||
492 | int ngot; | ||
493 | fd_set readset, writeset, exceptset; | ||
494 | struct timeval timout; | ||
495 | |||
496 | timout.tv_sec = 0; | ||
497 | timout.tv_usec = 0; | ||
498 | FD_ZERO(&writeset); | ||
499 | FD_ZERO(&readset); | ||
500 | FD_ZERO(&exceptset); | ||
501 | FD_SET(sockfd, &readset); | ||
502 | FD_SET(sockfd, &exceptset); | ||
503 | |||
504 | if (select(sockfd+1, &readset, &writeset, &exceptset, &timout) < 0) | ||
505 | perror("select"); | ||
506 | if (FD_ISSET(sockfd, &exceptset) || FD_ISSET(sockfd, &readset)) | ||
507 | { | ||
508 | int ret; | ||
509 | ret = recv(sockfd, pd_tkbuf + pd_spillbytes, | ||
510 | SOCKSIZE - pd_spillbytes, 0); | ||
511 | if (ret < 0) pdgui_sockerror("socket receive error"); | ||
512 | else if (ret == 0) | ||
513 | { | ||
514 | /* fprintf(stderr, "read %d\n", SOCKSIZE - pd_spillbytes); */ | ||
515 | fprintf(stderr, "pd_gui: pd process exited\n"); | ||
516 | tcl_mess("exit\n"); | ||
517 | } | ||
518 | else | ||
519 | { | ||
520 | char *lastcr = 0, *bp = pd_tkbuf, *ep = bp + (pd_spillbytes + ret); | ||
521 | int brace = 0; | ||
522 | char lastc = 0; | ||
523 | while (bp < ep) | ||
524 | { | ||
525 | char c = *bp; | ||
526 | if (c == '}' && brace) brace--; | ||
527 | else if (c == '{') brace++; | ||
528 | else if (!brace && c == '\n' && lastc != '\\') lastcr = bp; | ||
529 | lastc = c; | ||
530 | bp++; | ||
531 | } | ||
532 | if (lastcr) | ||
533 | { | ||
534 | int xtra = pd_tkbuf + pd_spillbytes + ret - (lastcr+1); | ||
535 | char bashwas = lastcr[1]; | ||
536 | lastcr[1] = 0; | ||
537 | tcl_mess(pd_tkbuf); | ||
538 | lastcr[1] = bashwas; | ||
539 | if (xtra) | ||
540 | { | ||
541 | /* fprintf(stderr, "x %d\n", xtra); */ | ||
542 | memmove(pd_tkbuf, lastcr+1, xtra); | ||
543 | } | ||
544 | pd_spillbytes = xtra; | ||
545 | } | ||
546 | else | ||
547 | { | ||
548 | pd_spillbytes += ret; | ||
549 | } | ||
550 | } | ||
551 | } | ||
552 | } | ||
553 | |||
554 | #ifndef UNIX | ||
555 | /* if we aren't UNIX, we add a tcl command to poll the | ||
556 | socket for data. */ | ||
557 | static int pd_pollsocketCmd(ClientData cd, Tcl_Interp *interp, | ||
558 | int argc, char **argv) | ||
559 | { | ||
560 | pd_readsocket(cd, 0); | ||
561 | return (TCL_OK); | ||
562 | } | ||
563 | #endif | ||
564 | |||
565 | void pdgui_setupsocket(void) | ||
566 | { | ||
567 | struct sockaddr_in server; | ||
568 | struct hostent *hp; | ||
569 | #ifdef UNIX | ||
570 | int retry = 10; | ||
571 | #else | ||
572 | int retry = 1; | ||
573 | #endif | ||
574 | #ifdef MSW | ||
575 | short version = MAKEWORD(2, 0); | ||
576 | WSADATA nobby; | ||
577 | |||
578 | if (WSAStartup(version, &nobby)) pdgui_sockerror("setup"); | ||
579 | #endif | ||
580 | |||
581 | /* create a socket */ | ||
582 | sockfd = socket(AF_INET, SOCK_STREAM, 0); | ||
583 | if (sockfd < 0) pdgui_sockerror("socket"); | ||
584 | |||
585 | /* connect socket using hostname provided in command line */ | ||
586 | server.sin_family = AF_INET; | ||
587 | |||
588 | hp = gethostbyname(hostname); | ||
589 | |||
590 | if (hp == 0) | ||
591 | { | ||
592 | fprintf(stderr, | ||
593 | "localhost not found (inet protocol not installed?)\n"); | ||
594 | exit(1); | ||
595 | } | ||
596 | memcpy((char *)&server.sin_addr, (char *)hp->h_addr, hp->h_length); | ||
597 | |||
598 | /* assign client port number */ | ||
599 | server.sin_port = htons((unsigned short)portno); | ||
600 | |||
601 | /* try to connect */ | ||
602 | while (1) | ||
603 | { | ||
604 | if (connect(sockfd, (struct sockaddr *) &server, sizeof (server)) >= 0) | ||
605 | goto gotit; | ||
606 | retry--; | ||
607 | if (retry <= 0) | ||
608 | break; | ||
609 | /* In UNIX there's a race condition; the child won't be | ||
610 | able to connect before the parent (pd) has shed its | ||
611 | setuid-ness. In case this is the problem, sleep and | ||
612 | retry. */ | ||
613 | else | ||
614 | { | ||
615 | #ifdef UNIX | ||
616 | fd_set readset, writeset, exceptset; | ||
617 | struct timeval timout; | ||
618 | |||
619 | timout.tv_sec = 0; | ||
620 | timout.tv_usec = 100000; | ||
621 | FD_ZERO(&writeset); | ||
622 | FD_ZERO(&readset); | ||
623 | FD_ZERO(&exceptset); | ||
624 | fprintf(stderr, "retrying connect...\n"); | ||
625 | if (select(1, &readset, &writeset, &exceptset, &timout) < 0) | ||
626 | perror("select"); | ||
627 | #endif /* UNIX */ | ||
628 | } | ||
629 | } | ||
630 | pdgui_sockerror("connecting stream socket"); | ||
631 | gotit: ; | ||
632 | #ifdef UNIX | ||
633 | /* in unix we ask TK to call us back. In NT we have to poll. */ | ||
634 | Tk_CreateFileHandler(sockfd, TK_READABLE | TK_EXCEPTION, | ||
635 | pd_readsocket, 0); | ||
636 | #endif /* UNIX */ | ||
637 | } | ||
638 | |||
639 | /**************************** commands ************************/ | ||
640 | static char *pdgui_path; | ||
641 | |||
642 | /* The "pd" command, which cats its args together and throws the result | ||
643 | * at the Pd interpreter. | ||
644 | */ | ||
645 | #define MAXWRITE 1024 | ||
646 | |||
647 | static int pdCmd(ClientData cd, Tcl_Interp *interp, int argc, char **argv) | ||
648 | { | ||
649 | if (argc == 2) | ||
650 | { | ||
651 | int n = strlen(argv[1]); | ||
652 | if (send(sockfd, argv[1], n, 0) < n) | ||
653 | { | ||
654 | perror("stdout"); | ||
655 | tcl_mess("exit\n"); | ||
656 | } | ||
657 | } | ||
658 | else | ||
659 | { | ||
660 | int i; | ||
661 | char buf[MAXWRITE]; | ||
662 | buf[0] = 0; | ||
663 | for (i = 1; i < argc; i++) | ||
664 | { | ||
665 | if (strlen(argv[i]) + strlen(buf) + 2 > MAXWRITE) | ||
666 | { | ||
667 | interp->result = "pd: arg list too long"; | ||
668 | return (TCL_ERROR); | ||
669 | } | ||
670 | if (i > 1) strcat(buf, " "); | ||
671 | strcat(buf, argv[i]); | ||
672 | } | ||
673 | if (send(sockfd, buf, strlen(buf), 0) < 0) | ||
674 | { | ||
675 | perror("stdout"); | ||
676 | tcl_mess("exit\n"); | ||
677 | } | ||
678 | } | ||
679 | return (TCL_OK); | ||
680 | } | ||
681 | |||
682 | /*********** "c" level access to tk functions. ******************/ | ||
683 | |||
684 | static Tcl_Interp *tk_myinterp; | ||
685 | |||
686 | void tcl_mess(char *s) | ||
687 | { | ||
688 | int result; | ||
689 | result = Tcl_Eval(tk_myinterp, s); | ||
690 | if (result != TCL_OK) | ||
691 | { | ||
692 | if (*tk_myinterp->result) printf("%s\n", tk_myinterp->result); | ||
693 | } | ||
694 | } | ||
695 | |||
696 | /* LATER should do a bounds check -- but how do you get printf to do that? */ | ||
697 | void tcl_vmess(char *fmt, ...) | ||
698 | { | ||
699 | int result, i; | ||
700 | char buf[MAXWRITE]; | ||
701 | va_list ap; | ||
702 | |||
703 | va_start(ap, fmt); | ||
704 | |||
705 | vsprintf(buf, fmt, ap); | ||
706 | result = Tcl_Eval(tk_myinterp, buf); | ||
707 | if (result != TCL_OK) | ||
708 | { | ||
709 | if (*tk_myinterp->result) printf("%s\n", tk_myinterp->result); | ||
710 | } | ||
711 | va_end(ap); | ||
712 | } | ||
713 | |||
714 | #ifdef UNIX | ||
715 | void pdgui_doevalfile(Tcl_Interp *interp, char *s) | ||
716 | { | ||
717 | char buf[GUISTRING]; | ||
718 | sprintf(buf, "set pd_guidir \"%s\"\n", pdgui_path); | ||
719 | tcl_mess(buf); | ||
720 | strcpy(buf, pdgui_path); | ||
721 | strcat(buf, "/bin/"); | ||
722 | strcat(buf, s); | ||
723 | if (Tcl_EvalFile(interp, buf) != TCL_OK) | ||
724 | { | ||
725 | char buf2[1000]; | ||
726 | sprintf(buf2, "puts [concat tcl: %s: can't open script]\n", | ||
727 | buf); | ||
728 | tcl_mess(buf2); | ||
729 | } | ||
730 | } | ||
731 | |||
732 | void pdgui_evalfile(char *s) | ||
733 | { | ||
734 | pdgui_doevalfile(tk_myinterp, s); | ||
735 | } | ||
736 | #endif | ||
737 | |||
738 | void pdgui_startup(Tcl_Interp *interp) | ||
739 | { | ||
740 | |||
741 | /* save pointer to the main interpreter */ | ||
742 | tk_myinterp = interp; | ||
743 | |||
744 | |||
745 | /* add our own TK commands */ | ||
746 | Tcl_CreateCommand(interp, "pd", (Tcl_CmdProc*)pdCmd, (ClientData)NULL, | ||
747 | (Tcl_CmdDeleteProc *)NULL); | ||
748 | #ifndef UNIX | ||
749 | Tcl_CreateCommand(interp, "pd_pollsocket",(Tcl_CmdProc*) pd_pollsocketCmd, | ||
750 | (ClientData)NULL, (Tcl_CmdDeleteProc *)NULL); | ||
751 | #endif | ||
752 | pdgui_setupsocket(); | ||
753 | |||
754 | /* read in the startup file */ | ||
755 | #if !defined(MSW) && !defined(MACOSX) | ||
756 | pdgui_evalfile("pd.tk"); | ||
757 | #endif | ||
758 | } | ||
759 | |||
760 | #ifdef UNIX | ||
761 | void pdgui_setname(char *s) | ||
762 | { | ||
763 | char *t; | ||
764 | char *str; | ||
765 | int n; | ||
766 | if (t = strrchr(s, '/')) str = s, n = (t-s) + 1; | ||
767 | else str = "./", n = 2; | ||
768 | if (n > GUISTRING-100) n = GUISTRING-100; | ||
769 | pdgui_path = malloc(n+9); | ||
770 | |||
771 | strncpy(pdgui_path, str, n); | ||
772 | while (strlen(pdgui_path) > 0 && pdgui_path[strlen(pdgui_path)-1] == '/') | ||
773 | pdgui_path[strlen(pdgui_path)-1] = 0; | ||
774 | if (t = strrchr(pdgui_path, '/')) | ||
775 | *t = 0; | ||
776 | } | ||
777 | #endif | ||
778 | |||
779 | int Pdtcl_Init(Tcl_Interp *interp) | ||
780 | { | ||
781 | const char *myvalue = Tcl_GetVar(interp, "argv", 0); | ||
782 | int myportno; | ||
783 | if (myvalue && (myportno = atoi(myvalue)) > 1) | ||
784 | pdgui_setsock(myportno); | ||
785 | tk_myinterp = interp; | ||
786 | pdgui_startup(interp); | ||
787 | interp->result = "loaded pdtcl_init"; | ||
788 | |||
789 | return (TCL_OK); | ||
790 | } | ||
791 | |||
792 | int Pdtcl_SafeInit(Tcl_Interp *interp) { | ||
793 | fprintf(stderr, "Pdtcl_Safeinit 51\n"); | ||
794 | return (TCL_OK); | ||
795 | } | ||
796 | |||