diff options
Diffstat (limited to 'apps/plugins/pdbox/PDa/extra/dumpOSC.c')
-rw-r--r-- | apps/plugins/pdbox/PDa/extra/dumpOSC.c | 1000 |
1 files changed, 1 insertions, 999 deletions
diff --git a/apps/plugins/pdbox/PDa/extra/dumpOSC.c b/apps/plugins/pdbox/PDa/extra/dumpOSC.c index 37767c2b03..28b0d8223e 100644 --- a/apps/plugins/pdbox/PDa/extra/dumpOSC.c +++ b/apps/plugins/pdbox/PDa/extra/dumpOSC.c | |||
@@ -997,1002 +997,4 @@ void complain(char *s, ...) { | |||
997 | } | 997 | } |
998 | 998 | ||
999 | #endif /* __sgi or LINUX or WIN32 */ | 999 | #endif /* __sgi or LINUX or WIN32 */ |
1000 | /* | 1000 | |
1001 | Written by Matt Wright and Adrian Freed, The Center for New Music and | ||
1002 | Audio Technologies, University of California, Berkeley. Copyright (c) | ||
1003 | 1992,93,94,95,96,97,98,99,2000,01,02,03,04 The Regents of the University of | ||
1004 | California (Regents). | ||
1005 | |||
1006 | Permission to use, copy, modify, distribute, and distribute modified versions | ||
1007 | of this software and its documentation without fee and without a signed | ||
1008 | licensing agreement, is hereby granted, provided that the above copyright | ||
1009 | notice, this paragraph and the following two paragraphs appear in all copies, | ||
1010 | modifications, and distributions. | ||
1011 | |||
1012 | IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, | ||
1013 | SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING | ||
1014 | OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS | ||
1015 | BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
1016 | |||
1017 | REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, | ||
1018 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | ||
1019 | PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED | ||
1020 | HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE | ||
1021 | MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. | ||
1022 | |||
1023 | |||
1024 | The OSC webpage is http://cnmat.cnmat.berkeley.edu/OpenSoundControl | ||
1025 | */ | ||
1026 | |||
1027 | |||
1028 | /* | ||
1029 | |||
1030 | dumpOSC.c | ||
1031 | server that displays OpenSoundControl messages sent to it | ||
1032 | for debugging client udp and UNIX protocol | ||
1033 | |||
1034 | by Matt Wright, 6/3/97 | ||
1035 | modified from dumpSC.c, by Matt Wright and Adrian Freed | ||
1036 | |||
1037 | version 0.2: Added "-silent" option a.k.a. "-quiet" | ||
1038 | |||
1039 | version 0.3: Incorporated patches from Nicola Bernardini to make | ||
1040 | things Linux-friendly. Also added ntohl() in the right places | ||
1041 | to support little-endian architectures. | ||
1042 | |||
1043 | |||
1044 | |||
1045 | compile: | ||
1046 | cc -o dumpOSC dumpOSC.c | ||
1047 | |||
1048 | to-do: | ||
1049 | |||
1050 | More robustness in saying exactly what's wrong with ill-formed | ||
1051 | messages. (If they don't make sense, show exactly what was | ||
1052 | received.) | ||
1053 | |||
1054 | Time-based features: print time-received for each packet | ||
1055 | |||
1056 | Clean up to separate OSC parsing code from socket/select stuff | ||
1057 | |||
1058 | pd: branched from http://www.cnmat.berkeley.edu/OpenSoundControl/src/dumpOSC/dumpOSC.c | ||
1059 | ------------- | ||
1060 | -- added pd functions | ||
1061 | -- socket is made differently than original via pd mechanisms | ||
1062 | -- tweaks for Win32 www.zeggz.com/raf 13-April-2002 | ||
1063 | -- the OSX changes from cnmat didnt make it here yet but this compiles | ||
1064 | on OSX anyway. | ||
1065 | |||
1066 | */ | ||
1067 | |||
1068 | #if HAVE_CONFIG_H | ||
1069 | #include <config.h> | ||
1070 | #endif | ||
1071 | |||
1072 | #include "m_pd.h" | ||
1073 | //#include "m_imp.h" | ||
1074 | #include "s_stuff.h" | ||
1075 | |||
1076 | /* declarations */ | ||
1077 | |||
1078 | // typedef void (*t_fdpollfn)(void *ptr, int fd); | ||
1079 | void sys_addpollfn(int fd, t_fdpollfn fn, void *ptr); | ||
1080 | |||
1081 | |||
1082 | #if defined(__sgi) || defined(__linux) || defined(WIN32) || defined(__APPLE__) | ||
1083 | |||
1084 | #ifdef WIN32 | ||
1085 | #include "OSC-common.h" | ||
1086 | #include <winsock2.h> | ||
1087 | #include <string.h> | ||
1088 | #include <stdlib.h> | ||
1089 | #include <fcntl.h> | ||
1090 | #include <sys/types.h> | ||
1091 | #include <sys/stat.h> | ||
1092 | #include <ctype.h> | ||
1093 | #include <signal.h> | ||
1094 | #else | ||
1095 | #include <stdio.h> | ||
1096 | #include <string.h> | ||
1097 | #include <stdlib.h> | ||
1098 | #include <unistd.h> | ||
1099 | #include <fcntl.h> | ||
1100 | #include <sys/types.h> | ||
1101 | #include <sys/stat.h> | ||
1102 | #include <netinet/in.h> | ||
1103 | #include <rpc/rpc.h> | ||
1104 | #include <sys/socket.h> | ||
1105 | #include <sys/un.h> | ||
1106 | #include <sys/times.h> | ||
1107 | #include <sys/param.h> | ||
1108 | #include <sys/time.h> | ||
1109 | #include <sys/ioctl.h> | ||
1110 | #include <ctype.h> | ||
1111 | #include <arpa/inet.h> | ||
1112 | #include <netdb.h> | ||
1113 | #include <pwd.h> | ||
1114 | #include <signal.h> | ||
1115 | #include <grp.h> | ||
1116 | #include <sys/file.h> | ||
1117 | //#include <sys/prctl.h> | ||
1118 | |||
1119 | #ifdef NEED_SCHEDCTL_AND_LOCK | ||
1120 | #include <sys/schedctl.h> | ||
1121 | #include <sys/lock.h> | ||
1122 | #endif | ||
1123 | #endif | ||
1124 | |||
1125 | |||
1126 | char *htm_error_string; | ||
1127 | typedef int Boolean; | ||
1128 | typedef void *OBJ; | ||
1129 | |||
1130 | typedef struct ClientAddressStruct { | ||
1131 | struct sockaddr_in cl_addr; | ||
1132 | int clilen; | ||
1133 | int sockfd; | ||
1134 | } *ClientAddr; | ||
1135 | |||
1136 | typedef unsigned long long osc_time_t; | ||
1137 | |||
1138 | Boolean ShowBytes = FALSE; | ||
1139 | Boolean Silent = FALSE; | ||
1140 | |||
1141 | /* Declarations */ | ||
1142 | #ifndef WIN32 | ||
1143 | static int unixinitudp(int chan); | ||
1144 | #endif | ||
1145 | |||
1146 | static int initudp(int chan); | ||
1147 | static void closeudp(int sockfd); | ||
1148 | Boolean ClientReply(int packetsize, void *packet, int socketfd, | ||
1149 | void *clientaddresspointer, int clientaddressbufferlength); | ||
1150 | void sgi_CleanExit(void); | ||
1151 | Boolean sgi_HaveToQuit(void); | ||
1152 | int RegisterPollingDevice(int fd, void (*callbackfunction)(int , void *), void *dummy); | ||
1153 | static void catch_sigint(); | ||
1154 | static int Synthmessage(char *m, int n, void *clientdesc, int clientdesclength, int fd) ; | ||
1155 | char *DataAfterAlignedString(char *string, char *boundary) ; | ||
1156 | Boolean IsNiceString(char *string, char *boundary) ; | ||
1157 | void complain(char *s, ...); | ||
1158 | |||
1159 | #define MAXMESG 32768 | ||
1160 | static char mbuf[MAXMESG]; | ||
1161 | |||
1162 | /* ----------------------------- dumpOSC ------------------------- */ | ||
1163 | |||
1164 | #define MAXOUTAT 50 | ||
1165 | |||
1166 | static t_class *dumpOSC_class; | ||
1167 | |||
1168 | typedef struct _dumpOSC | ||
1169 | { | ||
1170 | t_object x_obj; | ||
1171 | t_outlet *x_msgout; | ||
1172 | t_outlet *x_connectout; | ||
1173 | t_atom x_outat[MAXOUTAT]; | ||
1174 | int x_outatc; | ||
1175 | t_binbuf *x_b; | ||
1176 | int x_connectsocket; | ||
1177 | int x_nconnections; | ||
1178 | int x_udp; | ||
1179 | struct sockaddr_in x_server; | ||
1180 | int x_clilen; | ||
1181 | } t_dumpOSC; | ||
1182 | |||
1183 | void dumpOSC_ParsePacket(t_dumpOSC *x, char *buf, int n, ClientAddr returnAddr); | ||
1184 | Boolean dumpOSC_SendReply(char *buf, int n, void *clientDesc, int clientDescLenght, int fd); | ||
1185 | static void dumpOSC_Smessage(t_dumpOSC *x, char *address, void *v, int n, ClientAddr returnAddr); | ||
1186 | static void dumpOSC_PrintTypeTaggedArgs(t_dumpOSC *x, void *v, int n); | ||
1187 | static void dumpOSC_PrintHeuristicallyTypeGuessedArgs(t_dumpOSC *x, void *v, int n, int skipComma); | ||
1188 | |||
1189 | static void dumpOSC_read(t_dumpOSC *x, int sockfd) { | ||
1190 | int clilen = x->x_clilen; | ||
1191 | int n; | ||
1192 | struct ClientAddressStruct ras; | ||
1193 | ClientAddr ra = &ras; | ||
1194 | |||
1195 | //catchupflag= FALSE; | ||
1196 | |||
1197 | /* if (ShowBytes) { */ | ||
1198 | /* int i; */ | ||
1199 | /* printf("%d byte message:\n", n); */ | ||
1200 | /* for (i = 0; i < n; ++i) { */ | ||
1201 | /* printf(" %x (%c)\t", m[i], m[i]); */ | ||
1202 | /* if (i%4 == 3) printf("\n"); */ | ||
1203 | /* } */ | ||
1204 | /* printf("\n"); */ | ||
1205 | /* } */ | ||
1206 | |||
1207 | // return catchupflag; | ||
1208 | //struct sockaddr_in x->x_server; | ||
1209 | //while( (n = recvfrom(sockfd, mbuf, MAXMESG, 0, &cl_addr, &clilen)) >0) | ||
1210 | // while(( | ||
1211 | |||
1212 | #ifdef WIN32 | ||
1213 | if ((n = recvfrom(sockfd, mbuf, MAXMESG, 0, (SOCKADDR*)&x->x_server, &clilen)) >0) | ||
1214 | #else | ||
1215 | if ((n = recvfrom(sockfd, mbuf, MAXMESG, 0, (struct sockaddr *)&x->x_server, &clilen)) >0) | ||
1216 | #endif | ||
1217 | { | ||
1218 | //int r; | ||
1219 | ras.cl_addr = *((struct sockaddr_in *) &x->x_server); | ||
1220 | ras.clilen = x->x_clilen; | ||
1221 | ras.sockfd = x->x_connectsocket; | ||
1222 | |||
1223 | #ifdef DEBUG | ||
1224 | printf("dumpOSC_read: received UDP packet of length %d\n", n); | ||
1225 | #endif | ||
1226 | |||
1227 | if(!dumpOSC_SendReply(mbuf, n, &x->x_server, clilen, sockfd)) | ||
1228 | { | ||
1229 | dumpOSC_ParsePacket(x, mbuf, n, ra); | ||
1230 | } | ||
1231 | //r = Synthmessage(mbuf, n, &x->x_server, clilen, sockfd); | ||
1232 | //post ("%d", r); | ||
1233 | //outlet_anything(x->x_msgout, at[msg].a_w.w_symbol, | ||
1234 | // emsg-msg-1, at + msg + 1); | ||
1235 | // outlet_list(x->x_msgout, 0, n, mbuf); | ||
1236 | //if( sgi_HaveToQuit()) goto out; | ||
1237 | //if(r>0) goto back; | ||
1238 | //clilen = maxclilen; | ||
1239 | } | ||
1240 | } | ||
1241 | |||
1242 | static void *dumpOSC_new(t_symbol *compatflag, | ||
1243 | t_floatarg fportno) { | ||
1244 | t_dumpOSC *x; | ||
1245 | struct sockaddr_in server; | ||
1246 | int clilen=sizeof(server); | ||
1247 | int sockfd; | ||
1248 | int portno=fportno; | ||
1249 | int udp = 1; | ||
1250 | |||
1251 | //x->x_b = binbuf_new(); | ||
1252 | //x->x_outat = binbuf_getvec(x->x_b); | ||
1253 | |||
1254 | //{{raf}} pointer not valid yet...moving this down | ||
1255 | //x->x_outatc = 0; {{raf}} | ||
1256 | |||
1257 | /* create a socket */ | ||
1258 | if ((sockfd = socket(AF_INET, (udp ? SOCK_DGRAM : SOCK_STREAM), 0)) == -1) | ||
1259 | { | ||
1260 | sys_sockerror("socket"); | ||
1261 | return (0); | ||
1262 | } | ||
1263 | |||
1264 | server.sin_family = AF_INET; | ||
1265 | server.sin_addr.s_addr = INADDR_ANY; | ||
1266 | /* assign server port number */ | ||
1267 | server.sin_port = htons((u_short)portno); | ||
1268 | /* name the socket */ | ||
1269 | if (bind(sockfd, (struct sockaddr *)&server, sizeof(server)) < 0) | ||
1270 | { | ||
1271 | sys_sockerror("bind"); | ||
1272 | sys_closesocket(sockfd); | ||
1273 | return (0); | ||
1274 | } | ||
1275 | |||
1276 | x = (t_dumpOSC *)pd_new(dumpOSC_class); | ||
1277 | x->x_outatc = 0; // {{raf}} now pointer is valid (less invalid) | ||
1278 | |||
1279 | x->x_msgout = outlet_new(&x->x_obj, &s_anything); | ||
1280 | |||
1281 | // if (udp) /* datagram protocol */ | ||
1282 | { | ||
1283 | |||
1284 | sys_addpollfn(sockfd, (t_fdpollfn)dumpOSC_read, x); | ||
1285 | x->x_connectout = 0; | ||
1286 | } | ||
1287 | // else /* streaming protocol */ | ||
1288 | /* { */ | ||
1289 | /* if (listen(sockfd, 5) < 0) */ | ||
1290 | /* { */ | ||
1291 | /* sys_sockerror("listen"); */ | ||
1292 | /* sys_closesocket(sockfd); */ | ||
1293 | /* sockfd = -1; */ | ||
1294 | /* } */ | ||
1295 | /* else */ | ||
1296 | /* { */ | ||
1297 | /* sys_addpollfn(sockfd, (t_fdpollfn)dumpOSC_connectpoll, x); */ | ||
1298 | /* x->x_connectout = outlet_new(&x->x_obj, &s_float); */ | ||
1299 | /* } */ | ||
1300 | /* } */ | ||
1301 | |||
1302 | x->x_connectsocket = sockfd; | ||
1303 | x->x_server = server; | ||
1304 | x->x_clilen = clilen; | ||
1305 | x->x_nconnections = 0; | ||
1306 | x->x_udp = udp; | ||
1307 | |||
1308 | return (x); | ||
1309 | } | ||
1310 | |||
1311 | static void dumpOSC_free(t_dumpOSC *x) | ||
1312 | { | ||
1313 | /* LATER make me clean up open connections */ | ||
1314 | if (x->x_connectsocket >= 0) | ||
1315 | { | ||
1316 | sys_rmpollfn(x->x_connectsocket); | ||
1317 | sys_closesocket(x->x_connectsocket); | ||
1318 | } | ||
1319 | } | ||
1320 | |||
1321 | #ifdef WIN32 | ||
1322 | OSC_API void dumpOSC_setup(void) | ||
1323 | #else | ||
1324 | void dumpOSC_setup(void) | ||
1325 | #endif | ||
1326 | { | ||
1327 | dumpOSC_class = class_new(gensym("dumpOSC"), | ||
1328 | (t_newmethod)dumpOSC_new, (t_method)dumpOSC_free, | ||
1329 | sizeof(t_dumpOSC), CLASS_NOINLET, A_DEFFLOAT, A_DEFFLOAT, | ||
1330 | A_DEFSYM, 0); | ||
1331 | class_sethelpsymbol(dumpOSC_class, gensym("dumpOSC-help.pd")); | ||
1332 | } | ||
1333 | |||
1334 | |||
1335 | #ifndef WIN32 | ||
1336 | #define UNIXDG_PATH "/tmp/htm" | ||
1337 | #define UNIXDG_TMP "/tmp/htm.XXXXXX" | ||
1338 | static int unixinitudp(int chan) | ||
1339 | { | ||
1340 | struct sockaddr_un serv_addr; | ||
1341 | int sockfd; | ||
1342 | |||
1343 | if((sockfd = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0) | ||
1344 | return sockfd; | ||
1345 | |||
1346 | bzero((char *)&serv_addr, sizeof(serv_addr)); | ||
1347 | serv_addr.sun_family = AF_UNIX; | ||
1348 | strcpy(serv_addr.sun_path, UNIXDG_PATH); | ||
1349 | sprintf(serv_addr.sun_path+strlen(serv_addr.sun_path), "%d", chan); | ||
1350 | unlink(serv_addr.sun_path); | ||
1351 | if(bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr.sun_family)+strlen(serv_addr.sun_path)) < 0) | ||
1352 | { | ||
1353 | perror("unable to bind\n"); | ||
1354 | return -1; | ||
1355 | } | ||
1356 | |||
1357 | fcntl(sockfd, F_SETFL, FNDELAY); | ||
1358 | return sockfd; | ||
1359 | } | ||
1360 | #endif // #ifndef WIN32 | ||
1361 | |||
1362 | |||
1363 | |||
1364 | static int initudp(int chan) | ||
1365 | { | ||
1366 | |||
1367 | #ifdef WIN32 | ||
1368 | struct sockaddr_in serv_addr; | ||
1369 | unsigned int sockfd; | ||
1370 | ULONG nonBlocking = (ULONG) TRUE; | ||
1371 | |||
1372 | if( (sockfd = socket(AF_INET, SOCK_DGRAM, 0)) != INVALID_SOCKET ) { | ||
1373 | ZeroMemory((char *)&serv_addr, sizeof(serv_addr)); | ||
1374 | serv_addr.sin_family = AF_INET; | ||
1375 | serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); | ||
1376 | serv_addr.sin_port = htons(chan); | ||
1377 | if(bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) >= 0) { | ||
1378 | // set for non-blocking mode | ||
1379 | if(ioctlsocket(sockfd, FIONBIO, &nonBlocking) == SOCKET_ERROR) { | ||
1380 | perror("unable to set non-blocking\n"); | ||
1381 | return -1; | ||
1382 | } | ||
1383 | } | ||
1384 | else { perror("unable to bind\n"); return -1; } | ||
1385 | } | ||
1386 | return (sockfd == INVALID_SOCKET ? -1 : (int)sockfd); | ||
1387 | #else | ||
1388 | struct sockaddr_in serv_addr; | ||
1389 | int sockfd; | ||
1390 | |||
1391 | if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) | ||
1392 | return sockfd; | ||
1393 | |||
1394 | bzero((char *)&serv_addr, sizeof(serv_addr)); | ||
1395 | serv_addr.sin_family = AF_INET; | ||
1396 | serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); | ||
1397 | serv_addr.sin_port = htons(chan); | ||
1398 | |||
1399 | if(bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) | ||
1400 | { | ||
1401 | perror("unable to bind\n"); | ||
1402 | return -1; | ||
1403 | } | ||
1404 | |||
1405 | fcntl(sockfd, F_SETFL, FNDELAY); | ||
1406 | return sockfd; | ||
1407 | #endif | ||
1408 | } | ||
1409 | |||
1410 | |||
1411 | |||
1412 | |||
1413 | |||
1414 | |||
1415 | |||
1416 | |||
1417 | static void closeudp(int sockfd) { | ||
1418 | #ifdef WIN32 | ||
1419 | closesocket(sockfd); | ||
1420 | #else | ||
1421 | close(sockfd); | ||
1422 | #endif | ||
1423 | } | ||
1424 | |||
1425 | static Boolean catchupflag=FALSE; | ||
1426 | Boolean ClientReply(int packetsize, void *packet, int socketfd, | ||
1427 | void *clientaddresspointer, int clientaddressbufferlength) | ||
1428 | { | ||
1429 | if(!clientaddresspointer) return FALSE; | ||
1430 | catchupflag= TRUE; | ||
1431 | return packetsize==sendto(socketfd, packet, packetsize, 0, clientaddresspointer, clientaddressbufferlength); | ||
1432 | } | ||
1433 | |||
1434 | static Boolean exitflag= FALSE; | ||
1435 | void sgi_CleanExit(void) { | ||
1436 | exitflag = TRUE; | ||
1437 | } | ||
1438 | |||
1439 | Boolean sgi_HaveToQuit(void) { | ||
1440 | return exitflag; | ||
1441 | } | ||
1442 | |||
1443 | |||
1444 | /* file descriptor poll table */ | ||
1445 | static int npolldevs =0; | ||
1446 | typedef struct polldev | ||
1447 | { | ||
1448 | int fd; | ||
1449 | void (*callbackfunction)(int , void *); | ||
1450 | void *dummy; | ||
1451 | } polldev; | ||
1452 | #define TABMAX 8 | ||
1453 | static polldev polldevs[TABMAX]; | ||
1454 | |||
1455 | |||
1456 | /* Register a device (referred to by a file descriptor that the caller | ||
1457 | should have already successfully obtained from a system call) to be | ||
1458 | polled as real-time constraints allowed. | ||
1459 | |||
1460 | When a select(2) call indicates activity on the file descriptor, the | ||
1461 | callback function is called with the file descripter as first | ||
1462 | argument and the given dummy argument (presumably a pointer to the | ||
1463 | instance variables associated with the device). | ||
1464 | */ | ||
1465 | int RegisterPollingDevice(int fd, void (*callbackfunction)(int , void *), void *dummy) | ||
1466 | { | ||
1467 | if(npolldevs<TABMAX) | ||
1468 | { | ||
1469 | polldevs[npolldevs].fd = fd; | ||
1470 | polldevs[npolldevs].callbackfunction = callbackfunction; | ||
1471 | polldevs[npolldevs].dummy = dummy; | ||
1472 | } | ||
1473 | else return -1; | ||
1474 | return npolldevs++; | ||
1475 | } | ||
1476 | |||
1477 | static int caught_sigint; | ||
1478 | |||
1479 | static void catch_sigint() { | ||
1480 | caught_sigint = 1; | ||
1481 | } | ||
1482 | static int sockfd, usockfd; | ||
1483 | |||
1484 | |||
1485 | void PrintClientAddr(ClientAddr CA) { | ||
1486 | unsigned long addr = CA->cl_addr.sin_addr.s_addr; | ||
1487 | printf("Client address %p:\n", CA); | ||
1488 | printf(" clilen %d, sockfd %d\n", CA->clilen, CA->sockfd); | ||
1489 | printf(" sin_family %d, sin_port %d\n", CA->cl_addr.sin_family, | ||
1490 | CA->cl_addr.sin_port); | ||
1491 | printf(" address: (%x) %s\n", addr, inet_ntoa(CA->cl_addr.sin_addr)); | ||
1492 | |||
1493 | printf(" sin_zero = \"%c%c%c%c%c%c%c%c\"\n", | ||
1494 | CA->cl_addr.sin_zero[0], | ||
1495 | CA->cl_addr.sin_zero[1], | ||
1496 | CA->cl_addr.sin_zero[2], | ||
1497 | CA->cl_addr.sin_zero[3], | ||
1498 | CA->cl_addr.sin_zero[4], | ||
1499 | CA->cl_addr.sin_zero[5], | ||
1500 | CA->cl_addr.sin_zero[6], | ||
1501 | CA->cl_addr.sin_zero[7]); | ||
1502 | |||
1503 | printf("\n"); | ||
1504 | } | ||
1505 | |||
1506 | //******************* | ||
1507 | |||
1508 | void WriteTime(char* dst, osc_time_t osctime) | ||
1509 | { | ||
1510 | *(int32_t*)dst = htonl((int32_t)(osctime >> 32)); | ||
1511 | *(int32_t*)(dst+4) = htonl((int32_t)osctime); | ||
1512 | } | ||
1513 | |||
1514 | void WriteMode(char* dst) | ||
1515 | { | ||
1516 | *(int32_t*)dst = htonl(0); | ||
1517 | } | ||
1518 | |||
1519 | osc_time_t ReadTime(const char* src) | ||
1520 | { | ||
1521 | osc_time_t osctime = ntohl(*(int32_t*)src); | ||
1522 | return (osctime << 32) + ntohl(*(int32_t*)(src+4)); | ||
1523 | } | ||
1524 | |||
1525 | double TimeToSeconds(osc_time_t osctime) | ||
1526 | { | ||
1527 | return (double)osctime * 2.3283064365386962890625e-10 /* 1/2^32 */; | ||
1528 | } | ||
1529 | |||
1530 | int timeRound(double x) | ||
1531 | { | ||
1532 | return x >= 0.0 ? x+0.5 : x-0.5; | ||
1533 | } | ||
1534 | /* | ||
1535 | void WriteLogicalTime(char* dst) | ||
1536 | { | ||
1537 | static double startTime = -1.0; | ||
1538 | double sTime; | ||
1539 | |||
1540 | // Initialisierung der Startzeit. | ||
1541 | // Knnte effizienter (ohne 'if') auch irgendwo vorher passieren. | ||
1542 | // Knnte wahrscheinlich auch 0.0 sein. | ||
1543 | if (startTime < 0.0) { | ||
1544 | startTime = clock_getlogicaltime(); | ||
1545 | } | ||
1546 | |||
1547 | sTime = clock_gettimesince(startTime) * 0.001; | ||
1548 | *(int32_t*)dst = hton'K l((int32_t)sTime); | ||
1549 | *(int32_t*)(dst+4) = htonl((int32_t)(4294967296.0 * sTime)); | ||
1550 | } | ||
1551 | */ | ||
1552 | |||
1553 | void WriteLogicalTime(char* dst) | ||
1554 | { | ||
1555 | double sTime = clock_gettimesince(19230720) / 1000.0; | ||
1556 | double tau = sTime - timeRound(sTime); | ||
1557 | |||
1558 | //fprintf(stderr, "sSec = %f tau = %f\n", sTime, tau); | ||
1559 | |||
1560 | *(int32_t*)dst = htonl((int32_t)(sTime)); | ||
1561 | *(int32_t*)(dst+4) = htonl((int32_t)(4294967296 * tau)); | ||
1562 | } | ||
1563 | |||
1564 | Boolean dumpOSC_SendReply(char *buf, int n, void *clientDesc, int clientDescLenght, int fd) | ||
1565 | { | ||
1566 | if((n == 24) && (strcmp(buf, "#time") == 0)) | ||
1567 | { | ||
1568 | osc_time_t t0, t1, t2; | ||
1569 | double dt0, dt1, dt2; | ||
1570 | |||
1571 | WriteMode(buf+6); | ||
1572 | |||
1573 | t0 = ReadTime(buf+8); | ||
1574 | |||
1575 | WriteLogicalTime(buf+16); | ||
1576 | t1 = ReadTime(buf+16); // reverse | ||
1577 | dt0 = TimeToSeconds(t0); // client time | ||
1578 | dt1 = TimeToSeconds(t1); // server time | ||
1579 | |||
1580 | // fprintf(stderr, "%f\t%f\t%f\n", dt0, dt1, dt0 - dt1); | ||
1581 | |||
1582 | sendto(fd, buf, n, 0, (struct sockaddr *)clientDesc, clientDescLenght); | ||
1583 | return TRUE; | ||
1584 | } | ||
1585 | else | ||
1586 | { | ||
1587 | return FALSE; | ||
1588 | } | ||
1589 | } | ||
1590 | |||
1591 | //********************** | ||
1592 | |||
1593 | void dumpOSC_ParsePacket(t_dumpOSC *x, char *buf, int n, ClientAddr returnAddr) { | ||
1594 | // t_dumpOSC *x; | ||
1595 | int size, messageLen, i; | ||
1596 | char *messageName; | ||
1597 | char *args; | ||
1598 | |||
1599 | //#ifdef PRINTADDRS | ||
1600 | #ifdef DEBUG | ||
1601 | //PrintClientAddr(returnAddr); | ||
1602 | #endif | ||
1603 | |||
1604 | |||
1605 | if ((n%4) != 0) { | ||
1606 | complain("SynthControl packet size (%d) not a multiple of 4 bytes: dropping", n); | ||
1607 | return; | ||
1608 | } | ||
1609 | |||
1610 | if ((n >= 8) && (strncmp(buf, "#bundle", 8) == 0)) { | ||
1611 | /* This is a bundle message. */ | ||
1612 | #ifdef DEBUG | ||
1613 | printf("dumpOSC_ParsePacket: bundle msg: bundles not yet supported\n"); | ||
1614 | #endif | ||
1615 | |||
1616 | if (n < 16) { | ||
1617 | complain("Bundle message too small (%d bytes) for time tag", n); | ||
1618 | return; | ||
1619 | } | ||
1620 | |||
1621 | /* Print the time tag */ | ||
1622 | #ifdef DEBUG | ||
1623 | printf("[ %lx%08lx\n", ntohl(*((unsigned long *)(buf+8))), ntohl(*((unsigned long *)(buf+12)))); | ||
1624 | #endif | ||
1625 | |||
1626 | /* Note: if we wanted to actually use the time tag as a little-endian | ||
1627 | 64-bit int, we'd have to word-swap the two 32-bit halves of it */ | ||
1628 | |||
1629 | i = 16; /* Skip "#group\0" and time tag */ | ||
1630 | |||
1631 | while(i<n) { | ||
1632 | size = ntohl(*((int *) (buf + i))); | ||
1633 | if ((size % 4) != 0) { | ||
1634 | complain("Bad size count %d in bundle (not a multiple of 4)", size); | ||
1635 | return; | ||
1636 | } | ||
1637 | if ((size + i + 4) > n) { | ||
1638 | complain("Bad size count %d in bundle (only %d bytes left in entire bundle)", | ||
1639 | size, n-i-4); | ||
1640 | return; | ||
1641 | } | ||
1642 | |||
1643 | /* Recursively handle element of bundle */ | ||
1644 | dumpOSC_ParsePacket(x, buf+i+4, size, returnAddr); | ||
1645 | i += 4 + size; | ||
1646 | } | ||
1647 | |||
1648 | if (i != n) { | ||
1649 | complain("This can't happen"); | ||
1650 | } | ||
1651 | #ifdef DEBUG | ||
1652 | printf("]\n"); | ||
1653 | #endif | ||
1654 | |||
1655 | } | ||
1656 | else if ((n == 24) && (strcmp(buf, "#time") == 0)) | ||
1657 | { | ||
1658 | complain("Time message: %s\n :).\n", htm_error_string); | ||
1659 | return; | ||
1660 | |||
1661 | } | ||
1662 | else | ||
1663 | { | ||
1664 | /* This is not a bundle message */ | ||
1665 | |||
1666 | messageName = buf; | ||
1667 | args = DataAfterAlignedString(messageName, buf+n); | ||
1668 | if (args == 0) { | ||
1669 | complain("Bad message name string: %s\nDropping entire message.\n", | ||
1670 | htm_error_string); | ||
1671 | return; | ||
1672 | } | ||
1673 | messageLen = args-messageName; | ||
1674 | dumpOSC_Smessage(x, messageName, (void *)args, n-messageLen, returnAddr); | ||
1675 | } | ||
1676 | } | ||
1677 | |||
1678 | #define SMALLEST_POSITIVE_FLOAT 0.000001f | ||
1679 | |||
1680 | static void dumpOSC_Smessage(t_dumpOSC *x, char *address, void *v, int n, ClientAddr returnAddr) { | ||
1681 | char *chars = v; | ||
1682 | t_atom at; | ||
1683 | //t_atom myargv[50]; | ||
1684 | |||
1685 | int myargc = x->x_outatc; | ||
1686 | t_atom* mya = x->x_outat; | ||
1687 | int myi; | ||
1688 | |||
1689 | #ifdef DEBUG | ||
1690 | printf("%s ", address); | ||
1691 | #endif | ||
1692 | |||
1693 | // ztoln+cvt from envgen.c, ggee-0.18 .. | ||
1694 | // outlet_anything's 'symbol' gets set to address | ||
1695 | // so we dont need to append address to the atomlist | ||
1696 | /* | ||
1697 | SETSYMBOL(mya,gensym(address));myargc++; | ||
1698 | x->x_outatc = myargc; | ||
1699 | */ | ||
1700 | |||
1701 | if (n != 0) { | ||
1702 | if (chars[0] == ',') { | ||
1703 | if (chars[1] != ',') { | ||
1704 | /* This message begins with a type-tag string */ | ||
1705 | dumpOSC_PrintTypeTaggedArgs(x, v, n); | ||
1706 | } else { | ||
1707 | /* Double comma means an escaped real comma, not a type string */ | ||
1708 | dumpOSC_PrintHeuristicallyTypeGuessedArgs(x, v, n, 1); | ||
1709 | } | ||
1710 | } else { | ||
1711 | dumpOSC_PrintHeuristicallyTypeGuessedArgs(x, v, n, 0); | ||
1712 | } | ||
1713 | } | ||
1714 | |||
1715 | outlet_anything(x->x_msgout,gensym(address),x->x_outatc,(t_atom*)&x->x_outat); | ||
1716 | x->x_outatc = 0; | ||
1717 | #ifdef DEBUG | ||
1718 | printf("\n"); | ||
1719 | #endif | ||
1720 | fflush(stdout); /* Added for Sami 5/21/98 */ | ||
1721 | } | ||
1722 | |||
1723 | static void dumpOSC_PrintTypeTaggedArgs(t_dumpOSC *x, void *v, int n) { | ||
1724 | char *typeTags, *thisType; | ||
1725 | char *p; | ||
1726 | |||
1727 | int myargc = x->x_outatc; | ||
1728 | t_atom* mya = x->x_outat; | ||
1729 | int myi; | ||
1730 | |||
1731 | typeTags = v; | ||
1732 | |||
1733 | if (!IsNiceString(typeTags, typeTags+n)) { | ||
1734 | /* No null-termination, so maybe it wasn't a type tag | ||
1735 | string after all */ | ||
1736 | dumpOSC_PrintHeuristicallyTypeGuessedArgs(x, v, n, 0); | ||
1737 | return; | ||
1738 | } | ||
1739 | |||
1740 | p = DataAfterAlignedString(typeTags, typeTags+n); | ||
1741 | |||
1742 | |||
1743 | for (thisType = typeTags + 1; *thisType != 0; ++thisType) { | ||
1744 | switch (*thisType) { | ||
1745 | case 'i': case 'r': case 'm': case 'c': | ||
1746 | #ifdef DEBUG | ||
1747 | //post("integer: %d", ntohl(*((int *) p))); | ||
1748 | #endif | ||
1749 | /* Martin Peach fix for negative floats: | ||
1750 | * was: SETFLOAT(mya+myargc,ntohl(*((int *) p))); | ||
1751 | * now is: | ||
1752 | */ | ||
1753 | SETFLOAT(mya+myargc,(signed)ntohl(*((int *) p))); | ||
1754 | myargc++; | ||
1755 | |||
1756 | p += 4; | ||
1757 | break; | ||
1758 | |||
1759 | case 'f': { | ||
1760 | int i = ntohl(*((int *) p)); | ||
1761 | float *floatp = ((float *) (&i)); | ||
1762 | #ifdef DEBUG | ||
1763 | post("float: %f", *floatp); | ||
1764 | #endif | ||
1765 | SETFLOAT(mya+myargc,*floatp); | ||
1766 | myargc++; | ||
1767 | |||
1768 | p += 4; | ||
1769 | } | ||
1770 | break; | ||
1771 | |||
1772 | case 'h': case 't': | ||
1773 | #ifdef DEBUG | ||
1774 | printf("[A 64-bit int] "); | ||
1775 | #endif | ||
1776 | post("[A 64-bit int] not implemented"); | ||
1777 | |||
1778 | p += 8; | ||
1779 | break; | ||
1780 | |||
1781 | case 'd': | ||
1782 | #ifdef DEBUG | ||
1783 | printf("[A 64-bit float] "); | ||
1784 | #endif | ||
1785 | post("[A 64-bit float] not implemented"); | ||
1786 | |||
1787 | p += 8; | ||
1788 | break; | ||
1789 | |||
1790 | case 's': case 'S': | ||
1791 | if (!IsNiceString(p, typeTags+n)) { | ||
1792 | post("Type tag said this arg is a string but it's not!\n"); | ||
1793 | return; | ||
1794 | } else { | ||
1795 | #ifdef DEBUG | ||
1796 | post("string: \"%s\"", p); | ||
1797 | #endif | ||
1798 | SETSYMBOL(mya+myargc,gensym(p)); | ||
1799 | myargc++; | ||
1800 | //outlet_list(x->x_msgout, 0,sizeof(p), p); | ||
1801 | //outlet_anything(x->x_msgout, 0, sizeof(p), p); | ||
1802 | p = DataAfterAlignedString(p, typeTags+n); | ||
1803 | // append to output vector .. | ||
1804 | } | ||
1805 | break; | ||
1806 | |||
1807 | case 'T': | ||
1808 | #ifdef DEBUG | ||
1809 | printf("[True] "); | ||
1810 | #endif | ||
1811 | SETFLOAT(mya+myargc,1.); | ||
1812 | myargc++; | ||
1813 | break; | ||
1814 | case 'F': | ||
1815 | #ifdef DEBUG | ||
1816 | printf("[False] "); | ||
1817 | #endif | ||
1818 | SETFLOAT(mya+myargc,0.); | ||
1819 | myargc++; | ||
1820 | break; | ||
1821 | case 'N': | ||
1822 | #ifdef DEBUG | ||
1823 | printf("[Nil]"); | ||
1824 | #endif | ||
1825 | post("sendOSC: [Nil] not implemented"); | ||
1826 | break; | ||
1827 | case 'I': | ||
1828 | #ifdef DEBUG | ||
1829 | printf("[Infinitum]"); | ||
1830 | #endif | ||
1831 | post("sendOSC: [Infinitum] not implemented"); | ||
1832 | break; | ||
1833 | |||
1834 | default: | ||
1835 | post("sendOSC: [Unrecognized type tag %c]", *thisType); | ||
1836 | // return; | ||
1837 | } | ||
1838 | } | ||
1839 | x->x_outatc = myargc; | ||
1840 | } | ||
1841 | |||
1842 | static void dumpOSC_PrintHeuristicallyTypeGuessedArgs(t_dumpOSC *x, void *v, int n, int skipComma) { | ||
1843 | int i, thisi; | ||
1844 | float thisf; | ||
1845 | int *ints; | ||
1846 | char *chars; | ||
1847 | char *string, *nextString; | ||
1848 | |||
1849 | int myargc= x->x_outatc; | ||
1850 | t_atom* mya = x->x_outat; | ||
1851 | int myi; | ||
1852 | |||
1853 | |||
1854 | /* Go through the arguments 32 bits at a time */ | ||
1855 | ints = v; | ||
1856 | chars = v; | ||
1857 | |||
1858 | for (i = 0; i<n/4; ) { | ||
1859 | string = &chars[i*4]; | ||
1860 | thisi = ntohl(ints[i]); | ||
1861 | /* Reinterpret the (potentially byte-reversed) thisi as a float */ | ||
1862 | thisf = *(((float *) (&thisi))); | ||
1863 | |||
1864 | if (thisi >= -1000 && thisi <= 1000000) { | ||
1865 | #ifdef DEBUG | ||
1866 | printf("%d ", thisi); | ||
1867 | #endif | ||
1868 | // append to output vector .. | ||
1869 | SETFLOAT(mya+myargc,(t_float) (thisi)); | ||
1870 | myargc++; | ||
1871 | // outlet_float(x->x_msgout, thisi); | ||
1872 | i++; | ||
1873 | } else if (thisf >= -1000.f && thisf <= 1000000.f && | ||
1874 | (thisf <=0.0f || thisf >= SMALLEST_POSITIVE_FLOAT)) { | ||
1875 | #ifdef DEBUG | ||
1876 | printf("%f ", thisf); | ||
1877 | #endif | ||
1878 | // append to output vector .. | ||
1879 | SETFLOAT(mya+myargc,thisf); | ||
1880 | myargc++; | ||
1881 | //outlet_float(x->x_msgout, thisf); | ||
1882 | i++; | ||
1883 | } else if (IsNiceString(string, chars+n)) { | ||
1884 | nextString = DataAfterAlignedString(string, chars+n); | ||
1885 | #ifdef DEBUG | ||
1886 | printf("\"%s\" ", (i == 0 && skipComma) ? string +1 : string); | ||
1887 | #endif | ||
1888 | // append to output vector .. | ||
1889 | SETSYMBOL(mya+myargc,gensym(string)); | ||
1890 | myargc++; | ||
1891 | //outlet_symbol(x->x_msgout, gensym((i == 0 && skipComma) ? string +1 : string)); | ||
1892 | i += (nextString-string) / 4; | ||
1893 | } else { | ||
1894 | // unhandled .. ;) | ||
1895 | #ifdef DEBUG | ||
1896 | printf("0x%x xx", ints[i]); | ||
1897 | #endif | ||
1898 | i++; | ||
1899 | } | ||
1900 | x->x_outatc = myargc; | ||
1901 | } | ||
1902 | } | ||
1903 | |||
1904 | |||
1905 | #define STRING_ALIGN_PAD 4 | ||
1906 | |||
1907 | char *DataAfterAlignedString(char *string, char *boundary) | ||
1908 | { | ||
1909 | /* The argument is a block of data beginning with a string. The | ||
1910 | string has (presumably) been padded with extra null characters | ||
1911 | so that the overall length is a multiple of STRING_ALIGN_PAD | ||
1912 | bytes. Return a pointer to the next byte after the null | ||
1913 | byte(s). The boundary argument points to the character after | ||
1914 | the last valid character in the buffer---if the string hasn't | ||
1915 | ended by there, something's wrong. | ||
1916 | |||
1917 | If the data looks wrong, return 0, and set htm_error_string */ | ||
1918 | |||
1919 | int i; | ||
1920 | |||
1921 | if ((boundary - string) %4 != 0) { | ||
1922 | fprintf(stderr, "Internal error: DataAfterAlignedString: bad boundary\n"); | ||
1923 | return 0; | ||
1924 | } | ||
1925 | |||
1926 | for (i = 0; string[i] != '\0'; i++) { | ||
1927 | if (string + i >= boundary) { | ||
1928 | htm_error_string = "DataAfterAlignedString: Unreasonably long string"; | ||
1929 | return 0; | ||
1930 | } | ||
1931 | } | ||
1932 | |||
1933 | /* Now string[i] is the first null character */ | ||
1934 | i++; | ||
1935 | |||
1936 | for (; (i % STRING_ALIGN_PAD) != 0; i++) { | ||
1937 | if (string + i >= boundary) { | ||
1938 | htm_error_string = "DataAfterAlignedString: Unreasonably long string"; | ||
1939 | return 0; | ||
1940 | } | ||
1941 | if (string[i] != '\0') { | ||
1942 | htm_error_string = "DataAfterAlignedString: Incorrectly padded string."; | ||
1943 | return 0; | ||
1944 | } | ||
1945 | } | ||
1946 | |||
1947 | return string+i; | ||
1948 | } | ||
1949 | |||
1950 | Boolean IsNiceString(char *string, char *boundary) | ||
1951 | { | ||
1952 | /* Arguments same as DataAfterAlignedString(). Is the given "string" | ||
1953 | really a string? I.e., is it a sequence of isprint() characters | ||
1954 | terminated with 1-4 null characters to align on a 4-byte boundary? */ | ||
1955 | |||
1956 | int i; | ||
1957 | |||
1958 | if ((boundary - string) %4 != 0) { | ||
1959 | fprintf(stderr, "Internal error: IsNiceString: bad boundary\n"); | ||
1960 | return 0; | ||
1961 | } | ||
1962 | |||
1963 | for (i = 0; string[i] != '\0'; i++) { | ||
1964 | if (!isprint(string[i])) return FALSE; | ||
1965 | if (string + i >= boundary) return FALSE; | ||
1966 | } | ||
1967 | |||
1968 | /* If we made it this far, it's a null-terminated sequence of printing characters | ||
1969 | in the given boundary. Now we just make sure it's null padded... */ | ||
1970 | |||
1971 | /* Now string[i] is the first null character */ | ||
1972 | i++; | ||
1973 | for (; (i % STRING_ALIGN_PAD) != 0; i++) { | ||
1974 | if (string[i] != '\0') return FALSE; | ||
1975 | } | ||
1976 | |||
1977 | return TRUE; | ||
1978 | } | ||
1979 | |||
1980 | |||
1981 | |||
1982 | |||
1983 | |||
1984 | |||
1985 | |||
1986 | |||
1987 | |||
1988 | #include <stdarg.h> | ||
1989 | void complain(char *s, ...) { | ||
1990 | va_list ap; | ||
1991 | va_start(ap, s); | ||
1992 | fprintf(stderr, "*** ERROR: "); | ||
1993 | vfprintf(stderr, s, ap); | ||
1994 | fprintf(stderr, "\n"); | ||
1995 | va_end(ap); | ||
1996 | } | ||
1997 | |||
1998 | #endif /* __sgi or LINUX or WIN32 */ | ||