Merge pull request #506 from andrewcsmith/patch-2
[supercollider.git] / lang / LangPrimSource / OSCData.cpp
blob85b15f9e787e00cb67944be1fdeae486602827ff
1 /*
2 SuperCollider real time audio synthesis system
3 Copyright (c) 2002 James McCartney. All rights reserved.
4 http://www.audiosynth.com
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 #include "OSCData.h"
22 #include "PyrPrimitive.h"
23 #include "PyrKernel.h"
24 #include "PyrInterpreter.h"
25 #include "PyrSched.h"
26 #include "PyrSymbol.h"
27 #include "GC.h"
28 //#include "PyrOMS.h"
29 //#include "MidiQ.h"
30 #include <string.h>
31 #include <math.h>
32 #include <stdexcept>
33 #include <new>
34 #include <vector>
36 #ifdef SC_WIN32
37 # include <winsock2.h>
38 typedef int socklen_t;
39 # define bzero( ptr, count ) memset( ptr, 0, count )
40 #else
41 # include <sys/socket.h>
42 # include <netinet/tcp.h>
43 # include <netdb.h>
44 #endif
46 #include <pthread.h>
47 #include "scsynthsend.h"
48 #include "sc_msg_iter.h"
49 #include "SC_ComPort.h"
50 #include "SC_WorldOptions.h"
51 #include "SC_SndBuf.h"
52 #include "SC_Endian.h"
54 #ifndef SC_DARWIN
55 # ifndef SC_WIN32
56 # include <unistd.h>
57 # endif
58 #endif
60 #include "../../../common/server_shm.hpp"
62 struct InternalSynthServerGlobals
64 struct World *mWorld;
65 int mNumSharedControls;
66 float *mSharedControls;
69 const int kNumDefaultSharedControls = 1024;
70 float gDefaultSharedControls[kNumDefaultSharedControls];
71 bool gUseDoubles = false;
73 InternalSynthServerGlobals gInternalSynthServer = { 0, kNumDefaultSharedControls, gDefaultSharedControls };
75 SC_UdpInPort* gUDPport = 0;
77 PyrString* newPyrString(VMGlobals *g, char *s, int flags, bool collect);
79 PyrSymbol *s_call, *s_write, *s_recvoscmsg, *s_recvoscbndl, *s_netaddr;
80 const char* gPassword;
81 extern bool compiledOK;
83 std::vector<SC_UdpCustomInPort *> gCustomUdpPorts;
86 ///////////
88 inline bool IsBundle(char* ptr)
90 return strcmp(ptr, "#bundle") == 0;
93 ///////////
95 const int ivxNetAddr_Hostaddr = 0;
96 const int ivxNetAddr_PortID = 1;
97 const int ivxNetAddr_Hostname = 2;
98 const int ivxNetAddr_Socket = 3;
100 void makeSockAddr(struct sockaddr_in &toaddr, int32 addr, int32 port);
101 int sendallto(int socket, const void *msg, size_t len, struct sockaddr *toaddr, int addrlen);
102 int sendall(int socket, const void *msg, size_t len);
103 static int makeSynthMsgWithTags(big_scpacket *packet, PyrSlot *slots, int size);
104 int makeSynthBundle(big_scpacket *packet, PyrSlot *slots, int size, bool useElapsed);
106 static int addMsgSlot(big_scpacket *packet, PyrSlot *slot)
108 switch (GetTag(slot)) {
109 case tagInt :
110 packet->addi(slotRawInt(slot));
111 break;
112 case tagSym :
113 packet->adds(slotRawSymbol(slot)->name);
114 break;
115 case tagObj :
116 if (isKindOf(slotRawObject(slot), class_string)) {
117 PyrString *stringObj = slotRawString(slot);
118 packet->adds(stringObj->s, stringObj->size);
119 } else if (isKindOf(slotRawObject(slot), class_int8array)) {
120 PyrInt8Array *arrayObj = slotRawInt8Array(slot);
121 packet->addb(arrayObj->b, arrayObj->size);
122 } else if (isKindOf(slotRawObject(slot), class_array)) {
123 PyrObject *arrayObj = slotRawObject(slot);
124 big_scpacket packet2;
125 if (arrayObj->size > 1 && isKindOfSlot(arrayObj->slots+1, class_array)) {
126 makeSynthBundle(&packet2, arrayObj->slots, arrayObj->size, true);
127 } else {
128 int error = makeSynthMsgWithTags(&packet2, arrayObj->slots, arrayObj->size);
129 if (error != errNone)
130 return error;
132 packet->addb((uint8*)packet2.data(), packet2.size());
134 break;
135 case tagNil :
136 case tagTrue :
137 case tagFalse :
138 case tagChar :
139 case tagPtr :
140 break;
141 default :
142 if (gUseDoubles) packet->addd(slotRawFloat(slot));
143 else packet->addf(slotRawFloat(slot));
144 break;
146 return errNone;
149 static int addMsgSlotWithTags(big_scpacket *packet, PyrSlot *slot)
151 switch (GetTag(slot)) {
152 case tagInt :
153 packet->addtag('i');
154 packet->addi(slotRawInt(slot));
155 break;
156 case tagSym :
157 packet->addtag('s');
158 packet->adds(slotRawSymbol(slot)->name);
159 break;
160 case tagObj :
161 if (isKindOf(slotRawObject(slot), class_string)) {
162 PyrString *stringObj = slotRawString(slot);
163 packet->addtag('s');
164 packet->adds(stringObj->s, stringObj->size);
165 } else if (isKindOf(slotRawObject(slot), class_int8array)) {
166 PyrInt8Array *arrayObj = slotRawInt8Array(slot);
167 packet->addtag('b');
168 packet->addb(arrayObj->b, arrayObj->size);
169 } else if (isKindOf(slotRawObject(slot), class_array)) {
170 PyrObject *arrayObj = slotRawObject(slot);
171 if (arrayObj->size) {
172 packet->addtag('b');
173 big_scpacket packet2;
174 if (arrayObj->size > 1 && isKindOfSlot(arrayObj->slots+1, class_array)) {
175 makeSynthBundle(&packet2, arrayObj->slots, arrayObj->size, true);
176 } else {
177 int error = makeSynthMsgWithTags(&packet2, arrayObj->slots, arrayObj->size);
178 if (error != errNone)
179 return error;
181 packet->addb((uint8*)packet2.data(), packet2.size());
182 } else {
183 packet->addtag('i');
184 packet->addi(0);
187 break;
188 case tagTrue :
189 packet->addtag('i');
190 packet->addi(1);
191 break;
192 case tagChar :
193 packet->addtag(slotRawChar(slot));
194 break;
195 case tagFalse :
196 case tagNil :
197 case tagPtr :
198 packet->addtag('i');
199 packet->addi(0);
200 break;
201 default :
202 if (gUseDoubles) {
203 packet->addtag('d');
204 packet->addd(slotRawFloat(slot));
205 } else {
206 packet->addtag('f');
207 packet->addf(slotRawFloat(slot));
209 break;
211 return errNone;
214 static int makeSynthMsgWithTags(big_scpacket *packet, PyrSlot *slots, int size)
216 packet->BeginMsg();
218 // First component: OSC Address Pattern.
219 // For convenience, we allow the user to omit the initial '/', when
220 // expressing it as a symbol (e.g. \g_new) - we add it back on here, for OSC compliance.
221 if(GetTag(slots) == tagSym && slotRawSymbol(slots)->name[0]!='/'){
222 packet->adds_slpre(slotRawSymbol(slots)->name);
223 } else {
224 int error = addMsgSlot(packet, slots);
225 if (error != errNone)
226 return error;
229 // skip space for tags
230 packet->maketags(size);
232 packet->addtag(',');
234 try {
235 for (int i=1; i<size; ++i) {
236 int error = addMsgSlotWithTags(packet, slots+i);
237 if (error != errNone)
238 return error;
240 } catch (std::runtime_error & e) {
241 error("makeSynthMsgWithTags: %s\n", e.what());
242 return errFailed;
245 packet->EndMsg();
247 return errNone;
250 void PerformOSCBundle(int inSize, char *inData, PyrObject *inReply, int inPortNum);
251 void PerformOSCMessage(int inSize, char *inData, PyrObject *inReply, int inPortNum);
252 PyrObject* ConvertReplyAddress(ReplyAddress *inReply);
254 void localServerReplyFunc(struct ReplyAddress *inReplyAddr, char* inBuf, int inSize);
255 void localServerReplyFunc(struct ReplyAddress *inReplyAddr, char* inBuf, int inSize)
257 bool isBundle = IsBundle(inBuf);
259 pthread_mutex_lock (&gLangMutex);
260 if (compiledOK) {
261 PyrObject *replyObj = ConvertReplyAddress(inReplyAddr);
262 if (isBundle) {
263 PerformOSCBundle(inSize, inBuf, replyObj, gUDPport->RealPortNum());
264 } else {
265 PerformOSCMessage(inSize, inBuf, replyObj, gUDPport->RealPortNum());
268 pthread_mutex_unlock (&gLangMutex);
272 int makeSynthBundle(big_scpacket *packet, PyrSlot *slots, int size, bool useElapsed)
274 double time;
275 int err;
276 int64 oscTime;
278 err = slotDoubleVal(slots, &time);
279 if (!err) {
280 if (useElapsed) {
281 oscTime = ElapsedTimeToOSC(time);
282 } else {
283 oscTime = (int64)(time * kSecondsToOSC);
285 } else {
286 oscTime = 1; // immediate
288 packet->OpenBundle(oscTime);
290 for (int i=1; i<size; ++i) {
291 if (isKindOfSlot(slots+i, class_array)) {
292 PyrObject *obj = slotRawObject(&slots[i]);
293 int error = makeSynthMsgWithTags(packet, obj->slots, obj->size);
294 if (error != errNone)
295 return error;
298 packet->CloseBundle();
299 return errNone;
302 int netAddrSend(PyrObject *netAddrObj, int msglen, char *bufptr, bool sendMsgLen=true);
303 int netAddrSend(PyrObject *netAddrObj, int msglen, char *bufptr, bool sendMsgLen)
305 int err, port, addr;
307 if (IsPtr(netAddrObj->slots + ivxNetAddr_Socket)) {
308 SC_TcpClientPort* comPort = (SC_TcpClientPort*)slotRawPtr(netAddrObj->slots + ivxNetAddr_Socket);
310 // send TCP
311 int tcpSocket = comPort->Socket();
313 if (sendMsgLen) {
314 // send length of message in network byte-order
315 int32 sizebuf = htonl(msglen);
316 sendall(tcpSocket, &sizebuf, sizeof(int32));
319 sendall(tcpSocket, bufptr, msglen);
321 } else {
322 if (gUDPport == 0) return errFailed;
324 // send UDP
325 err = slotIntVal(netAddrObj->slots + ivxNetAddr_Hostaddr, &addr);
326 if (err) return err;
328 if (addr == 0) {
329 #ifndef NO_INTERNAL_SERVER
330 if (gInternalSynthServer.mWorld) {
331 World_SendPacket(gInternalSynthServer.mWorld, msglen, bufptr, &localServerReplyFunc);
333 #endif
334 return errNone;
337 err = slotIntVal(netAddrObj->slots + ivxNetAddr_PortID, &port);
338 if (err) return err;
340 struct sockaddr_in toaddr;
341 makeSockAddr(toaddr, addr, port);
343 sendallto(gUDPport->Socket(), bufptr, msglen, (sockaddr*)&toaddr, sizeof(toaddr));
346 return errNone;
350 ///////////
352 inline size_t OSCStrLen(char *str)
354 return (strlen(str) + 4) & ~3;
358 int makeSynthBundle(big_scpacket *packet, PyrSlot *slots, int size, bool useElapsed);
360 static void netAddrTcpClientNotifyFunc(void *clientData);
361 void netAddrTcpClientNotifyFunc(void *clientData)
363 extern bool compiledOK;
365 pthread_mutex_lock(&gLangMutex);
366 if (compiledOK) {
367 PyrObject* netAddrObj = (PyrObject*)clientData;
368 VMGlobals* g = gMainVMGlobals;
369 g->canCallOS = false;
370 ++g->sp; SetObject(g->sp, netAddrObj);
371 runInterpreter(g, getsym("prConnectionClosed"), 1);
372 g->canCallOS = false;
374 pthread_mutex_unlock(&gLangMutex);
377 int prNetAddr_Connect(VMGlobals *g, int numArgsPushed);
378 int prNetAddr_Connect(VMGlobals *g, int numArgsPushed)
380 PyrSlot* netAddrSlot = g->sp;
381 PyrObject* netAddrObj = slotRawObject(netAddrSlot);
383 int err, port, addr;
385 err = slotIntVal(netAddrObj->slots + ivxNetAddr_PortID, &port);
386 if (err) return err;
388 err = slotIntVal(netAddrObj->slots + ivxNetAddr_Hostaddr, &addr);
389 if (err) return err;
391 struct sockaddr_in toaddr;
392 makeSockAddr(toaddr, addr, port);
394 int aSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
395 if (aSocket == -1) {
396 //post("\nCould not create socket\n");
397 return errFailed;
400 const int on = 1;
401 #ifdef SC_WIN32
402 if (setsockopt( aSocket, IPPROTO_TCP, TCP_NODELAY, (const char*)&on, sizeof(on)) != 0) {
403 #else
404 if (setsockopt( aSocket, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on)) != 0) {
405 #endif
406 //post("\nCould not setsockopt TCP_NODELAY\n");
407 #ifdef SC_WIN32
408 closesocket(aSocket);
409 #else
410 close(aSocket);
411 #endif
412 return errFailed;
416 if(connect(aSocket,(struct sockaddr*)&toaddr,sizeof(toaddr)) != 0)
418 //post("\nCould not connect socket\n");
419 #ifdef SC_WIN32
420 closesocket(aSocket);
421 #else
422 close(aSocket);
423 #endif
424 return errFailed;
427 SC_TcpClientPort *comPort = new SC_TcpClientPort(aSocket, netAddrTcpClientNotifyFunc, netAddrObj);
428 SetPtr(netAddrObj->slots + ivxNetAddr_Socket, comPort);
430 return errNone;
433 int prNetAddr_Disconnect(VMGlobals *g, int numArgsPushed);
434 int prNetAddr_Disconnect(VMGlobals *g, int numArgsPushed)
436 PyrSlot* netAddrSlot = g->sp;
437 PyrObject* netAddrObj = slotRawObject(netAddrSlot);
439 SC_TcpClientPort *comPort = (SC_TcpClientPort*)slotRawPtr(netAddrObj->slots + ivxNetAddr_Socket);
440 if (comPort) comPort->Close();
442 return errNone;
446 int prNetAddr_SendMsg(VMGlobals *g, int numArgsPushed);
447 int prNetAddr_SendMsg(VMGlobals *g, int numArgsPushed)
449 PyrSlot* netAddrSlot = g->sp - numArgsPushed + 1;
450 PyrSlot* args = netAddrSlot + 1;
451 big_scpacket packet;
453 int numargs = numArgsPushed - 1;
454 int error = makeSynthMsgWithTags(&packet, args, numargs);
455 if (error != errNone)
456 return error;
458 //for (int i=0; i<packet.size()/4; i++) post("%d %p\n", i, packet.buf[i]);
460 return netAddrSend(slotRawObject(netAddrSlot), packet.size(), (char*)packet.buf);
464 int prNetAddr_SendBundle(VMGlobals *g, int numArgsPushed);
465 int prNetAddr_SendBundle(VMGlobals *g, int numArgsPushed)
467 PyrSlot* netAddrSlot = g->sp - numArgsPushed + 1;
468 PyrSlot* args = netAddrSlot + 1;
469 big_scpacket packet;
471 double time;
472 int err = slotDoubleVal(args, &time);
473 if (!err) {
474 time += slotRawFloat(&g->thread->seconds);
475 SetFloat(args, time);
477 int numargs = numArgsPushed - 1;
478 makeSynthBundle(&packet, args, numargs, true);
480 //for (int i=0; i<packet.size()/4; i++) post("%d %p\n", i, packet.buf[i]);
482 return netAddrSend(slotRawObject(netAddrSlot), packet.size(), (char*)packet.buf);
485 int prNetAddr_SendRaw(VMGlobals *g, int numArgsPushed);
486 int prNetAddr_SendRaw(VMGlobals *g, int numArgsPushed)
488 PyrSlot* netAddrSlot = g->sp - 1;
489 PyrSlot* arraySlot = g->sp;
490 PyrObject* netAddrObj = slotRawObject(netAddrSlot);
492 if (!IsObj(arraySlot) || !isKindOf(slotRawObject(arraySlot), class_rawarray)) {
493 error("sendRaw arg must be a kind of RawArray.\n");
494 return errWrongType;
496 PyrObject *array = slotRawObject(arraySlot);
498 char *bufptr = (char*)array->slots;
499 int32 msglen = array->size * gFormatElemSize[array->obj_format];
501 return netAddrSend(netAddrObj, msglen, bufptr, false);
504 int prNetAddr_GetBroadcastFlag(VMGlobals *g, int numArgsPushed);
505 int prNetAddr_GetBroadcastFlag(VMGlobals *g, int numArgsPushed)
507 if (gUDPport == 0) return errFailed;
508 int opt;
509 socklen_t optlen = sizeof(opt);
510 #ifdef SC_WIN32
511 if (getsockopt(gUDPport->Socket(), SOL_SOCKET, SO_BROADCAST, (char *)&opt, &optlen) == -1)
512 #else
513 if (getsockopt(gUDPport->Socket(), SOL_SOCKET, SO_BROADCAST, &opt, &optlen) == -1)
514 #endif
515 return errFailed;
516 SetBool(g->sp, opt);
517 return errNone;
520 int prNetAddr_SetBroadcastFlag(VMGlobals *g, int numArgsPushed);
521 int prNetAddr_SetBroadcastFlag(VMGlobals *g, int numArgsPushed)
523 if (gUDPport == 0) return errFailed;
524 int opt = IsTrue(g->sp);
525 #ifdef SC_WIN32
526 if (setsockopt(gUDPport->Socket(), SOL_SOCKET, SO_BROADCAST, (char *)&opt, sizeof(opt)) == -1)
527 #else
528 if (setsockopt(gUDPport->Socket(), SOL_SOCKET, SO_BROADCAST, &opt, sizeof(opt)) == -1)
529 #endif
530 return errFailed;
531 return errNone;
534 int prNetAddr_BundleSize(VMGlobals *g, int numArgsPushed);
535 int prNetAddr_BundleSize(VMGlobals *g, int numArgsPushed)
537 PyrSlot* args = g->sp;
538 big_scpacket packet;
539 int numargs = slotRawObject(args)->size;
540 if (numargs < 1) return errFailed;
541 makeSynthBundle(&packet, slotRawObject(args)->slots, numargs, true);
542 SetInt(args, packet.size());
543 return errNone;
546 int prNetAddr_MsgSize(VMGlobals *g, int numArgsPushed);
547 int prNetAddr_MsgSize(VMGlobals *g, int numArgsPushed)
549 PyrSlot* args = g->sp;
550 big_scpacket packet;
552 int numargs = slotRawObject(args)->size;
553 if (numargs < 1) return errFailed;
554 int error = makeSynthMsgWithTags(&packet, slotRawObject(args)->slots, numargs);
555 if (error != errNone)
556 return error;
558 SetInt(args, packet.size());
559 return errNone;
563 int prNetAddr_UseDoubles(VMGlobals *g, int numArgsPushed);
564 int prNetAddr_UseDoubles(VMGlobals *g, int numArgsPushed)
566 //PyrSlot* netAddrSlot = g->sp - 1;
567 PyrSlot* flag = g->sp;
569 gUseDoubles = IsTrue(flag);
571 return errNone;
574 int prArray_OSCBytes(VMGlobals *g, int numArgsPushed);
575 int prArray_OSCBytes(VMGlobals *g, int numArgsPushed)
577 PyrSlot* a = g->sp;
578 PyrObject *array = slotRawObject(a);
579 PyrSlot* args = array->slots;
580 int numargs = array->size;
581 if (numargs < 1) return errFailed;
582 big_scpacket packet;
584 if (IsFloat(args) || IsNil(args) || IsInt(args)) {
585 makeSynthBundle(&packet, args, numargs, false);
586 } else if (IsSym(args) || isKindOfSlot(args, class_string)) {
587 int error = makeSynthMsgWithTags(&packet, args, numargs);
588 if (error != errNone)
589 return error;
590 } else {
591 return errWrongType;
594 int size = packet.size();
595 PyrInt8Array* obj = newPyrInt8Array(g->gc, size, 0, true);
596 obj->size = size;
597 memcpy(obj->b, packet.data(), size);
598 SetObject(a, (PyrObject*)obj);
599 //for (int i=0; i<packet.size()/4; i++) post("%d %p\n", i, packet.buf[i]);
601 return errNone;
604 // Create a new <PyrInt8Array> object and copy data from `msg.getb'.
605 // Bytes are properly untyped, but there is no <UInt8Array> type.
607 static PyrInt8Array* MsgToInt8Array ( sc_msg_iter msg ) ;
608 static PyrInt8Array* MsgToInt8Array ( sc_msg_iter msg )
610 int size = msg.getbsize() ;
611 VMGlobals *g = gMainVMGlobals ;
612 PyrInt8Array *obj = newPyrInt8Array ( g->gc , size , 0 , true ) ;
613 obj->size = size ;
614 msg.getb ( (char *)obj->b , obj->size ) ;
615 return obj ;
618 PyrObject* ConvertOSCMessage(int inSize, char *inData)
620 char *cmdName = inData;
621 int cmdNameLen = OSCstrlen(cmdName);
622 sc_msg_iter msg(inSize - cmdNameLen, inData + cmdNameLen);
624 int numElems;
625 if (inSize == cmdNameLen) {
626 numElems = 0;
627 } else {
628 if (!msg.tags) {
629 numElems = 0;
630 error("OSC messages must have type tags. %s\n", cmdName);
631 } else {
632 numElems = strlen(msg.tags);
635 //post("tags %s %d\n", msg.tags, numElems);
637 VMGlobals *g = gMainVMGlobals;
638 PyrObject *obj = newPyrArray(g->gc, numElems + 1, 0, false);
639 PyrSlot *slots = obj->slots;
641 SetSymbol(slots+0, getsym(cmdName));
643 for (int i=0; i<numElems; ++i) {
644 char tag = msg.nextTag();
645 //post("%d %c\n", i, tag);
646 switch (tag) {
647 case 'i' :
648 SetInt(slots+i+1, msg.geti());
649 break;
650 case 'f' :
651 SetFloat(slots+i+1, msg.getf());
652 break;
653 case 'd' :
654 SetFloat(slots+i+1, msg.getd());
655 break;
656 case 's' :
657 SetSymbol(slots+i+1, getsym(msg.gets()));
658 //post("sym '%s'\n", slots[i+1].us->name);
659 break;
660 case 'b' :
661 SetObject(slots+i+1, (PyrObject*)MsgToInt8Array(msg));
662 break;
663 case 'c':
664 SetChar(slots+i+1, (char)msg.geti());
665 break;
666 // else add the type tag as a char (jrhb 2009)
667 default:
668 SetChar(slots+i+1, tag);
669 msg.gets();
672 obj->size = numElems + 1;
673 return obj;
676 PyrObject* ConvertReplyAddress(ReplyAddress *inReply)
678 VMGlobals *g = gMainVMGlobals;
679 PyrObject *obj = instantiateObject(g->gc, s_netaddr->u.classobj, 2, true, false);
680 PyrSlot *slots = obj->slots;
681 SetInt(slots+0, ntohl(inReply->mSockAddr.sin_addr.s_addr));
682 SetInt(slots+1, ntohs(inReply->mSockAddr.sin_port));
683 return obj;
686 void PerformOSCBundle(int inSize, char* inData, PyrObject *replyObj, int inPortNum)
688 // convert all data to arrays
690 int64 oscTime = OSCtime(inData + 8);
691 double seconds = OSCToElapsedTime(oscTime);
693 VMGlobals *g = gMainVMGlobals;
694 ++g->sp; SetObject(g->sp, g->process);
695 ++g->sp; SetFloat(g->sp, seconds);
696 ++g->sp; SetObject(g->sp, replyObj);
697 ++g->sp; SetInt(g->sp, inPortNum);
699 PyrSlot *stackBase = g->sp;
700 char *data = inData + 16;
701 char* dataEnd = inData + inSize;
702 while (data < dataEnd) {
703 int32 msgSize = OSCint(data);
704 data += sizeof(int32);
705 PyrObject *arrayObj = ConvertOSCMessage(msgSize, data);
706 ++g->sp; SetObject(g->sp, arrayObj);
707 data += msgSize;
710 int numMsgs = g->sp - stackBase;
712 runInterpreter(g, s_recvoscbndl, 4+numMsgs);
715 void ConvertOSCBundle(int inSize, char* inData, PyrObject *replyObj)
717 // convert all data to arrays
719 //int64 oscTime = OSCtime(inData + 8);
720 //double seconds = OSCToElapsedTime(oscTime);
722 VMGlobals *g = gMainVMGlobals;
724 int numMsgs = 0;
725 char *data = inData + 16;
726 char* dataEnd = inData + inSize;
727 while (data < dataEnd) {
728 int32 msgSize = OSCint(data);
729 data += sizeof(int32);
730 PyrObject *arrayObj = ConvertOSCMessage(msgSize, data);
731 ++g->sp; SetObject(g->sp, arrayObj);
732 numMsgs++;
733 data += msgSize;
737 void PerformOSCMessage(int inSize, char *inData, PyrObject *replyObj, int inPortNum)
740 PyrObject *arrayObj = ConvertOSCMessage(inSize, inData);
742 // call virtual machine to handle message
743 VMGlobals *g = gMainVMGlobals;
744 ++g->sp; SetObject(g->sp, g->process);
745 ++g->sp; SetFloat(g->sp, elapsedTime()); // time
746 ++g->sp; SetObject(g->sp, replyObj);
747 ++g->sp; SetInt(g->sp, inPortNum);
748 ++g->sp; SetObject(g->sp, arrayObj);
750 runInterpreter(g, s_recvoscmsg, 5);
755 void FreeOSCPacket(OSC_Packet *inPacket)
757 //post("->FreeOSCPacket %p\n", inPacket);
758 if (inPacket) {
759 free(inPacket->mData);
760 free(inPacket);
764 void ProcessOSCPacket(OSC_Packet* inPacket, int inPortNum)
766 //post("recv '%s' %d\n", inPacket->mData, inPacket->mSize);
767 inPacket->mIsBundle = IsBundle(inPacket->mData);
769 pthread_mutex_lock (&gLangMutex);
770 if (compiledOK) {
771 PyrObject *replyObj = ConvertReplyAddress(&inPacket->mReplyAddr);
772 if (compiledOK) {
773 if (inPacket->mIsBundle) {
774 PerformOSCBundle(inPacket->mSize, inPacket->mData, replyObj, inPortNum);
775 } else {
776 PerformOSCMessage(inPacket->mSize, inPacket->mData, replyObj, inPortNum);
780 pthread_mutex_unlock (&gLangMutex);
782 FreeOSCPacket(inPacket);
785 void init_OSC(int port);
786 void init_OSC(int port)
788 postfl("init_OSC\n");
790 #ifdef _WIN32
791 WSAData wsaData;
792 int nCode;
793 if ((nCode = WSAStartup(MAKEWORD(1, 1), &wsaData)) != 0) {
794 error( "sclang: init_OSC: WSAStartup() failed with error code %d.\n", nCode );
796 #endif
798 try {
799 gUDPport = new SC_UdpInPort(port);
800 } catch (...) {
801 postfl("No networking.");
805 int prOpenUDPPort(VMGlobals *g, int numArgsPushed);
806 int prOpenUDPPort(VMGlobals *g, int numArgsPushed)
808 PyrSlot *a = g->sp - 1;
809 PyrSlot *b = g->sp;
810 int port;
811 int err = slotIntVal(b, &port);
812 if (err) return err;
814 SC_UdpCustomInPort* newUDPport;
816 try {
817 SetTrue(a);
818 newUDPport = new SC_UdpCustomInPort(port);
819 gCustomUdpPorts.push_back(newUDPport);
820 } catch (...) {
821 SetFalse(a);
822 postfl("Could not bind to requested port. This may mean it is in use already by another application.\n");
824 return errNone;
827 void closeAllCustomPorts();
828 void closeAllCustomPorts()
830 // close all custom sockets
831 if(gCustomUdpPorts.empty()) postfl("empty\n");
832 for(int i=0; i<gCustomUdpPorts.size(); i++){
833 delete gCustomUdpPorts[i];
835 gCustomUdpPorts.clear();
838 void cleanup_OSC()
840 postfl( "cleaning up OSC\n");
841 #ifdef _WIN32
842 WSACleanup();
843 #endif
846 int prGetHostByName(VMGlobals *g, int numArgsPushed);
847 int prGetHostByName(VMGlobals *g, int numArgsPushed)
849 PyrSlot *a = g->sp;
850 char hostname[256];
852 int err = slotStrVal(a, hostname, 255);
853 if (err) return err;
855 struct hostent *he = gethostbyname(hostname);
856 if (!he) {
857 #ifdef _WIN32
858 int err = WSAGetLastError();
859 error("gethostbyname(\"%s\") failed with error code %i.\n",
860 hostname, err);
861 #endif
862 return errFailed;
865 SetInt(a, ntohl(*(int*)he->h_addr));
867 return errNone;
870 int prGetLangPort(VMGlobals *g, int numArgsPushed);
871 int prGetLangPort(VMGlobals *g, int numArgsPushed)
873 PyrSlot *a = g->sp;
874 if (!gUDPport) return errFailed;
875 SetInt(a, gUDPport->RealPortNum());
876 return errNone;
879 int prExit(VMGlobals *g, int numArgsPushed);
880 int prExit(VMGlobals *g, int numArgsPushed)
882 PyrSlot *a = g->sp;
884 exit(slotRawInt(a));
886 //post("exit %d\n", slotRawInt(a));
887 //DumpBackTrace(g);
888 return errNone;
891 extern "C" {
892 int vpost(const char *fmt, va_list vargs);
895 #ifndef NO_INTERNAL_SERVER
896 int prBootInProcessServer(VMGlobals *g, int numArgsPushed);
897 int prBootInProcessServer(VMGlobals *g, int numArgsPushed)
899 PyrSlot *a = g->sp;
901 if (!gInternalSynthServer.mWorld) {
902 SetPrintFunc(&vpost);
903 WorldOptions options = kDefaultWorldOptions;
905 PyrObject *optionsObj = slotRawObject(a);
906 PyrSlot *optionsSlots = optionsObj->slots;
908 static char mInputStreamsEnabled[512], mOutputStreamsEnabled[512], mDeviceName[512];
909 int err;
911 err = slotIntVal(optionsSlots + 0, (int*)&options.mNumAudioBusChannels);
912 if (err) return err;
914 err = slotIntVal(optionsSlots + 1, (int*)&options.mNumControlBusChannels);
915 if (err) return err;
917 err = slotIntVal(optionsSlots + 2, (int*)&options.mNumInputBusChannels);
918 if (err) return err;
920 err = slotIntVal(optionsSlots + 3, (int*)&options.mNumOutputBusChannels);
921 if (err) return err;
923 err = slotIntVal(optionsSlots + 4, (int*)&options.mNumBuffers);
924 if (err) return err;
926 err = slotIntVal(optionsSlots + 5, (int*)&options.mMaxNodes);
927 if (err) return err;
929 err = slotIntVal(optionsSlots + 6, (int*)&options.mMaxGraphDefs);
930 if (err) return err;
932 err = slotIntVal(optionsSlots + 8, (int*)&options.mBufLength);
933 if (err) return err;
935 if (NotNil(optionsSlots + 9)) {
936 err = slotIntVal(optionsSlots + 9, (int*)&options.mPreferredHardwareBufferFrameSize);
937 if (err) return err;
940 err = slotIntVal(optionsSlots + 10, (int*)&options.mRealTimeMemorySize);
941 if (err) return err;
943 err = slotIntVal(optionsSlots + 11, (int*)&options.mNumRGens);
944 if (err) return err;
946 err = slotIntVal(optionsSlots + 12, (int*)&options.mMaxWireBufs);
947 if (err) return err;
949 if (NotNil(optionsSlots + 13)) {
950 err = slotIntVal(optionsSlots + 13, (int*)&options.mPreferredSampleRate);
951 if (err) return err;
954 options.mLoadGraphDefs = IsTrue(optionsSlots + 14) ? 1 : 0;
956 #ifdef SC_DARWIN
957 err = slotStrVal(optionsSlots+15, mInputStreamsEnabled, 512);
958 if(err) options.mInputStreamsEnabled = NULL;
959 else options.mInputStreamsEnabled = mInputStreamsEnabled;
961 err = slotStrVal(optionsSlots+16, mOutputStreamsEnabled, 512);
962 if(err) options.mOutputStreamsEnabled = NULL;
963 else options.mOutputStreamsEnabled = mOutputStreamsEnabled;
964 #endif
966 err = slotStrVal(optionsSlots+17, mDeviceName, 512);
967 if(err) options.mInDeviceName = options.mOutDeviceName = NULL;
968 else options.mInDeviceName = options.mOutDeviceName = mDeviceName;
970 options.mNumSharedControls = gInternalSynthServer.mNumSharedControls;
971 options.mSharedControls = gInternalSynthServer.mSharedControls;
973 // internal servers use the PID to identify the shared memory region
974 #if defined(SC_IPHONE)
975 options.mSharedMemoryID = 0;
976 #elif !defined(_WIN32)
977 options.mSharedMemoryID = getpid();
978 #else
979 options.mSharedMemoryID = GetCurrentProcessId();
980 #endif
982 gInternalSynthServer.mWorld = World_New(&options);
985 return errNone;
988 int getScopeBuf(uint32 index, SndBuf *buf, bool& didChange)
990 if (gInternalSynthServer.mWorld) {
991 int serverErr = World_CopySndBuf(gInternalSynthServer.mWorld, index, buf, true, &didChange);
992 if (serverErr) return errFailed;
993 } else {
994 didChange = false;
996 return errNone;
998 void* wait_for_quit(void* thing);
999 void* wait_for_quit(void* thing)
1001 World *world = (World*)thing;
1002 World_WaitForQuit(world);
1003 return 0;
1006 int prQuitInProcessServer(VMGlobals *g, int numArgsPushed);
1007 int prQuitInProcessServer(VMGlobals *g, int numArgsPushed)
1009 //PyrSlot *a = g->sp;
1011 if (gInternalSynthServer.mWorld) {
1012 World *world = gInternalSynthServer.mWorld;
1013 gInternalSynthServer.mWorld = 0;
1015 pthread_t thread;
1016 pthread_create(&thread, NULL, wait_for_quit, (void*)world);
1017 pthread_detach(thread);
1020 return errNone;
1022 #else // is windows
1023 int prQuitInProcessServer(VMGlobals *g, int numArgsPushed);
1024 int prQuitInProcessServer(VMGlobals *g, int numArgsPushed)
1026 // no-op. Better to have this than to overwrite in lang.
1027 return errNone;
1029 #endif
1030 //#ifndef SC_WIN32
1032 inline int32 BUFMASK(int32 x)
1034 return (1 << (31 - CLZ(x))) - 1;
1037 int prAllocSharedControls(VMGlobals *g, int numArgsPushed);
1038 int prAllocSharedControls(VMGlobals *g, int numArgsPushed)
1040 //PyrSlot *a = g->sp - 1;
1041 PyrSlot *b = g->sp;
1043 if (gInternalSynthServer.mWorld) {
1044 post("can't allocate while internal server is running\n");
1045 return errNone;
1047 if (gInternalSynthServer.mSharedControls != gDefaultSharedControls) {
1048 free(gInternalSynthServer.mSharedControls);
1049 gInternalSynthServer.mSharedControls = gDefaultSharedControls;
1051 int numSharedControls;
1052 int err = slotIntVal(b, &numSharedControls);
1053 if (err) return err;
1054 if (numSharedControls <= 0) {
1055 gInternalSynthServer.mNumSharedControls = 0;
1056 } else if (numSharedControls < kNumDefaultSharedControls) {
1057 gInternalSynthServer.mNumSharedControls = numSharedControls;
1058 } else {
1059 gInternalSynthServer.mNumSharedControls = numSharedControls;
1060 gInternalSynthServer.mSharedControls = (float*)calloc(numSharedControls, sizeof(float));
1062 return errNone;
1066 int prGetSharedControl(VMGlobals *g, int numArgsPushed);
1067 int prGetSharedControl(VMGlobals *g, int numArgsPushed)
1069 PyrSlot *a = g->sp - 1;
1070 PyrSlot *b = g->sp;
1072 int index;
1073 int err = slotIntVal(b, &index);
1074 if (err) return err;
1075 if (index < 0 || index >= gInternalSynthServer.mNumSharedControls) {
1076 SetFloat(a, 0.);
1077 return errNone;
1079 float val = gInternalSynthServer.mSharedControls[index];
1080 SetFloat(a, val);
1081 return errNone;
1084 int prSetSharedControl(VMGlobals *g, int numArgsPushed);
1085 int prSetSharedControl(VMGlobals *g, int numArgsPushed)
1087 //PyrSlot *a = g->sp - 2;
1088 PyrSlot *b = g->sp - 1;
1089 PyrSlot *c = g->sp;
1091 int index;
1092 int err = slotIntVal(b, &index);
1093 if (err) return err;
1095 float val;
1096 err = slotFloatVal(c, &val);
1097 if (err) return err;
1099 if (index < 0 || index >= gInternalSynthServer.mNumSharedControls) {
1100 return errNone;
1102 gInternalSynthServer.mSharedControls[index] = val;
1103 return errNone;
1106 static int disconnectSharedMem(VMGlobals *g, PyrObject * object)
1108 int ptrIndex = 0;
1109 PyrSlot * ptrSlot = object->slots + ptrIndex;
1111 if (IsNil(ptrSlot))
1112 // already disconnected
1113 return errNone;
1115 assert(IsPtr(ptrSlot));
1117 server_shared_memory_client * client = (server_shared_memory_client*)slotRawPtr(ptrSlot);
1118 delete client;
1119 SetNil(ptrSlot);
1120 return errNone;
1123 int prConnectSharedMem(VMGlobals *g, int numArgsPushed)
1125 #if !defined(SC_IPHONE)
1126 PyrSlot *a = g->sp - 1;
1127 PyrSlot *b = g->sp;
1129 assert(IsObj(a));
1131 PyrObject * self = slotRawObject(a);
1132 int portNumber = slotRawInt(b);
1134 int ptrIndex = 0;
1135 int finalizerIndex = 1;
1137 try {
1138 server_shared_memory_client * client = new server_shared_memory_client(portNumber);
1139 SetPtr(self->slots + ptrIndex, client);
1141 InstallFinalizer(g, self, finalizerIndex, disconnectSharedMem);
1143 postfl("Shared memory server interface initialized\n");
1144 } catch (std::exception & e) {
1145 postfl("Cannot connect to shared memory: %s\n", e.what());
1146 return errFailed;
1148 #else
1149 postfl("Warning: Shared memory server interface disabled on iphone\n");
1150 #endif
1151 return errNone;
1154 int prDisconnectSharedMem(VMGlobals *g, int numArgsPushed)
1156 PyrSlot *a = g->sp;
1158 assert(IsObj(a));
1159 PyrObject * self = slotRawObject(a);
1160 return disconnectSharedMem(g, self);
1163 int prGetControlBusValue(VMGlobals *g, int numArgsPushed)
1165 PyrSlot *a = g->sp - 1;
1166 PyrSlot *b = g->sp;
1168 assert(IsObj(a));
1169 PyrObject * self = slotRawObject(a);
1170 int ptrIndex = 0;
1171 PyrSlot * ptrSlot = self->slots + ptrIndex;
1172 if (NotPtr(ptrSlot))
1173 return errFailed;
1175 if (!IsInt(b))
1176 return errFailed;
1178 int busIndex = slotRawInt(b);
1180 if (NotPtr(ptrSlot))
1181 return errFailed;
1183 server_shared_memory_client * client = (server_shared_memory_client*)slotRawPtr(ptrSlot);
1185 float value = client->get_control_busses()[busIndex];
1186 SetFloat(a, value);
1187 return errNone;
1190 int prGetControlBusValues(VMGlobals *g, int numArgsPushed)
1192 PyrSlot *a = g->sp - 2;
1193 PyrSlot *b = g->sp - 1;
1194 PyrSlot *c = g->sp;
1196 assert(IsObj(a));
1197 PyrObject * self = slotRawObject(a);
1198 int ptrIndex = 0;
1199 PyrSlot * ptrSlot = self->slots + ptrIndex;
1200 if (NotPtr(ptrSlot))
1201 return errFailed;
1203 if (!IsInt(b))
1204 return errFailed;
1206 int busIndex = slotRawInt(b);
1208 if (!IsInt(c))
1209 return errFailed;
1211 int numberOfChannels = slotRawInt(c);
1213 server_shared_memory_client * client = (server_shared_memory_client*)slotRawPtr(ptrSlot);
1215 PyrObject * ret = newPyrArray(g->gc, numberOfChannels, 0, 1);
1216 ret->size = numberOfChannels;
1218 for (int i = 0; i != numberOfChannels; ++i) {
1219 float value = client->get_control_busses()[busIndex + i];
1220 SetFloat(ret->slots+i, value);
1223 SetObject(a, ret);
1224 return errNone;
1227 int prSetControlBusValue(VMGlobals *g, int numArgsPushed)
1229 PyrSlot *a = g->sp - 2;
1230 PyrSlot *b = g->sp - 1;
1231 PyrSlot *c = g->sp;
1233 assert(IsObj(a));
1234 PyrObject * self = slotRawObject(a);
1235 int ptrIndex = 0;
1236 PyrSlot * ptrSlot = self->slots + ptrIndex;
1237 if (NotPtr(ptrSlot))
1238 return errFailed;
1240 if (!IsInt(b))
1241 return errFailed;
1243 int busIndex = slotRawInt(b);
1245 if (NotPtr(ptrSlot))
1246 return errFailed;
1248 float value;
1249 int error = slotFloatVal(c, &value);
1250 if (error != errNone)
1251 return error;
1253 server_shared_memory_client * client = (server_shared_memory_client*)slotRawPtr(ptrSlot);
1255 client->get_control_busses()[busIndex] = value;
1256 return errNone;
1259 int prSetControlBusValues(VMGlobals *g, int numArgsPushed)
1261 PyrSlot *a = g->sp - 2;
1262 PyrSlot *b = g->sp - 1;
1263 PyrSlot *c = g->sp;
1265 assert(IsObj(a));
1266 PyrObject * self = slotRawObject(a);
1267 int ptrIndex = 0;
1268 PyrSlot * ptrSlot = self->slots + ptrIndex;
1269 if (NotPtr(ptrSlot))
1270 return errFailed;
1272 if (!IsInt(b))
1273 return errFailed;
1275 int busIndex = slotRawInt(b);
1277 if (!IsObj(c))
1278 return errFailed;
1280 PyrObject * values = slotRawObject(c);
1281 server_shared_memory_client * client = (server_shared_memory_client*)slotRawPtr(ptrSlot);
1282 float * control_busses = client->get_control_busses() + busIndex;
1284 for (int i = 0; i != values->size; ++i) {
1285 float value;
1286 int error = slotFloatVal(values->slots + i, &value);
1287 if (error != errNone)
1288 return error;
1290 control_busses[i] = value;
1292 return errNone;
1295 void init_OSC_primitives();
1296 void init_OSC_primitives()
1298 int base, index;
1300 base = nextPrimitiveIndex();
1301 index = 0;
1303 definePrimitive(base, index++, "_NetAddr_Connect", prNetAddr_Connect, 1, 0);
1304 definePrimitive(base, index++, "_NetAddr_Disconnect", prNetAddr_Disconnect, 1, 0);
1305 definePrimitive(base, index++, "_NetAddr_SendMsg", prNetAddr_SendMsg, 1, 1);
1306 definePrimitive(base, index++, "_NetAddr_SendBundle", prNetAddr_SendBundle, 2, 1);
1307 definePrimitive(base, index++, "_NetAddr_SendRaw", prNetAddr_SendRaw, 2, 0);
1308 definePrimitive(base, index++, "_NetAddr_GetBroadcastFlag", prNetAddr_GetBroadcastFlag, 1, 0);
1309 definePrimitive(base, index++, "_NetAddr_SetBroadcastFlag", prNetAddr_SetBroadcastFlag, 2, 0);
1310 definePrimitive(base, index++, "_NetAddr_BundleSize", prNetAddr_BundleSize, 1, 0);
1311 definePrimitive(base, index++, "_NetAddr_MsgSize", prNetAddr_MsgSize, 1, 0);
1313 definePrimitive(base, index++, "_NetAddr_UseDoubles", prNetAddr_UseDoubles, 2, 0);
1314 definePrimitive(base, index++, "_Array_OSCBytes", prArray_OSCBytes, 1, 0);
1315 definePrimitive(base, index++, "_GetHostByName", prGetHostByName, 1, 0);
1316 definePrimitive(base, index++, "_GetLangPort", prGetLangPort, 1, 0);
1317 definePrimitive(base, index++, "_Exit", prExit, 1, 0);
1318 #ifndef NO_INTERNAL_SERVER
1319 definePrimitive(base, index++, "_BootInProcessServer", prBootInProcessServer, 1, 0);
1320 #endif
1321 definePrimitive(base, index++, "_QuitInProcessServer", prQuitInProcessServer, 1, 0);
1322 definePrimitive(base, index++, "_AllocSharedControls", prAllocSharedControls, 2, 0);
1323 definePrimitive(base, index++, "_SetSharedControl", prSetSharedControl, 3, 0);
1324 definePrimitive(base, index++, "_GetSharedControl", prGetSharedControl, 2, 0);
1325 definePrimitive(base, index++, "_OpenUDPPort", prOpenUDPPort, 2, 0);
1327 // server shared memory interface
1328 definePrimitive(base, index++, "_ServerShmInterface_connectSharedMem", prConnectSharedMem, 2, 0);
1329 definePrimitive(base, index++, "_ServerShmInterface_disconnectSharedMem", prDisconnectSharedMem, 1, 0);
1330 definePrimitive(base, index++, "_ServerShmInterface_getControlBusValue", prGetControlBusValue, 2, 0);
1331 definePrimitive(base, index++, "_ServerShmInterface_getControlBusValues", prGetControlBusValues, 3, 0);
1333 definePrimitive(base, index++, "_ServerShmInterface_setControlBusValue", prSetControlBusValue, 3, 0);
1334 definePrimitive(base, index++, "_ServerShmInterface_setControlBusValues", prSetControlBusValues, 4, 0);
1336 //post("initOSCRecs###############\n");
1337 s_call = getsym("call");
1338 s_write = getsym("write");
1339 s_recvoscmsg = getsym("recvOSCmessage");
1340 s_recvoscbndl = getsym("recvOSCbundle");
1341 s_netaddr = getsym("NetAddr");