summaryrefslogtreecommitdiff
path: root/apps/plugins/pdbox/PDa/src/s_inter.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/pdbox/PDa/src/s_inter.c')
-rw-r--r--apps/plugins/pdbox/PDa/src/s_inter.c1000
1 files changed, 0 insertions, 1000 deletions
diff --git a/apps/plugins/pdbox/PDa/src/s_inter.c b/apps/plugins/pdbox/PDa/src/s_inter.c
index 37c44770ed..9df9c82b40 100644
--- a/apps/plugins/pdbox/PDa/src/s_inter.c
+++ b/apps/plugins/pdbox/PDa/src/s_inter.c
@@ -998,1003 +998,3 @@ void glob_quit(void *dummy)
998 sys_bail(0); 998 sys_bail(0);
999} 999}
1000 1000
1001/* Copyright (c) 1997-1999 Miller Puckette.
1002* For information on usage and redistribution, and for a DISCLAIMER OF ALL
1003* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
1004
1005/* Pd side of the Pd/Pd-gui interface. Also, some system interface routines
1006that didn't really belong anywhere. */
1007
1008#include "m_pd.h"
1009#include "s_stuff.h"
1010#include "m_imp.h"
1011#ifdef UNIX
1012#include <unistd.h>
1013#include <sys/socket.h>
1014#include <netinet/in.h>
1015#include <netinet/tcp.h>
1016#include <netdb.h>
1017#include <stdlib.h>
1018#include <sys/time.h>
1019#include <sys/mman.h>
1020#endif
1021#ifdef HAVE_BSTRING_H
1022#include <bstring.h>
1023#endif
1024#ifdef MSW
1025#include <io.h>
1026#include <fcntl.h>
1027#include <process.h>
1028#include <winsock.h>
1029typedef int pid_t;
1030#define EADDRINUSE WSAEADDRINUSE
1031#endif
1032#include <stdarg.h>
1033#include <signal.h>
1034#include <fcntl.h>
1035#include <errno.h>
1036#include <string.h>
1037#include <stdio.h>
1038
1039#ifdef MACOSX
1040#include <sys/types.h>
1041#include <sys/stat.h>
1042#include <pthread.h>
1043#else
1044#include <stdlib.h>
1045#endif
1046
1047#define DEBUG_MESSUP 1 /* messages up from pd to pd-gui */
1048#define DEBUG_MESSDOWN 2 /* messages down from pd-gui to pd */
1049
1050/* T.Grill - make it a _little_ more adaptable... */
1051#ifndef PDBINDIR
1052#define PDBINDIR "bin/"
1053#endif
1054
1055#ifndef WISHAPP
1056#define WISHAPP "wish83.exe"
1057#endif
1058
1059extern char pd_version[];
1060
1061typedef struct _fdpoll
1062{
1063 int fdp_fd;
1064 t_fdpollfn fdp_fn;
1065 void *fdp_ptr;
1066} t_fdpoll;
1067
1068#define INBUFSIZE 4096
1069
1070struct _socketreceiver
1071{
1072 char *sr_inbuf;
1073 int sr_inhead;
1074 int sr_intail;
1075 void *sr_owner;
1076 int sr_udp;
1077 t_socketnotifier sr_notifier;
1078 t_socketreceivefn sr_socketreceivefn;
1079};
1080
1081static int sys_nfdpoll;
1082static t_fdpoll *sys_fdpoll;
1083static int sys_maxfd;
1084static int sys_guisock;
1085
1086static t_binbuf *inbinbuf;
1087static t_socketreceiver *sys_socketreceiver;
1088extern int sys_addhist(int phase);
1089
1090#ifdef MSW
1091static LARGE_INTEGER nt_inittime;
1092static double nt_freq = 0;
1093
1094static void sys_initntclock(void)
1095{
1096 LARGE_INTEGER f1;
1097 LARGE_INTEGER now;
1098 QueryPerformanceCounter(&now);
1099 if (!QueryPerformanceFrequency(&f1))
1100 {
1101 fprintf(stderr, "pd: QueryPerformanceFrequency failed\n");
1102 f1.QuadPart = 1;
1103 }
1104 nt_freq = f1.QuadPart;
1105 nt_inittime = now;
1106}
1107
1108#if 0
1109 /* this is a version you can call if you did the QueryPerformanceCounter
1110 call yourself. Necessary for time tagging incoming MIDI at interrupt
1111 level, for instance; but we're not doing that just now. */
1112
1113double nt_tixtotime(LARGE_INTEGER *dumbass)
1114{
1115 if (nt_freq == 0) sys_initntclock();
1116 return (((double)(dumbass->QuadPart - nt_inittime.QuadPart)) / nt_freq);
1117}
1118#endif
1119#endif /* MSW */
1120
1121 /* get "real time" in seconds; take the
1122 first time we get called as a reference time of zero. */
1123t_time sys_getrealtime(void)
1124{
1125#ifdef UNIX
1126 static struct timeval then;
1127 struct timeval now;
1128 gettimeofday(&now, 0);
1129 if (then.tv_sec == 0 && then.tv_usec == 0) then = now;
1130 return (now.tv_sec - then.tv_sec)*1000000 +
1131 (now.tv_usec - then.tv_usec);
1132#endif
1133#ifdef MSW
1134 LARGE_INTEGER now;
1135 QueryPerformanceCounter(&now);
1136 if (nt_freq == 0) sys_initntclock();
1137 return (((double)(now.QuadPart - nt_inittime.QuadPart)) / nt_freq);
1138#endif
1139}
1140
1141void sys_sockerror(char *s)
1142{
1143#ifdef MSW
1144 int err = WSAGetLastError();
1145 if (err == 10054) return;
1146 else if (err == 10044)
1147 {
1148 fprintf(stderr,
1149 "Warning: you might not have TCP/IP \"networking\" turned on\n");
1150 fprintf(stderr, "which is needed for Pd to talk to its GUI layer.\n");
1151 }
1152#endif
1153#ifdef UNIX
1154 int err = errno;
1155#endif
1156 fprintf(stderr, "%s: %s (%d)\n", s, strerror(err), err);
1157}
1158
1159void sys_addpollfn(int fd, t_fdpollfn fn, void *ptr)
1160{
1161 int nfd = sys_nfdpoll;
1162 int size = nfd * sizeof(t_fdpoll);
1163 t_fdpoll *fp;
1164 sys_fdpoll = (t_fdpoll *)t_resizebytes(sys_fdpoll, size,
1165 size + sizeof(t_fdpoll));
1166 fp = sys_fdpoll + nfd;
1167 fp->fdp_fd = fd;
1168 fp->fdp_fn = fn;
1169 fp->fdp_ptr = ptr;
1170 sys_nfdpoll = nfd + 1;
1171 if (fd >= sys_maxfd) sys_maxfd = fd + 1;
1172}
1173
1174void sys_rmpollfn(int fd)
1175{
1176 int nfd = sys_nfdpoll;
1177 int i, size = nfd * sizeof(t_fdpoll);
1178 t_fdpoll *fp;
1179 for (i = nfd, fp = sys_fdpoll; i--; fp++)
1180 {
1181 if (fp->fdp_fd == fd)
1182 {
1183 while (i--)
1184 {
1185 fp[0] = fp[1];
1186 fp++;
1187 }
1188 sys_fdpoll = (t_fdpoll *)t_resizebytes(sys_fdpoll, size,
1189 size - sizeof(t_fdpoll));
1190 sys_nfdpoll = nfd - 1;
1191 return;
1192 }
1193 }
1194 post("warning: %d removed from poll list but not found", fd);
1195}
1196
1197static int sys_domicrosleep(int microsec, int pollem)
1198{
1199 struct timeval timout;
1200 int i, didsomething = 0;
1201 t_fdpoll *fp;
1202 timout.tv_sec = 0;
1203 timout.tv_usec = microsec;
1204 if (pollem)
1205 {
1206 fd_set readset, writeset, exceptset;
1207 FD_ZERO(&writeset);
1208 FD_ZERO(&readset);
1209 FD_ZERO(&exceptset);
1210 for (fp = sys_fdpoll, i = sys_nfdpoll; i--; fp++)
1211 FD_SET(fp->fdp_fd, &readset);
1212 select(sys_maxfd+1, &readset, &writeset, &exceptset, &timout);
1213 for (i = 0; i < sys_nfdpoll; i++)
1214 if (FD_ISSET(sys_fdpoll[i].fdp_fd, &readset))
1215 {
1216 (*sys_fdpoll[i].fdp_fn)(sys_fdpoll[i].fdp_ptr, sys_fdpoll[i].fdp_fd);
1217 didsomething = 1;
1218 }
1219 return (didsomething);
1220 }
1221 else
1222 {
1223 select(0, 0, 0, 0, &timout);
1224 return (0);
1225 }
1226}
1227
1228void sys_microsleep(int microsec)
1229{
1230 sys_domicrosleep(microsec, 1);
1231}
1232
1233t_socketreceiver *socketreceiver_new(void *owner, t_socketnotifier notifier,
1234 t_socketreceivefn socketreceivefn, int udp)
1235{
1236 t_socketreceiver *x = (t_socketreceiver *)getbytes(sizeof(*x));
1237 x->sr_inhead = x->sr_intail = 0;
1238 x->sr_owner = owner;
1239 x->sr_notifier = notifier;
1240 x->sr_socketreceivefn = socketreceivefn;
1241 x->sr_udp = udp;
1242 if (!(x->sr_inbuf = malloc(INBUFSIZE))) bug("t_socketreceiver");;
1243 return (x);
1244}
1245
1246void socketreceiver_free(t_socketreceiver *x)
1247{
1248 free(x->sr_inbuf);
1249 freebytes(x, sizeof(*x));
1250}
1251
1252 /* this is in a separately called subroutine so that the buffer isn't
1253 sitting on the stack while the messages are getting passed. */
1254static int socketreceiver_doread(t_socketreceiver *x)
1255{
1256 char messbuf[INBUFSIZE], *bp = messbuf;
1257 int indx;
1258 int inhead = x->sr_inhead;
1259 int intail = x->sr_intail;
1260 char *inbuf = x->sr_inbuf;
1261 if (intail == inhead) return (0);
1262 for (indx = intail; indx != inhead; indx = (indx+1)&(INBUFSIZE-1))
1263 {
1264 /* if we hit a semi that isn't preceeded by a \, it's a message
1265 boundary. LATER we should deal with the possibility that the
1266 preceeding \ might itself be escaped! */
1267 char c = *bp++ = inbuf[indx];
1268 if (c == ';' && (!indx || inbuf[indx-1] != '\\'))
1269 {
1270 intail = (indx+1)&(INBUFSIZE-1);
1271 binbuf_text(inbinbuf, messbuf, bp - messbuf);
1272 if (sys_debuglevel & DEBUG_MESSDOWN)
1273 {
1274 write(2, messbuf, bp - messbuf);
1275 write(2, "\n", 1);
1276 }
1277 x->sr_inhead = inhead;
1278 x->sr_intail = intail;
1279 return (1);
1280 }
1281 }
1282 return (0);
1283}
1284
1285static void socketreceiver_getudp(t_socketreceiver *x, int fd)
1286{
1287 char buf[INBUFSIZE+1];
1288 int ret = recv(fd, buf, INBUFSIZE, 0);
1289 if (ret < 0)
1290 {
1291 sys_sockerror("recv");
1292 sys_rmpollfn(fd);
1293 sys_closesocket(fd);
1294 }
1295 else if (ret > 0)
1296 {
1297 buf[ret] = 0;
1298#if 0
1299 post("%s", buf);
1300#endif
1301 if (buf[ret-1] != '\n')
1302 {
1303#if 0
1304 buf[ret] = 0;
1305 error("dropped bad buffer %s\n", buf);
1306#endif
1307 }
1308 else
1309 {
1310 char *semi = strchr(buf, ';');
1311 if (semi)
1312 *semi = 0;
1313 binbuf_text(inbinbuf, buf, strlen(buf));
1314 outlet_setstacklim();
1315 if (x->sr_socketreceivefn)
1316 (*x->sr_socketreceivefn)(x->sr_owner, inbinbuf);
1317 else bug("socketreceiver_getudp");
1318 }
1319 }
1320}
1321
1322
1323
1324#include <termios.h>
1325#include <string.h>
1326
1327static struct termios stored_settings;
1328EXTERN int sys_stdin;
1329
1330void set_keypress(void)
1331{
1332 struct termios new_settings;
1333
1334 tcgetattr(0,&stored_settings);
1335
1336 new_settings = stored_settings;
1337
1338 /* Disable canonical mode, and set buffer size to 1 byte */
1339 new_settings.c_lflag &= (~ICANON);
1340 new_settings.c_cc[VTIME] = 0;
1341 new_settings.c_cc[VMIN] = 1;
1342
1343/* echo off */
1344 new_settings.c_lflag &= (~ECHO);
1345
1346 tcsetattr(0,TCSANOW,&new_settings);
1347 return;
1348}
1349
1350void reset_keypress(void)
1351{
1352 if (sys_stdin)
1353 tcsetattr(0,TCSANOW,&stored_settings);
1354 return;
1355}
1356
1357static t_symbol* _ss;
1358
1359
1360void stdin_read(t_socketreceiver *x, int fd) {
1361 static char input[256];
1362
1363 char* in;
1364 int got;
1365
1366 got = read(fd,input,256);
1367 in = input;
1368 while (got-- && _ss->s_thing)
1369 pd_float(_ss->s_thing,(float)*in++);
1370}
1371
1372void socketreceiver_read(t_socketreceiver *x, int fd)
1373{
1374 if (x->sr_udp) /* UDP ("datagram") socket protocol */
1375 socketreceiver_getudp(x, fd);
1376 else /* TCP ("streaming") socket protocol */
1377 {
1378 char *semi;
1379 int readto =
1380 (x->sr_inhead >= x->sr_intail ? INBUFSIZE : x->sr_intail-1);
1381 int ret;
1382
1383 /* the input buffer might be full. If so, drop the whole thing */
1384 if (readto == x->sr_inhead)
1385 {
1386 fprintf(stderr, "pd: dropped message from gui\n");
1387 x->sr_inhead = x->sr_intail = 0;
1388 readto = INBUFSIZE;
1389 }
1390 else
1391 {
1392 ret = recv(fd, x->sr_inbuf + x->sr_inhead,
1393 readto - x->sr_inhead, 0);
1394 if (ret < 0)
1395 {
1396 sys_sockerror("recv");
1397 if (x == sys_socketreceiver) sys_bail(1);
1398 else
1399 {
1400 if (x->sr_notifier) (*x->sr_notifier)(x->sr_owner);
1401 sys_rmpollfn(fd);
1402 sys_closesocket(fd);
1403 }
1404 }
1405 else if (ret == 0)
1406 {
1407 if (x == sys_socketreceiver)
1408 {
1409 fprintf(stderr, "pd: exiting\n");
1410 sys_bail(0);
1411 }
1412 else
1413 {
1414 post("EOF on socket %d\n", fd);
1415 if (x->sr_notifier) (*x->sr_notifier)(x->sr_owner);
1416 sys_rmpollfn(fd);
1417 sys_closesocket(fd);
1418 }
1419 }
1420 else
1421 {
1422 x->sr_inhead += ret;
1423 if (x->sr_inhead >= INBUFSIZE) x->sr_inhead = 0;
1424 while (socketreceiver_doread(x))
1425 {
1426 outlet_setstacklim();
1427 if (x->sr_socketreceivefn)
1428 (*x->sr_socketreceivefn)(x->sr_owner, inbinbuf);
1429 else binbuf_eval(inbinbuf, 0, 0, 0);
1430 }
1431 }
1432 }
1433 }
1434}
1435
1436void sys_closesocket(int fd)
1437{
1438#ifdef UNIX
1439 close(fd);
1440#endif
1441#ifdef MSW
1442 closesocket(fd);
1443#endif
1444}
1445
1446
1447void sys_gui(char *s)
1448{
1449 int length = strlen(s), written = 0, res, histwas = sys_addhist(4);
1450 if (sys_debuglevel & DEBUG_MESSUP)
1451 fprintf(stderr, "%s", s);
1452 if (sys_nogui)
1453 return;
1454 while (1)
1455 {
1456 res = send(sys_guisock, s + written, length, 0);
1457 if (res < 0)
1458 {
1459 perror("pd output pipe");
1460 sys_bail(1);
1461 }
1462 else
1463 {
1464 written += res;
1465 if (written >= length)
1466 break;
1467 }
1468 }
1469 sys_addhist(histwas);
1470}
1471
1472/* LATER should do a bounds check -- but how do you get printf to do that?
1473 See also rtext_senditup() in this regard */
1474
1475void sys_vgui(char *fmt, ...)
1476{
1477 int result, i;
1478 char buf[2048];
1479 va_list ap;
1480
1481 va_start(ap, fmt);
1482 vsprintf(buf, fmt, ap);
1483 sys_gui(buf);
1484 va_end(ap);
1485}
1486
1487
1488#define FIRSTPORTNUM 5400
1489
1490/* -------------- signal handling for UNIX -------------- */
1491
1492#ifdef UNIX
1493typedef void (*sighandler_t)(int);
1494
1495static void sys_signal(int signo, sighandler_t sigfun)
1496{
1497 struct sigaction action;
1498 action.sa_flags = 0;
1499 action.sa_handler = sigfun;
1500 memset(&action.sa_mask, 0, sizeof(action.sa_mask));
1501#if 0 /* GG says: don't use that */
1502 action.sa_restorer = 0;
1503#endif
1504 if (sigaction(signo, &action, 0) < 0)
1505 perror("sigaction");
1506}
1507
1508static void sys_exithandler(int n)
1509{
1510 static int trouble = 0;
1511 if (!trouble)
1512 {
1513 trouble = 1;
1514 fprintf(stderr, "Pd: signal %d\n", n);
1515 sys_bail(1);
1516
1517 }
1518 else _exit(1);
1519}
1520
1521static void sys_alarmhandler(int n)
1522{
1523 fprintf(stderr, "Pd: system call timed out\n");
1524}
1525
1526static void sys_huphandler(int n)
1527{
1528 struct timeval timout;
1529 timout.tv_sec = 0;
1530 timout.tv_usec = 30000;
1531 select(1, 0, 0, 0, &timout);
1532}
1533
1534void sys_setalarm(int microsec)
1535{
1536 struct itimerval gonzo;
1537#if 0
1538 fprintf(stderr, "timer %d\n", microsec);
1539#endif
1540 gonzo.it_interval.tv_sec = 0;
1541 gonzo.it_interval.tv_usec = 0;
1542 gonzo.it_value.tv_sec = 0;
1543 gonzo.it_value.tv_usec = microsec;
1544 if (microsec)
1545 sys_signal(SIGALRM, sys_alarmhandler);
1546 else sys_signal(SIGALRM, SIG_IGN);
1547 setitimer(ITIMER_REAL, &gonzo, 0);
1548}
1549
1550#endif
1551
1552#ifdef __linux__
1553
1554#if defined(_POSIX_PRIORITY_SCHEDULING) || defined(_POSIX_MEMLOCK)
1555#include <sched.h>
1556#endif
1557
1558void sys_set_priority(int higher)
1559{
1560#ifdef _POSIX_PRIORITY_SCHEDULING
1561 struct sched_param par;
1562 int p1 ,p2, p3;
1563 p1 = sched_get_priority_min(SCHED_FIFO);
1564 p2 = sched_get_priority_max(SCHED_FIFO);
1565#ifdef USEAPI_JACK
1566 p3 = (higher ? p1 + 7 : p1 + 5);
1567#else
1568 p3 = (higher ? p2 - 1 : p2 - 3);
1569#endif
1570 par.sched_priority = p3;
1571 if (sched_setscheduler(0,SCHED_FIFO,&par) != -1)
1572 fprintf(stderr, "priority %d scheduling enabled.\n", p3);
1573#endif
1574
1575#ifdef _POSIX_MEMLOCK
1576 if (mlockall(MCL_FUTURE) != -1)
1577 fprintf(stderr, "memory locking enabled.\n");
1578#endif
1579
1580}
1581
1582#endif /* __linux__ */
1583
1584static int sys_watchfd;
1585
1586#ifdef __linux__
1587void glob_ping(t_pd *dummy)
1588{
1589 if (write(sys_watchfd, "\n", 1) < 1)
1590 {
1591 fprintf(stderr, "pd: watchdog process died\n");
1592 sys_bail(1);
1593 }
1594}
1595#endif
1596
1597static int defaultfontshit[] = {
1598 8, 5, 9, 10, 6, 10, 12, 7, 13, 14, 9, 17, 16, 10, 19, 24, 15, 28,
1599 24, 15, 28};
1600
1601int sys_startgui(const char *guidir)
1602{
1603 pid_t childpid;
1604 char cmdbuf[4*MAXPDSTRING];
1605 struct sockaddr_in server;
1606 int msgsock;
1607 char buf[15];
1608 int len = sizeof(server);
1609 int ntry = 0, portno = FIRSTPORTNUM;
1610 int xsock = -1;
1611#ifdef MSW
1612 short version = MAKEWORD(2, 0);
1613 WSADATA nobby;
1614#endif
1615#ifdef UNIX
1616 int stdinpipe[2];
1617#endif
1618 /* create an empty FD poll list */
1619 sys_fdpoll = (t_fdpoll *)t_getbytes(0);
1620 sys_nfdpoll = 0;
1621 inbinbuf = binbuf_new();
1622
1623#ifdef UNIX
1624 signal(SIGHUP, sys_huphandler);
1625 signal(SIGINT, sys_exithandler);
1626 signal(SIGQUIT, sys_exithandler);
1627 signal(SIGILL, sys_exithandler);
1628 signal(SIGIOT, sys_exithandler);
1629 signal(SIGFPE, SIG_IGN);
1630 /* signal(SIGILL, sys_exithandler);
1631 signal(SIGBUS, sys_exithandler);
1632 signal(SIGSEGV, sys_exithandler); */
1633 signal(SIGPIPE, SIG_IGN);
1634 signal(SIGALRM, SIG_IGN);
1635 signal(SIGTERM, SIG_IGN);
1636#if 0 /* GG says: don't use that */
1637 signal(SIGSTKFLT, sys_exithandler);
1638#endif
1639#endif
1640#ifdef MSW
1641 if (WSAStartup(version, &nobby)) sys_sockerror("WSAstartup");
1642#endif
1643
1644 if (sys_nogui)
1645 {
1646 /* fake the GUI's message giving cwd and font sizes; then
1647 skip starting the GUI up. */
1648 t_atom zz[19];
1649 int i;
1650#ifdef MSW
1651 if (GetCurrentDirectory(MAXPDSTRING, cmdbuf) == 0)
1652 strcpy(cmdbuf, ".");
1653#endif
1654#ifdef UNIX
1655 if (!getcwd(cmdbuf, MAXPDSTRING))
1656 strcpy(cmdbuf, ".");
1657
1658#endif
1659 SETSYMBOL(zz, gensym(cmdbuf));
1660 for (i = 1; i < 22; i++)
1661 SETFLOAT(zz + i, defaultfontshit[i-1]);
1662 SETFLOAT(zz+22,0);
1663 glob_initfromgui(0, 0, 23, zz);
1664 }
1665 else
1666 {
1667#ifdef MSW
1668 char scriptbuf[MAXPDSTRING+30], wishbuf[MAXPDSTRING+30], portbuf[80];
1669 int spawnret;
1670
1671#endif
1672#ifdef MSW
1673 char intarg;
1674#else
1675 int intarg;
1676#endif
1677
1678 /* create a socket */
1679 xsock = socket(AF_INET, SOCK_STREAM, 0);
1680 if (xsock < 0) sys_sockerror("socket");
1681#if 0
1682 intarg = 0;
1683 if (setsockopt(xsock, SOL_SOCKET, SO_SNDBUF,
1684 &intarg, sizeof(intarg)) < 0)
1685 post("setsockopt (SO_RCVBUF) failed\n");
1686 intarg = 0;
1687 if (setsockopt(xsock, SOL_SOCKET, SO_RCVBUF,
1688 &intarg, sizeof(intarg)) < 0)
1689 post("setsockopt (SO_RCVBUF) failed\n");
1690#endif
1691 intarg = 1;
1692 if (setsockopt(xsock, IPPROTO_TCP, TCP_NODELAY,
1693 &intarg, sizeof(intarg)) < 0)
1694#ifndef MSW
1695 post("setsockopt (TCP_NODELAY) failed\n")
1696#endif
1697 ;
1698
1699
1700 server.sin_family = AF_INET;
1701 server.sin_addr.s_addr = INADDR_ANY;
1702
1703 /* assign server port number */
1704 server.sin_port = htons((unsigned short)portno);
1705
1706 /* name the socket */
1707 while (bind(xsock, (struct sockaddr *)&server, sizeof(server)) < 0)
1708 {
1709#ifdef MSW
1710 int err = WSAGetLastError();
1711#endif
1712#ifdef UNIX
1713 int err = errno;
1714#endif
1715 if ((ntry++ > 20) || (err != EADDRINUSE))
1716 {
1717 perror("bind");
1718 fprintf(stderr,
1719 "Pd needs your machine to be configured with\n");
1720 fprintf(stderr,
1721 "'networking' turned on (see Pd's html doc for details.)\n");
1722 exit(1);
1723 }
1724 portno++;
1725 server.sin_port = htons((unsigned short)(portno));
1726 }
1727
1728 if (sys_verbose) fprintf(stderr, "port %d\n", portno);
1729
1730 sys_socketreceiver = socketreceiver_new(0, 0, 0, 0);
1731
1732#ifdef UNIX
1733 childpid = fork();
1734 if (childpid < 0)
1735 {
1736 if (errno) perror("sys_startgui");
1737 else fprintf(stderr, "sys_startgui failed\n");
1738 return (1);
1739 }
1740 else if (!childpid) /* we're the child */
1741 {
1742 seteuid(getuid()); /* lose setuid priveliges */
1743#ifndef MACOSX
1744 /* the wish process in Unix will make a wish shell and
1745 read/write standard in and out unless we close the
1746 file descriptors. Somehow this doesn't make the MAC OSX
1747 version of Wish happy...*/
1748 if (pipe(stdinpipe) < 0)
1749 sys_sockerror("pipe");
1750 else
1751 {
1752 if (stdinpipe[0] != 0)
1753 {
1754 close (0);
1755 dup2(stdinpipe[0], 0);
1756 close(stdinpipe[0]);
1757 }
1758 }
1759#endif
1760 if (!sys_guicmd)
1761 {
1762#ifdef MACOSX
1763 char *homedir = getenv("HOME"), filename[250];
1764 struct stat statbuf;
1765 if (!homedir || strlen(homedir) > 150)
1766 goto nohomedir;
1767 sprintf(filename,
1768 "%s/Applications/Utilities/Wish shell.app/Contents/MacOS/Wish Shell",
1769 homedir);
1770 if (stat(filename, &statbuf) >= 0)
1771 goto foundit;
1772 sprintf(filename,
1773 "%s/Applications/Wish shell.app/Contents/MacOS/Wish Shell",
1774 homedir);
1775 if (stat(filename, &statbuf) >= 0)
1776 goto foundit;
1777 nohomedir:
1778 strcpy(filename,
1779 "/Applications/Utilities/Wish Shell.app/Contents/MacOS/Wish Shell");
1780 if (stat(filename, &statbuf) >= 0)
1781 goto foundit;
1782 strcpy(filename,
1783 "/Applications/Wish Shell.app/Contents/MacOS/Wish Shell");
1784 foundit:
1785 sprintf(cmdbuf, "\"%s\" %s/pd.tk %d\n", filename, guidir, portno);
1786#else
1787 sprintf(cmdbuf,
1788"TCL_LIBRARY=\"%s/tcl/library\" TK_LIBRARY=\"%s/tk/library\" \
1789 \"%s/pd-gui\" %d\n",
1790 sys_libdir->s_name, sys_libdir->s_name, guidir, portno);
1791#endif
1792 sys_guicmd = cmdbuf;
1793 }
1794 if (sys_verbose) fprintf(stderr, "%s", sys_guicmd);
1795 execl("/bin/sh", "sh", "-c", sys_guicmd, 0);
1796 perror("pd: exec");
1797 _exit(1);
1798 }
1799#endif /* UNIX */
1800
1801#ifdef MSW
1802 /* in MSW land "guipath" is unused; we just do everything from
1803 the libdir. */
1804 /* fprintf(stderr, "%s\n", sys_libdir->s_name); */
1805
1806 strcpy(scriptbuf, "\"");
1807 strcat(scriptbuf, sys_libdir->s_name);
1808 strcat(scriptbuf, "/" PDBINDIR "pd.tk\"");
1809 sys_bashfilename(scriptbuf, scriptbuf);
1810
1811 sprintf(portbuf, "%d", portno);
1812
1813 strcpy(wishbuf, sys_libdir->s_name);
1814 strcat(wishbuf, "/" PDBINDIR WISHAPP);
1815 sys_bashfilename(wishbuf, wishbuf);
1816
1817 spawnret = _spawnl(P_NOWAIT, wishbuf, WISHAPP, scriptbuf, portbuf, 0);
1818 if (spawnret < 0)
1819 {
1820 perror("spawnl");
1821 fprintf(stderr, "%s: couldn't load TCL\n", wishbuf);
1822 exit(1);
1823 }
1824
1825#endif /* MSW */
1826 }
1827
1828#ifdef __linux__
1829 /* now that we've spun off the child process we can promote
1830 our process's priority, if we happen to be root. */
1831 if (sys_hipriority)
1832 {
1833 if (!getuid() || !geteuid())
1834 {
1835 /* To prevent lockup, we fork off a watchdog process with
1836 higher real-time priority than ours. The GUI has to send
1837 a stream of ping messages to the watchdog THROUGH the Pd
1838 process which has to pick them up from the GUI and forward
1839 them. If any of these things aren't happening the watchdog
1840 starts sending "stop" and "cont" signals to the Pd process
1841 to make it timeshare with the rest of the system. (Version
1842 0.33P2 : if there's no GUI, the watchdog pinging is done
1843 from the scheduler idle routine in this process instead.) */
1844
1845 int pipe9[2], watchpid;
1846 if (pipe(pipe9) < 0)
1847 {
1848 seteuid(getuid()); /* lose setuid priveliges */
1849 sys_sockerror("pipe");
1850 return (1);
1851 }
1852 watchpid = fork();
1853 if (watchpid < 0)
1854 {
1855 seteuid(getuid()); /* lose setuid priveliges */
1856 if (errno)
1857 perror("sys_startgui");
1858 else fprintf(stderr, "sys_startgui failed\n");
1859 return (1);
1860 }
1861 else if (!watchpid) /* we're the child */
1862 {
1863 sys_set_priority(1);
1864 seteuid(getuid()); /* lose setuid priveliges */
1865 if (pipe9[1] != 0)
1866 {
1867 dup2(pipe9[0], 0);
1868 close(pipe9[0]);
1869 }
1870 close(pipe9[1]);
1871
1872 sprintf(cmdbuf, "%s/pd-watchdog\n", guidir);
1873 if (sys_verbose) fprintf(stderr, "%s", cmdbuf);
1874 execl("/bin/sh", "sh", "-c", cmdbuf, 0);
1875 perror("pd: exec");
1876 _exit(1);
1877 }
1878 else /* we're the parent */
1879 {
1880 sys_set_priority(0);
1881 seteuid(getuid()); /* lose setuid priveliges */
1882 close(pipe9[0]);
1883 sys_watchfd = pipe9[1];
1884 /* We also have to start the ping loop in the GUI;
1885 this is done later when the socket is open. */
1886 }
1887 }
1888 else
1889 {
1890 post("realtime setting failed because not root\n");
1891 sys_hipriority = 0;
1892 }
1893 }
1894
1895 seteuid(getuid()); /* lose setuid priveliges */
1896#endif /* __linux__ */
1897
1898#ifdef MSW
1899 if (!SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS))
1900 fprintf(stderr, "pd: couldn't set high priority class\n");
1901#endif
1902#ifdef MACOSX
1903 if (sys_hipriority)
1904 {
1905 struct sched_param param;
1906 int policy = SCHED_RR;
1907 int err;
1908 param.sched_priority = 80; // adjust 0 : 100
1909
1910 err = pthread_setschedparam(pthread_self(), policy, &param);
1911 if (err)
1912 post("warning: high priority scheduling failed\n");
1913 }
1914#endif /* MACOSX */
1915
1916 if (!sys_nogui)
1917 {
1918 char buf[256];
1919 if (sys_verbose)
1920 fprintf(stderr, "Waiting for connection request... \n");
1921 if (listen(xsock, 5) < 0) sys_sockerror("listen");
1922
1923 sys_guisock = accept(xsock, (struct sockaddr *) &server, &len);
1924#ifdef OOPS
1925 close(xsock);
1926#endif
1927 if (sys_guisock < 0) sys_sockerror("accept");
1928 sys_addpollfn(sys_guisock, (t_fdpollfn)socketreceiver_read,
1929 sys_socketreceiver);
1930
1931 if (sys_verbose)
1932 fprintf(stderr, "... connected\n");
1933
1934 /* here is where we start the pinging. */
1935#ifdef __linux__
1936 if (sys_hipriority)
1937 sys_gui("pdtk_watchdog\n");
1938#endif
1939 sys_get_audio_apis(buf);
1940 sys_vgui("pdtk_pd_startup {%s} %s\n", pd_version, buf);
1941 }
1942 if (sys_stdin) {
1943 set_keypress();
1944 _ss = gensym("stdin");
1945 sys_addpollfn(1, (t_fdpollfn) stdin_read,NULL);
1946 }
1947 return (0);
1948
1949}
1950
1951
1952static int sys_poll_togui(void)
1953{
1954 /* LATER use this to flush output buffer to gui */
1955 return (0);
1956}
1957
1958int sys_pollgui(void)
1959{
1960 return (sys_domicrosleep(0, 1) || sys_poll_togui());
1961}
1962
1963
1964/* T.Grill - import clean quit function */
1965extern void sys_exit(void);
1966
1967/* This is called when something bad has happened, like a segfault.
1968Call glob_quit() below to exit cleanly.
1969LATER try to save dirty documents even in the bad case. */
1970void sys_bail(int n)
1971{
1972 static int reentered = 0;
1973 reset_keypress();
1974 if (!reentered)
1975 {
1976 reentered = 1;
1977#ifndef __linux /* sys_close_audio() hangs if you're in a signal? */
1978 fprintf(stderr, "closing audio...\n");
1979 sys_close_audio();
1980 fprintf(stderr, "closing MIDI...\n");
1981 sys_close_midi();
1982 fprintf(stderr, "... done.\n");
1983#endif
1984 exit(1);
1985 }
1986 else _exit(n);
1987}
1988
1989void glob_quit(void *dummy)
1990{
1991 sys_vgui("exit\n");
1992 if (!sys_nogui)
1993 {
1994 close(sys_guisock);
1995 sys_rmpollfn(sys_guisock);
1996 }
1997 reset_keypress();
1998 sys_bail(0);
1999}
2000