/* * Copyright (c) 1991-1994 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the Computer Systems * Engineering Group at Lawrence Berkeley Laboratory. * 4. Neither the name of the University nor of the Laboratory may be used * to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ static const char rcsid[] = "@(#) $Header: main.cc,v 1.48 96/05/03 06:27:20 van Exp $ (LBL)"; #include "config.h" #include #include #include #ifdef WIN32 #include #else #include #include #include #endif #include "sys-time.h" #ifdef sgi #include #endif #ifdef _AIX #include #endif extern "C" { #include } #ifndef WIN32 #include #endif #include "inet.h" #include "Tcl.h" extern "C" int Tk_StripchartCmd(ClientData, Tcl_Interp*, int ac, char** av); #ifdef WIN32 extern "C" int WinPutsCmd(ClientData, Tcl_Interp*, int ac, char** av); extern "C" int WinGetUserName(ClientData, Tcl_Interp*, int ac, char** av); extern "C" int WinPutRegistry(ClientData, Tcl_Interp*, int ac, char** av); extern "C" int WinGetRegistry(ClientData, Tcl_Interp*, int ac, char** av); #endif /*XXX*/ #define PROTOTYPES 1 #include "global.h" #include "md5.h" #if defined(sun) && defined(__svr4__) #include #define gethostname(name, len) { \ struct utsname _uts_; \ \ if (uname(&_uts_) < 0) { \ perror("uname"); \ exit(1); \ }\ \ strcpy((name), _uts_.nodename); \ } #endif static void usage() { fprintf(stderr, "\ usage: vat [-aAcdEjJkLMnrRsSv] [-C conf] [-D dump] [-f format] [-F device]\n\ \t[-g geometry] [-d display] [-I chan] [-K key] [-N name] [-K key ]\n\ \t[-t ttl] [-u script] [-U socket] [-X res=val] dest/port[/fmt/ttl]\n" ); exit(1); } static class UsageCommand : public TclObject { public: UsageCommand() : TclObject("usage") {} int command(int argc, const char*const* argv) { usage(); /*NOTREACHED*/ return (0); } } cmd_usage; #ifndef SIGARGS #define SIGARGS ... #endif #ifdef SIGCHLD static SIGRET ReapChild(SIGARGS) { while (waitpid(-1, 0, WNOHANG) > 0) ; } #endif extern void adios(); static SIGRET DoQuit(SIGARGS) { adios(); } void initcatchers() { signal(SIGINT, DoQuit); #ifdef SIGHUP signal(SIGHUP, DoQuit); #endif signal(SIGTERM, DoQuit); #ifdef SIGCHLD signal(SIGCHLD, ReapChild); #endif } static class AdiosCommand : public TclObject { public: AdiosCommand() : TclObject("adios") {} int command(int argc, const char*const* argv) { adios(); /*NOTREACHED*/ return (0); } } cmd_adios; static class HaveFontCommand : public TclObject { public: HaveFontCommand() : TclObject("havefont") {} int command(int argc, const char*const* argv) { Tcl& t = Tcl::instance(); if (argc != 2) t.result("0"); else { Tk_Window tk = t.tkmain(); Tk_Uid uid = Tk_GetUid((char*)argv[1]); Tk_Font p = Tk_GetFont(t.interp(), tk, uid); t.result(p != 0 ? "1" : "0"); } return (TCL_OK); } } cmd_havefont; static class GetHostNameCommand : public TclObject { public: GetHostNameCommand() : TclObject("gethostname") {} int command(int argc, const char*const* argv) { Tcl& tcl = Tcl::instance(); char* bp = tcl.buffer(); tcl.result(bp); gethostname(bp, MAXHOSTNAMELEN); return (TCL_OK); } } cmd_gethostname; extern "C" char version[]; static class VersionCommand : public TclObject { public: VersionCommand() : TclObject("version") {} int command(int argc, const char*const* argv) { Tcl::instance().result(version); return (TCL_OK); } } cmd_version; extern "C" char *optarg; extern "C" int optind; extern "C" int opterr; int yesno(const char* s) { if (s == 0) return (0); if (isdigit(*s)) return (atoi(s)); int ret; switch (*s) { case 't': case 'T': case 'y': case 'Y': case '1': ret = 1; break; case 'o': case 'O': ret = (s[1] == 'n' || s[1] == 'N'); break; default: ret = 0; break; } return (ret); } #ifndef sgi inline #endif static void set_option(Tk_Window tk, const char* name, const char* value) { char wrk[80]; sprintf(wrk, "Vat.%s", name); Tk_AddOption(tk, wrk, (char*)value, TK_USER_DEFAULT_PRIO + 1); } static void toggle_option(const char* name) { Tcl& tcl = Tcl::instance(); const char* value = tcl.attr(name); if (value != 0 && yesno(value)) tcl.add_option(name, "0"); else tcl.add_option(name, "1"); } static int is_whitespace(const char* s) { int c; while ((c = *s++) != 0) if (!isspace(c)) return (0); return (1); } #if defined(__hpux) || defined(sco) #ifdef sco #define gethostid xgethostid #else #include #endif gethostid() { int id; char hostname[256]; /* 255 is max legal DNS name */ size_t hostname_size = 256; struct hostent *hostp; struct in_addr addru; /* union for conversion */ (void) gethostname(hostname, hostname_size); hostname[hostname_size] = '\0'; /* make sure it is null-terminated */ hostp = gethostbyname(hostname); if(hostp == NULL) /* our own name was not found! punt. */ id = 0; else { /* return first address of host */ memcpy(&(addru.s_addr), hostp->h_addr_list[0], 4); id = addru.s_addr; } return id; } #endif #ifdef __svr4__ #include #define gethostid xgethostid gethostid() { char wrk[32]; if (sysinfo(SI_HW_SERIAL, wrk, sizeof(wrk)) > 0) return (atoi(wrk)); return (0); } #endif /* * From the RTP spec. */ u_int32_t heuristic_random() { struct { struct timeval tv; clock_t cpu; pid_t pid; u_long hid; uid_t uid; gid_t gid; struct utsname name; } s; gettimeofday(&s.tv, 0); uname(&s.name); s.cpu = clock(); s.pid = getpid(); s.hid = gethostid(); s.uid = getuid(); s.gid = getgid(); MD5_CTX context; MD5Init(&context); MD5Update(&context, (u_char*)&s, sizeof(s)); u_int32_t out[4]; MD5Final((u_char *)out, &context); return (out[0] ^ out[1] ^ out[2] ^ out[3]); } #include "bitmaps/speaker.xbm" #include "bitmaps/headphone.xbm" #include "bitmaps/lineout.xbm" #include "bitmaps/lineout2.xbm" #include "bitmaps/lineout3.xbm" #include "bitmaps/mic.xbm" #include "bitmaps/linein.xbm" #include "bitmaps/linein2.xbm" #include "bitmaps/linein3.xbm" #include "bitmaps/square.xbm" void loadbitmaps(Tcl_Interp* tcl) { Tk_DefineBitmap(tcl, Tk_GetUid("speaker"), speaker_bits, speaker_width, speaker_height); Tk_DefineBitmap(tcl, Tk_GetUid("headphone"), headphone_bits, headphone_width, headphone_height); Tk_DefineBitmap(tcl, Tk_GetUid("lineout"), lineout_bits, lineout_width, lineout_height); Tk_DefineBitmap(tcl, Tk_GetUid("lineout2"), lineout2_bits, lineout2_width, lineout2_height); Tk_DefineBitmap(tcl, Tk_GetUid("lineout3"), lineout3_bits, lineout3_width, lineout3_height); Tk_DefineBitmap(tcl, Tk_GetUid("mike"), mic_bits, mic_width, mic_height); Tk_DefineBitmap(tcl, Tk_GetUid("linein"), linein_bits, linein_width, linein_height); Tk_DefineBitmap(tcl, Tk_GetUid("linein2"), linein2_bits, linein2_width, linein2_height); Tk_DefineBitmap(tcl, Tk_GetUid("linein3"), linein3_bits, linein3_width, linein3_height); Tk_DefineBitmap(tcl, Tk_GetUid("square"), square_bits, square_width, square_height); } const char* disparg(int argc, const char*const* argv, const char* optstr) { const char* display = 0; int op; while ((op = getopt(argc, (char**)argv, (char*)optstr)) != -1) { if (op == 'd') { display = optarg; break; } else if (op == '?') usage(); } #ifdef linux optind = 0; #else optind = 1; #endif return (display); } char* parse_assignment(char* cp) { cp = strchr(cp, '='); if (cp != 0) { *cp = 0; return (cp + 1); } else return ("true"); } extern "C" { int TkPlatformInit(Tcl_Interp *interp) { Tcl_SetVar(interp, "tk_library", ".", TCL_GLOBAL_ONLY); #ifndef WIN32 extern void TkCreateXEventSource(void); TkCreateXEventSource(); #endif return (TCL_OK); } } int main(int argc, char **argv) { srandom(heuristic_random()); opterr = 0; const char* options = "aAB:cC:d:DEf:F:g:I:jJkK:lLMnN:p:P:rRsSt:U:u:X:"; const char* display = disparg(argc, (const char*const*)argv, options); Tcl::init("vat"); Tcl& tcl = Tcl::instance(); #ifdef WIN32 if (display == NULL) display = "localhost:0"; #endif #ifdef TCL_WINDOW_EVENTS tcl.evalf(display? "set argv \"-name vat -display %s\"" : "set argv \"-name vat\"", display); Tk_Window tk = 0; if (Tk_Init(tcl.interp()) == TCL_OK) tk = Tk_MainWindow(tcl.interp()); #else Tk_Window tk = Tk_CreateMainWindow(tcl.interp(), (char*)display, "vat", "Vat"); #endif if (tk == 0) { fprintf(stderr, "vat: %s\n", tcl.result()); exit(1); } tcl.tkmain(tk); loadbitmaps(tcl.interp()); tcl.CreateCommand("stripchart", Tk_StripchartCmd, (ClientData)tk); #ifdef WIN32 tcl.CreateCommand("puts", WinPutsCmd, (ClientData)tk); tcl.CreateCommand("getusername", WinGetUserName, (ClientData)tk); tcl.CreateCommand("putregistry", WinPutRegistry, (ClientData)tk); tcl.CreateCommand("getregistry", WinGetRegistry, (ClientData)tk); #endif EmbeddedTcl::init(); tcl.evalc("init_resources"); int op; while ((op = getopt(argc, argv, (char*)options)) != -1) { switch (op) { default: usage(); exit(1); case 'a': toggle_option("speakerAGC"); break; case 'A': toggle_option("mikeAGC"); break; case 'B': tcl.add_option("maxbw", optarg); break; case 'c': tcl.add_option("lectureMode", "0"); break; case 'C': tcl.add_option("conferenceName", optarg); break; case 'd': /* display (already processed) */ break; case 'D': tcl.add_option("meterDisable", "1"); break; case 'E': tcl.add_option("externalEchoCancel", "1"); break; case 'f': tcl.add_option("audioFormat", optarg); break; case 'F': tcl.add_option("audioFileName", optarg); break; case 'g': tcl.add_option("geometry", optarg); break; case 'I': tcl.add_option("confBusChannel", optarg); break; case 'j': tcl.add_option("outputPort", "Jack"); break; case 'J': toggle_option("speakerMute"); break; case 'k': tcl.add_option("keepSites", "1"); break; case 'K': /*XXX probably do not want this in X server*/ tcl.add_option("sessionKey", optarg); break; case 'l': tcl.add_option("lectureMode", "1"); break; case 'L': tcl.add_option("keepSites", "0"); break; case 'M': toggle_option("mikeMute"); break; case 'N': tcl.add_option("rtpName", optarg); break; case 'n': tcl.add_option("sessionType", "vat"); break; case 'P': tcl.add_option("defaultPriority", optarg); break; case 'r': tcl.add_option("sessionType", "rtp"); break; case 'R': tcl.add_option("recvOnly", "true"); break; case 's': tcl.add_option("outputPort", "Speaker"); break; case 'S': tcl.add_option("muteNewSites", "1"); break; case 't': tcl.add_option("defaultTTL", optarg); break; case 'u': tcl.add_option("startupScript", optarg); break; case 'U': if (optarg[0] >= '0' && optarg[0] <= '9') { tcl.add_option("defaultDevice", "af"); tcl.add_option("useAF", "true"); tcl.add_option("afDevice", optarg); } else tcl.add_option("defaultDevice", optarg); break; case 'X': { const char* value = parse_assignment(optarg); tcl.add_option(optarg, value); } break; } } const char* dst; if (optind < argc && argc > 1) { dst = argv[optind]; if (argc - optind > 1) { fprintf(stderr, "vat: extra arguments (starting with `%s')\n", argv[optind + 1]); exit(1); } } else if ((dst = tcl.attr("defaultHostSpec")) == 0) { fprintf(stderr, "vat: destination address required\n"); exit(1); } tcl.add_option("defaultHostSpec", dst); tcl.evalc("vat_main"); initcatchers(); /* win32 needs the following to get the initial window painted */ tcl.evalc("update idletasks"); Tk_MainLoop(); adios(); /* NOTREACHED*/ return (0); }