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
22 #include "PyrPrimitive.h"
23 #include "PyrKernel.h"
24 #include "PyrInterpreter.h"
26 #include "PyrSymbol.h"
37 # include <winsock2.h>
38 typedef int socklen_t
;
39 # define bzero( ptr, count ) memset( ptr, 0, count )
41 # include <sys/socket.h>
42 # include <netinet/tcp.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"
60 #include "../../../common/server_shm.hpp"
62 struct InternalSynthServerGlobals
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
;
88 inline bool IsBundle(char* ptr
)
90 return strcmp(ptr
, "#bundle") == 0;
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
)) {
110 packet
->addi(slotRawInt(slot
));
113 packet
->adds(slotRawSymbol(slot
)->name
);
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);
128 int error
= makeSynthMsgWithTags(&packet2
, arrayObj
->slots
, arrayObj
->size
);
129 if (error
!= errNone
)
132 packet
->addb((uint8
*)packet2
.data(), packet2
.size());
142 if (gUseDoubles
) packet
->addd(slotRawFloat(slot
));
143 else packet
->addf(slotRawFloat(slot
));
149 static int addMsgSlotWithTags(big_scpacket
*packet
, PyrSlot
*slot
)
151 switch (GetTag(slot
)) {
154 packet
->addi(slotRawInt(slot
));
158 packet
->adds(slotRawSymbol(slot
)->name
);
161 if (isKindOf(slotRawObject(slot
), class_string
)) {
162 PyrString
*stringObj
= slotRawString(slot
);
164 packet
->adds(stringObj
->s
, stringObj
->size
);
165 } else if (isKindOf(slotRawObject(slot
), class_int8array
)) {
166 PyrInt8Array
*arrayObj
= slotRawInt8Array(slot
);
168 packet
->addb(arrayObj
->b
, arrayObj
->size
);
169 } else if (isKindOf(slotRawObject(slot
), class_array
)) {
170 PyrObject
*arrayObj
= slotRawObject(slot
);
171 if (arrayObj
->size
) {
173 big_scpacket packet2
;
174 if (arrayObj
->size
> 1 && isKindOfSlot(arrayObj
->slots
+1, class_array
)) {
175 makeSynthBundle(&packet2
, arrayObj
->slots
, arrayObj
->size
, true);
177 int error
= makeSynthMsgWithTags(&packet2
, arrayObj
->slots
, arrayObj
->size
);
178 if (error
!= errNone
)
181 packet
->addb((uint8
*)packet2
.data(), packet2
.size());
193 packet
->addtag(slotRawChar(slot
));
204 packet
->addd(slotRawFloat(slot
));
207 packet
->addf(slotRawFloat(slot
));
214 static int makeSynthMsg(big_scpacket
*packet
, PyrSlot
*slots
, int size
)
218 for (int i
=0; i
<size
; ++i
) {
219 int error
= addMsgSlot(packet
, slots
+i
);
220 if (error
!= errNone
)
228 static int makeSynthMsgWithTags(big_scpacket
*packet
, PyrSlot
*slots
, int size
)
232 // First component: OSC Address Pattern.
233 // For convenience, we allow the user to omit the initial '/', when
234 // expressing it as a symbol (e.g. \g_new) - we add it back on here, for OSC compliance.
235 if(GetTag(slots
) == tagSym
&& slotRawSymbol(slots
)->name
[0]!='/'){
236 packet
->adds_slpre(slotRawSymbol(slots
)->name
);
238 int error
= addMsgSlot(packet
, slots
);
239 if (error
!= errNone
)
243 // skip space for tags
244 packet
->maketags(size
);
249 for (int i
=1; i
<size
; ++i
) {
250 int error
= addMsgSlotWithTags(packet
, slots
+i
);
251 if (error
!= errNone
)
254 } catch (std::runtime_error
& e
) {
255 error("makeSynthMsgWithTags: %s\n", e
.what());
264 void PerformOSCBundle(int inSize
, char *inData
, PyrObject
*inReply
, int inPortNum
);
265 void PerformOSCMessage(int inSize
, char *inData
, PyrObject
*inReply
, int inPortNum
);
266 PyrObject
* ConvertReplyAddress(ReplyAddress
*inReply
);
268 void localServerReplyFunc(struct ReplyAddress
*inReplyAddr
, char* inBuf
, int inSize
);
269 void localServerReplyFunc(struct ReplyAddress
*inReplyAddr
, char* inBuf
, int inSize
)
271 bool isBundle
= IsBundle(inBuf
);
273 pthread_mutex_lock (&gLangMutex
);
275 PyrObject
*replyObj
= ConvertReplyAddress(inReplyAddr
);
277 PerformOSCBundle(inSize
, inBuf
, replyObj
, gUDPport
->RealPortNum());
279 PerformOSCMessage(inSize
, inBuf
, replyObj
, gUDPport
->RealPortNum());
282 pthread_mutex_unlock (&gLangMutex
);
286 int makeSynthBundle(big_scpacket
*packet
, PyrSlot
*slots
, int size
, bool useElapsed
)
292 err
= slotDoubleVal(slots
, &time
);
295 oscTime
= ElapsedTimeToOSC(time
);
297 oscTime
= (int64
)(time
* kSecondsToOSC
);
300 oscTime
= 1; // immediate
302 packet
->OpenBundle(oscTime
);
304 for (int i
=1; i
<size
; ++i
) {
305 if (isKindOfSlot(slots
+i
, class_array
)) {
306 PyrObject
*obj
= slotRawObject(&slots
[i
]);
307 int error
= makeSynthMsgWithTags(packet
, obj
->slots
, obj
->size
);
308 if (error
!= errNone
)
312 packet
->CloseBundle();
316 int netAddrSend(PyrObject
*netAddrObj
, int msglen
, char *bufptr
, bool sendMsgLen
=true);
317 int netAddrSend(PyrObject
*netAddrObj
, int msglen
, char *bufptr
, bool sendMsgLen
)
321 if (IsPtr(netAddrObj
->slots
+ ivxNetAddr_Socket
)) {
322 SC_TcpClientPort
* comPort
= (SC_TcpClientPort
*)slotRawPtr(netAddrObj
->slots
+ ivxNetAddr_Socket
);
325 int tcpSocket
= comPort
->Socket();
328 // send length of message in network byte-order
329 int32 sizebuf
= htonl(msglen
);
330 sendall(tcpSocket
, &sizebuf
, sizeof(int32
));
333 sendall(tcpSocket
, bufptr
, msglen
);
336 if (gUDPport
== 0) return errFailed
;
339 err
= slotIntVal(netAddrObj
->slots
+ ivxNetAddr_Hostaddr
, &addr
);
343 #ifndef NO_INTERNAL_SERVER
344 if (gInternalSynthServer
.mWorld
) {
345 World_SendPacket(gInternalSynthServer
.mWorld
, msglen
, bufptr
, &localServerReplyFunc
);
351 err
= slotIntVal(netAddrObj
->slots
+ ivxNetAddr_PortID
, &port
);
354 struct sockaddr_in toaddr
;
355 makeSockAddr(toaddr
, addr
, port
);
357 sendallto(gUDPport
->Socket(), bufptr
, msglen
, (sockaddr
*)&toaddr
, sizeof(toaddr
));
366 inline int OSCStrLen(char *str
)
368 return (strlen(str
) + 4) & ~3;
372 int makeSynthBundle(big_scpacket
*packet
, PyrSlot
*slots
, int size
, bool useElapsed
);
374 static void netAddrTcpClientNotifyFunc(void *clientData
);
375 void netAddrTcpClientNotifyFunc(void *clientData
)
377 extern bool compiledOK
;
379 pthread_mutex_lock(&gLangMutex
);
381 PyrObject
* netAddrObj
= (PyrObject
*)clientData
;
382 VMGlobals
* g
= gMainVMGlobals
;
383 g
->canCallOS
= false;
384 ++g
->sp
; SetObject(g
->sp
, netAddrObj
);
385 runInterpreter(g
, getsym("prConnectionClosed"), 1);
386 g
->canCallOS
= false;
388 pthread_mutex_unlock(&gLangMutex
);
391 int prNetAddr_Connect(VMGlobals
*g
, int numArgsPushed
);
392 int prNetAddr_Connect(VMGlobals
*g
, int numArgsPushed
)
394 PyrSlot
* netAddrSlot
= g
->sp
;
395 PyrObject
* netAddrObj
= slotRawObject(netAddrSlot
);
399 err
= slotIntVal(netAddrObj
->slots
+ ivxNetAddr_PortID
, &port
);
402 err
= slotIntVal(netAddrObj
->slots
+ ivxNetAddr_Hostaddr
, &addr
);
405 struct sockaddr_in toaddr
;
406 makeSockAddr(toaddr
, addr
, port
);
408 int aSocket
= socket(AF_INET
, SOCK_STREAM
, IPPROTO_TCP
);
410 //post("\nCould not create socket\n");
416 if (setsockopt( aSocket
, IPPROTO_TCP
, TCP_NODELAY
, (const char*)&on
, sizeof(on
)) != 0) {
418 if (setsockopt( aSocket
, IPPROTO_TCP
, TCP_NODELAY
, &on
, sizeof(on
)) != 0) {
420 //post("\nCould not setsockopt TCP_NODELAY\n");
422 closesocket(aSocket
);
430 if(connect(aSocket
,(struct sockaddr
*)&toaddr
,sizeof(toaddr
)) != 0)
432 //post("\nCould not connect socket\n");
434 closesocket(aSocket
);
441 SC_TcpClientPort
*comPort
= new SC_TcpClientPort(aSocket
, netAddrTcpClientNotifyFunc
, netAddrObj
);
442 SetPtr(netAddrObj
->slots
+ ivxNetAddr_Socket
, comPort
);
447 int prNetAddr_Disconnect(VMGlobals
*g
, int numArgsPushed
);
448 int prNetAddr_Disconnect(VMGlobals
*g
, int numArgsPushed
)
450 PyrSlot
* netAddrSlot
= g
->sp
;
451 PyrObject
* netAddrObj
= slotRawObject(netAddrSlot
);
453 SC_TcpClientPort
*comPort
= (SC_TcpClientPort
*)slotRawPtr(netAddrObj
->slots
+ ivxNetAddr_Socket
);
454 if (comPort
) comPort
->Close();
460 int prNetAddr_SendMsg(VMGlobals
*g
, int numArgsPushed
);
461 int prNetAddr_SendMsg(VMGlobals
*g
, int numArgsPushed
)
463 PyrSlot
* netAddrSlot
= g
->sp
- numArgsPushed
+ 1;
464 PyrSlot
* args
= netAddrSlot
+ 1;
467 int numargs
= numArgsPushed
- 1;
468 int error
= makeSynthMsgWithTags(&packet
, args
, numargs
);
469 if (error
!= errNone
)
472 //for (int i=0; i<packet.size()/4; i++) post("%d %p\n", i, packet.buf[i]);
474 return netAddrSend(slotRawObject(netAddrSlot
), packet
.size(), (char*)packet
.buf
);
478 int prNetAddr_SendBundle(VMGlobals
*g
, int numArgsPushed
);
479 int prNetAddr_SendBundle(VMGlobals
*g
, int numArgsPushed
)
481 PyrSlot
* netAddrSlot
= g
->sp
- numArgsPushed
+ 1;
482 PyrSlot
* args
= netAddrSlot
+ 1;
486 int err
= slotDoubleVal(args
, &time
);
488 time
+= slotRawFloat(&g
->thread
->seconds
);
489 SetFloat(args
, time
);
491 int numargs
= numArgsPushed
- 1;
492 makeSynthBundle(&packet
, args
, numargs
, true);
494 //for (int i=0; i<packet.size()/4; i++) post("%d %p\n", i, packet.buf[i]);
496 return netAddrSend(slotRawObject(netAddrSlot
), packet
.size(), (char*)packet
.buf
);
499 int prNetAddr_SendRaw(VMGlobals
*g
, int numArgsPushed
);
500 int prNetAddr_SendRaw(VMGlobals
*g
, int numArgsPushed
)
502 PyrSlot
* netAddrSlot
= g
->sp
- 1;
503 PyrSlot
* arraySlot
= g
->sp
;
504 PyrObject
* netAddrObj
= slotRawObject(netAddrSlot
);
506 if (!IsObj(arraySlot
) || !isKindOf(slotRawObject(arraySlot
), class_rawarray
)) {
507 error("sendRaw arg must be a kind of RawArray.\n");
510 PyrObject
*array
= slotRawObject(arraySlot
);
512 char *bufptr
= (char*)array
->slots
;
513 int32 msglen
= array
->size
* gFormatElemSize
[array
->obj_format
];
515 return netAddrSend(netAddrObj
, msglen
, bufptr
, false);
518 int prNetAddr_GetBroadcastFlag(VMGlobals
*g
, int numArgsPushed
);
519 int prNetAddr_GetBroadcastFlag(VMGlobals
*g
, int numArgsPushed
)
521 if (gUDPport
== 0) return errFailed
;
523 socklen_t optlen
= sizeof(opt
);
525 if (getsockopt(gUDPport
->Socket(), SOL_SOCKET
, SO_BROADCAST
, (char *)&opt
, &optlen
) == -1)
527 if (getsockopt(gUDPport
->Socket(), SOL_SOCKET
, SO_BROADCAST
, &opt
, &optlen
) == -1)
534 int prNetAddr_SetBroadcastFlag(VMGlobals
*g
, int numArgsPushed
);
535 int prNetAddr_SetBroadcastFlag(VMGlobals
*g
, int numArgsPushed
)
537 if (gUDPport
== 0) return errFailed
;
538 int opt
= IsTrue(g
->sp
);
540 if (setsockopt(gUDPport
->Socket(), SOL_SOCKET
, SO_BROADCAST
, (char *)&opt
, sizeof(opt
)) == -1)
542 if (setsockopt(gUDPport
->Socket(), SOL_SOCKET
, SO_BROADCAST
, &opt
, sizeof(opt
)) == -1)
548 int prNetAddr_BundleSize(VMGlobals
*g
, int numArgsPushed
);
549 int prNetAddr_BundleSize(VMGlobals
*g
, int numArgsPushed
)
551 PyrSlot
* args
= g
->sp
;
553 int numargs
= slotRawObject(args
)->size
;
554 if (numargs
< 1) return errFailed
;
555 makeSynthBundle(&packet
, slotRawObject(args
)->slots
, numargs
, true);
556 SetInt(args
, packet
.size());
560 int prNetAddr_MsgSize(VMGlobals
*g
, int numArgsPushed
);
561 int prNetAddr_MsgSize(VMGlobals
*g
, int numArgsPushed
)
563 PyrSlot
* args
= g
->sp
;
566 int numargs
= slotRawObject(args
)->size
;
567 if (numargs
< 1) return errFailed
;
568 int error
= makeSynthMsgWithTags(&packet
, slotRawObject(args
)->slots
, numargs
);
569 if (error
!= errNone
)
572 SetInt(args
, packet
.size());
577 int prNetAddr_UseDoubles(VMGlobals
*g
, int numArgsPushed
);
578 int prNetAddr_UseDoubles(VMGlobals
*g
, int numArgsPushed
)
580 //PyrSlot* netAddrSlot = g->sp - 1;
581 PyrSlot
* flag
= g
->sp
;
583 gUseDoubles
= IsTrue(flag
);
588 int prArray_OSCBytes(VMGlobals
*g
, int numArgsPushed
);
589 int prArray_OSCBytes(VMGlobals
*g
, int numArgsPushed
)
592 PyrObject
*array
= slotRawObject(a
);
593 PyrSlot
* args
= array
->slots
;
594 int numargs
= array
->size
;
595 if (numargs
< 1) return errFailed
;
598 if (IsFloat(args
) || IsNil(args
) || IsInt(args
)) {
599 makeSynthBundle(&packet
, args
, numargs
, false);
600 } else if (IsSym(args
) || isKindOfSlot(args
, class_string
)) {
601 int error
= makeSynthMsgWithTags(&packet
, args
, numargs
);
602 if (error
!= errNone
)
608 int size
= packet
.size();
609 PyrInt8Array
* obj
= newPyrInt8Array(g
->gc
, size
, 0, true);
611 memcpy(obj
->b
, packet
.data(), size
);
612 SetObject(a
, (PyrObject
*)obj
);
613 //for (int i=0; i<packet.size()/4; i++) post("%d %p\n", i, packet.buf[i]);
618 // Create a new <PyrInt8Array> object and copy data from `msg.getb'.
619 // Bytes are properly untyped, but there is no <UInt8Array> type.
621 static PyrInt8Array
* MsgToInt8Array ( sc_msg_iter msg
) ;
622 static PyrInt8Array
* MsgToInt8Array ( sc_msg_iter msg
)
624 int size
= msg
.getbsize() ;
625 VMGlobals
*g
= gMainVMGlobals
;
626 PyrInt8Array
*obj
= newPyrInt8Array ( g
->gc
, size
, 0 , true ) ;
628 msg
.getb ( (char *)obj
->b
, obj
->size
) ;
632 PyrObject
* ConvertOSCMessage(int inSize
, char *inData
)
634 char *cmdName
= inData
;
635 int cmdNameLen
= OSCstrlen(cmdName
);
636 sc_msg_iter
msg(inSize
- cmdNameLen
, inData
+ cmdNameLen
);
639 if (inSize
== cmdNameLen
) {
644 error("OSC messages must have type tags. %s\n", cmdName
);
646 numElems
= strlen(msg
.tags
);
649 //post("tags %s %d\n", msg.tags, numElems);
651 VMGlobals
*g
= gMainVMGlobals
;
652 PyrObject
*obj
= newPyrArray(g
->gc
, numElems
+ 1, 0, false);
653 PyrSlot
*slots
= obj
->slots
;
655 SetSymbol(slots
+0, getsym(cmdName
));
657 for (int i
=0; i
<numElems
; ++i
) {
658 char tag
= msg
.nextTag();
659 //post("%d %c\n", i, tag);
662 SetInt(slots
+i
+1, msg
.geti());
665 SetFloat(slots
+i
+1, msg
.getf());
668 SetFloat(slots
+i
+1, msg
.getd());
671 SetSymbol(slots
+i
+1, getsym(msg
.gets()));
672 //post("sym '%s'\n", slots[i+1].us->name);
675 SetObject(slots
+i
+1, (PyrObject
*)MsgToInt8Array(msg
));
678 SetChar(slots
+i
+1, (char)msg
.geti());
680 // else add the type tag as a char (jrhb 2009)
682 SetChar(slots
+i
+1, tag
);
686 obj
->size
= numElems
+ 1;
690 PyrObject
* ConvertReplyAddress(ReplyAddress
*inReply
)
692 VMGlobals
*g
= gMainVMGlobals
;
693 PyrObject
*obj
= instantiateObject(g
->gc
, s_netaddr
->u
.classobj
, 2, true, false);
694 PyrSlot
*slots
= obj
->slots
;
695 SetInt(slots
+0, ntohl(inReply
->mSockAddr
.sin_addr
.s_addr
));
696 SetInt(slots
+1, ntohs(inReply
->mSockAddr
.sin_port
));
700 void PerformOSCBundle(int inSize
, char* inData
, PyrObject
*replyObj
, int inPortNum
)
702 // convert all data to arrays
704 int64 oscTime
= OSCtime(inData
+ 8);
705 double seconds
= OSCToElapsedTime(oscTime
);
707 VMGlobals
*g
= gMainVMGlobals
;
708 ++g
->sp
; SetObject(g
->sp
, g
->process
);
709 ++g
->sp
; SetFloat(g
->sp
, seconds
);
710 ++g
->sp
; SetObject(g
->sp
, replyObj
);
711 ++g
->sp
; SetInt(g
->sp
, inPortNum
);
713 PyrSlot
*stackBase
= g
->sp
;
714 char *data
= inData
+ 16;
715 char* dataEnd
= inData
+ inSize
;
716 while (data
< dataEnd
) {
717 int32 msgSize
= OSCint(data
);
718 data
+= sizeof(int32
);
719 PyrObject
*arrayObj
= ConvertOSCMessage(msgSize
, data
);
720 ++g
->sp
; SetObject(g
->sp
, arrayObj
);
724 int numMsgs
= g
->sp
- stackBase
;
726 runInterpreter(g
, s_recvoscbndl
, 4+numMsgs
);
729 void ConvertOSCBundle(int inSize
, char* inData
, PyrObject
*replyObj
)
731 // convert all data to arrays
733 //int64 oscTime = OSCtime(inData + 8);
734 //double seconds = OSCToElapsedTime(oscTime);
736 VMGlobals
*g
= gMainVMGlobals
;
739 char *data
= inData
+ 16;
740 char* dataEnd
= inData
+ inSize
;
741 while (data
< dataEnd
) {
742 int32 msgSize
= OSCint(data
);
743 data
+= sizeof(int32
);
744 PyrObject
*arrayObj
= ConvertOSCMessage(msgSize
, data
);
745 ++g
->sp
; SetObject(g
->sp
, arrayObj
);
751 void PerformOSCMessage(int inSize
, char *inData
, PyrObject
*replyObj
, int inPortNum
)
754 PyrObject
*arrayObj
= ConvertOSCMessage(inSize
, inData
);
756 // call virtual machine to handle message
757 VMGlobals
*g
= gMainVMGlobals
;
758 ++g
->sp
; SetObject(g
->sp
, g
->process
);
759 ++g
->sp
; SetFloat(g
->sp
, elapsedTime()); // time
760 ++g
->sp
; SetObject(g
->sp
, replyObj
);
761 ++g
->sp
; SetInt(g
->sp
, inPortNum
);
762 ++g
->sp
; SetObject(g
->sp
, arrayObj
);
764 runInterpreter(g
, s_recvoscmsg
, 5);
769 void FreeOSCPacket(OSC_Packet
*inPacket
)
771 //post("->FreeOSCPacket %p\n", inPacket);
773 free(inPacket
->mData
);
778 void ProcessOSCPacket(OSC_Packet
* inPacket
, int inPortNum
)
780 //post("recv '%s' %d\n", inPacket->mData, inPacket->mSize);
781 inPacket
->mIsBundle
= IsBundle(inPacket
->mData
);
783 pthread_mutex_lock (&gLangMutex
);
785 PyrObject
*replyObj
= ConvertReplyAddress(&inPacket
->mReplyAddr
);
787 if (inPacket
->mIsBundle
) {
788 PerformOSCBundle(inPacket
->mSize
, inPacket
->mData
, replyObj
, inPortNum
);
790 PerformOSCMessage(inPacket
->mSize
, inPacket
->mData
, replyObj
, inPortNum
);
794 pthread_mutex_unlock (&gLangMutex
);
796 FreeOSCPacket(inPacket
);
799 void init_OSC(int port
);
800 void init_OSC(int port
)
802 postfl("init_OSC\n");
807 if ((nCode
= WSAStartup(MAKEWORD(1, 1), &wsaData
)) != 0) {
808 error( "sclang: init_OSC: WSAStartup() failed with error code %d.\n", nCode
);
813 gUDPport
= new SC_UdpInPort(port
);
815 postfl("No networking.");
819 int prOpenUDPPort(VMGlobals
*g
, int numArgsPushed
);
820 int prOpenUDPPort(VMGlobals
*g
, int numArgsPushed
)
822 PyrSlot
*a
= g
->sp
- 1;
825 int err
= slotIntVal(b
, &port
);
828 SC_UdpCustomInPort
* newUDPport
;
832 newUDPport
= new SC_UdpCustomInPort(port
);
833 gCustomUdpPorts
.push_back(newUDPport
);
836 postfl("Could not bind to requested port. This may mean it is in use already by another application.\n");
841 void closeAllCustomPorts();
842 void closeAllCustomPorts()
844 // close all custom sockets
845 if(gCustomUdpPorts
.empty()) postfl("empty\n");
846 for(int i
=0; i
<gCustomUdpPorts
.size(); i
++){
847 delete gCustomUdpPorts
[i
];
849 gCustomUdpPorts
.clear();
854 postfl( "cleaning up OSC\n");
860 int prGetHostByName(VMGlobals
*g
, int numArgsPushed
);
861 int prGetHostByName(VMGlobals
*g
, int numArgsPushed
)
866 int err
= slotStrVal(a
, hostname
, 255);
869 struct hostent
*he
= gethostbyname(hostname
);
872 int err
= WSAGetLastError();
873 error("gethostbyname(\"%s\") failed with error code %i.\n",
879 SetInt(a
, ntohl(*(int*)he
->h_addr
));
884 int prGetLangPort(VMGlobals
*g
, int numArgsPushed
);
885 int prGetLangPort(VMGlobals
*g
, int numArgsPushed
)
888 if (!gUDPport
) return errFailed
;
889 SetInt(a
, gUDPport
->RealPortNum());
893 int prExit(VMGlobals
*g
, int numArgsPushed
);
894 int prExit(VMGlobals
*g
, int numArgsPushed
)
900 //post("exit %d\n", slotRawInt(a));
906 int vpost(const char *fmt
, va_list vargs
);
909 #ifndef NO_INTERNAL_SERVER
910 int prBootInProcessServer(VMGlobals
*g
, int numArgsPushed
);
911 int prBootInProcessServer(VMGlobals
*g
, int numArgsPushed
)
915 if (!gInternalSynthServer
.mWorld
) {
916 SetPrintFunc(&vpost
);
917 WorldOptions options
= kDefaultWorldOptions
;
919 PyrObject
*optionsObj
= slotRawObject(a
);
920 PyrSlot
*optionsSlots
= optionsObj
->slots
;
922 static char mInputStreamsEnabled
[512], mOutputStreamsEnabled
[512], mDeviceName
[512];
925 err
= slotIntVal(optionsSlots
+ 0, (int*)&options
.mNumAudioBusChannels
);
928 err
= slotIntVal(optionsSlots
+ 1, (int*)&options
.mNumControlBusChannels
);
931 err
= slotIntVal(optionsSlots
+ 2, (int*)&options
.mNumInputBusChannels
);
934 err
= slotIntVal(optionsSlots
+ 3, (int*)&options
.mNumOutputBusChannels
);
937 err
= slotIntVal(optionsSlots
+ 4, (int*)&options
.mNumBuffers
);
940 err
= slotIntVal(optionsSlots
+ 5, (int*)&options
.mMaxNodes
);
943 err
= slotIntVal(optionsSlots
+ 6, (int*)&options
.mMaxGraphDefs
);
946 err
= slotIntVal(optionsSlots
+ 8, (int*)&options
.mBufLength
);
949 if (NotNil(optionsSlots
+ 9)) {
950 err
= slotIntVal(optionsSlots
+ 9, (int*)&options
.mPreferredHardwareBufferFrameSize
);
954 err
= slotIntVal(optionsSlots
+ 10, (int*)&options
.mRealTimeMemorySize
);
957 err
= slotIntVal(optionsSlots
+ 11, (int*)&options
.mNumRGens
);
960 err
= slotIntVal(optionsSlots
+ 12, (int*)&options
.mMaxWireBufs
);
963 if (NotNil(optionsSlots
+ 13)) {
964 err
= slotIntVal(optionsSlots
+ 13, (int*)&options
.mPreferredSampleRate
);
968 options
.mLoadGraphDefs
= IsTrue(optionsSlots
+ 14) ? 1 : 0;
971 err
= slotStrVal(optionsSlots
+15, mInputStreamsEnabled
, 512);
972 if(err
) options
.mInputStreamsEnabled
= NULL
;
973 else options
.mInputStreamsEnabled
= mInputStreamsEnabled
;
975 err
= slotStrVal(optionsSlots
+16, mOutputStreamsEnabled
, 512);
976 if(err
) options
.mOutputStreamsEnabled
= NULL
;
977 else options
.mOutputStreamsEnabled
= mOutputStreamsEnabled
;
980 err
= slotStrVal(optionsSlots
+17, mDeviceName
, 512);
981 if(err
) options
.mInDeviceName
= options
.mOutDeviceName
= NULL
;
982 else options
.mInDeviceName
= options
.mOutDeviceName
= mDeviceName
;
984 options
.mNumSharedControls
= gInternalSynthServer
.mNumSharedControls
;
985 options
.mSharedControls
= gInternalSynthServer
.mSharedControls
;
987 // internal servers use the PID to identify the shared memory region
988 #if defined(SC_IPHONE)
989 options
.mSharedMemoryID
= 0;
990 #elif !defined(_WIN32)
991 options
.mSharedMemoryID
= getpid();
993 options
.mSharedMemoryID
= GetCurrentProcessId()
996 gInternalSynthServer
.mWorld
= World_New(&options
);
1002 int getScopeBuf(uint32 index
, SndBuf
*buf
, bool& didChange
)
1004 if (gInternalSynthServer
.mWorld
) {
1005 int serverErr
= World_CopySndBuf(gInternalSynthServer
.mWorld
, index
, buf
, true, &didChange
);
1006 if (serverErr
) return errFailed
;
1012 void* wait_for_quit(void* thing
);
1013 void* wait_for_quit(void* thing
)
1015 World
*world
= (World
*)thing
;
1016 World_WaitForQuit(world
);
1020 int prQuitInProcessServer(VMGlobals
*g
, int numArgsPushed
);
1021 int prQuitInProcessServer(VMGlobals
*g
, int numArgsPushed
)
1023 //PyrSlot *a = g->sp;
1025 if (gInternalSynthServer
.mWorld
) {
1026 World
*world
= gInternalSynthServer
.mWorld
;
1027 gInternalSynthServer
.mWorld
= 0;
1030 pthread_create(&thread
, NULL
, wait_for_quit
, (void*)world
);
1031 pthread_detach(thread
);
1037 int prQuitInProcessServer(VMGlobals
*g
, int numArgsPushed
);
1038 int prQuitInProcessServer(VMGlobals
*g
, int numArgsPushed
)
1040 // no-op. Better to have this than to overwrite in lang.
1046 inline int32
BUFMASK(int32 x
)
1048 return (1 << (31 - CLZ(x
))) - 1;
1051 int prAllocSharedControls(VMGlobals
*g
, int numArgsPushed
);
1052 int prAllocSharedControls(VMGlobals
*g
, int numArgsPushed
)
1054 //PyrSlot *a = g->sp - 1;
1057 if (gInternalSynthServer
.mWorld
) {
1058 post("can't allocate while internal server is running\n");
1061 if (gInternalSynthServer
.mSharedControls
!= gDefaultSharedControls
) {
1062 free(gInternalSynthServer
.mSharedControls
);
1063 gInternalSynthServer
.mSharedControls
= gDefaultSharedControls
;
1065 int numSharedControls
;
1066 int err
= slotIntVal(b
, &numSharedControls
);
1067 if (err
) return err
;
1068 if (numSharedControls
<= 0) {
1069 gInternalSynthServer
.mNumSharedControls
= 0;
1070 } else if (numSharedControls
< kNumDefaultSharedControls
) {
1071 gInternalSynthServer
.mNumSharedControls
= numSharedControls
;
1073 gInternalSynthServer
.mNumSharedControls
= numSharedControls
;
1074 gInternalSynthServer
.mSharedControls
= (float*)calloc(numSharedControls
, sizeof(float));
1080 int prGetSharedControl(VMGlobals
*g
, int numArgsPushed
);
1081 int prGetSharedControl(VMGlobals
*g
, int numArgsPushed
)
1083 PyrSlot
*a
= g
->sp
- 1;
1087 int err
= slotIntVal(b
, &index
);
1088 if (err
) return err
;
1089 if (index
< 0 || index
>= gInternalSynthServer
.mNumSharedControls
) {
1093 float val
= gInternalSynthServer
.mSharedControls
[index
];
1098 int prSetSharedControl(VMGlobals
*g
, int numArgsPushed
);
1099 int prSetSharedControl(VMGlobals
*g
, int numArgsPushed
)
1101 //PyrSlot *a = g->sp - 2;
1102 PyrSlot
*b
= g
->sp
- 1;
1106 int err
= slotIntVal(b
, &index
);
1107 if (err
) return err
;
1110 err
= slotFloatVal(c
, &val
);
1111 if (err
) return err
;
1113 if (index
< 0 || index
>= gInternalSynthServer
.mNumSharedControls
) {
1116 gInternalSynthServer
.mSharedControls
[index
] = val
;
1120 static int disconnectSharedMem(VMGlobals
*g
, PyrObject
* object
)
1123 PyrSlot
* ptrSlot
= object
->slots
+ ptrIndex
;
1126 // already disconnected
1129 assert(IsPtr(ptrSlot
));
1131 server_shared_memory_client
* client
= (server_shared_memory_client
*)slotRawPtr(ptrSlot
);
1137 int prConnectSharedMem(VMGlobals
*g
, int numArgsPushed
)
1139 PyrSlot
*a
= g
->sp
- 1;
1144 PyrObject
* self
= slotRawObject(a
);
1145 int portNumber
= slotRawInt(b
);
1148 int finalizerIndex
= 1;
1151 server_shared_memory_client
* client
= new server_shared_memory_client(portNumber
);
1152 SetPtr(self
->slots
+ ptrIndex
, client
);
1154 InstallFinalizer(g
, self
, finalizerIndex
, disconnectSharedMem
);
1156 postfl("Shared memory server interface initialized\n");
1157 } catch (std::exception
& e
) {
1158 postfl("Cannot connect to shared memory: %s\n", e
.what());
1165 int prDisconnectSharedMem(VMGlobals
*g
, int numArgsPushed
)
1170 PyrObject
* self
= slotRawObject(a
);
1171 return disconnectSharedMem(g
, self
);
1174 int prGetControlBusValue(VMGlobals
*g
, int numArgsPushed
)
1176 PyrSlot
*a
= g
->sp
- 1;
1180 PyrObject
* self
= slotRawObject(a
);
1182 PyrSlot
* ptrSlot
= self
->slots
+ ptrIndex
;
1183 if (NotPtr(ptrSlot
))
1189 int busIndex
= slotRawInt(b
);
1191 if (NotPtr(ptrSlot
))
1194 server_shared_memory_client
* client
= (server_shared_memory_client
*)slotRawPtr(ptrSlot
);
1196 float value
= client
->get_control_busses()[busIndex
];
1201 int prGetControlBusValues(VMGlobals
*g
, int numArgsPushed
)
1203 PyrSlot
*a
= g
->sp
- 2;
1204 PyrSlot
*b
= g
->sp
- 1;
1208 PyrObject
* self
= slotRawObject(a
);
1210 PyrSlot
* ptrSlot
= self
->slots
+ ptrIndex
;
1211 if (NotPtr(ptrSlot
))
1217 int busIndex
= slotRawInt(b
);
1222 int numberOfChannels
= slotRawInt(c
);
1224 server_shared_memory_client
* client
= (server_shared_memory_client
*)slotRawPtr(ptrSlot
);
1226 PyrObject
* ret
= newPyrArray(g
->gc
, numberOfChannels
, 0, 1);
1227 ret
->size
= numberOfChannels
;
1229 for (int i
= 0; i
!= numberOfChannels
; ++i
) {
1230 float value
= client
->get_control_busses()[busIndex
+ i
];
1231 SetFloat(ret
->slots
+i
, value
);
1238 int prSetControlBusValue(VMGlobals
*g
, int numArgsPushed
)
1240 PyrSlot
*a
= g
->sp
- 2;
1241 PyrSlot
*b
= g
->sp
- 1;
1245 PyrObject
* self
= slotRawObject(a
);
1247 PyrSlot
* ptrSlot
= self
->slots
+ ptrIndex
;
1248 if (NotPtr(ptrSlot
))
1254 int busIndex
= slotRawInt(b
);
1256 if (NotPtr(ptrSlot
))
1260 int error
= slotFloatVal(c
, &value
);
1261 if (error
!= errNone
)
1264 server_shared_memory_client
* client
= (server_shared_memory_client
*)slotRawPtr(ptrSlot
);
1266 client
->get_control_busses()[busIndex
] = value
;
1270 int prSetControlBusValues(VMGlobals
*g
, int numArgsPushed
)
1272 PyrSlot
*a
= g
->sp
- 2;
1273 PyrSlot
*b
= g
->sp
- 1;
1277 PyrObject
* self
= slotRawObject(a
);
1279 PyrSlot
* ptrSlot
= self
->slots
+ ptrIndex
;
1280 if (NotPtr(ptrSlot
))
1286 int busIndex
= slotRawInt(b
);
1291 PyrObject
* values
= slotRawObject(c
);
1292 server_shared_memory_client
* client
= (server_shared_memory_client
*)slotRawPtr(ptrSlot
);
1293 float * control_busses
= client
->get_control_busses() + busIndex
;
1295 for (int i
= 0; i
!= values
->size
; ++i
) {
1297 int error
= slotFloatVal(values
->slots
+ i
, &value
);
1298 if (error
!= errNone
)
1301 control_busses
[i
] = value
;
1306 void init_OSC_primitives();
1307 void init_OSC_primitives()
1311 base
= nextPrimitiveIndex();
1314 definePrimitive(base
, index
++, "_NetAddr_Connect", prNetAddr_Connect
, 1, 0);
1315 definePrimitive(base
, index
++, "_NetAddr_Disconnect", prNetAddr_Disconnect
, 1, 0);
1316 definePrimitive(base
, index
++, "_NetAddr_SendMsg", prNetAddr_SendMsg
, 1, 1);
1317 definePrimitive(base
, index
++, "_NetAddr_SendBundle", prNetAddr_SendBundle
, 2, 1);
1318 definePrimitive(base
, index
++, "_NetAddr_SendRaw", prNetAddr_SendRaw
, 2, 0);
1319 definePrimitive(base
, index
++, "_NetAddr_GetBroadcastFlag", prNetAddr_GetBroadcastFlag
, 1, 0);
1320 definePrimitive(base
, index
++, "_NetAddr_SetBroadcastFlag", prNetAddr_SetBroadcastFlag
, 2, 0);
1321 definePrimitive(base
, index
++, "_NetAddr_BundleSize", prNetAddr_BundleSize
, 1, 0);
1322 definePrimitive(base
, index
++, "_NetAddr_MsgSize", prNetAddr_MsgSize
, 1, 0);
1324 definePrimitive(base
, index
++, "_NetAddr_UseDoubles", prNetAddr_UseDoubles
, 2, 0);
1325 definePrimitive(base
, index
++, "_Array_OSCBytes", prArray_OSCBytes
, 1, 0);
1326 definePrimitive(base
, index
++, "_GetHostByName", prGetHostByName
, 1, 0);
1327 definePrimitive(base
, index
++, "_GetLangPort", prGetLangPort
, 1, 0);
1328 definePrimitive(base
, index
++, "_Exit", prExit
, 1, 0);
1329 #ifndef NO_INTERNAL_SERVER
1330 definePrimitive(base
, index
++, "_BootInProcessServer", prBootInProcessServer
, 1, 0);
1332 definePrimitive(base
, index
++, "_QuitInProcessServer", prQuitInProcessServer
, 1, 0);
1333 definePrimitive(base
, index
++, "_AllocSharedControls", prAllocSharedControls
, 2, 0);
1334 definePrimitive(base
, index
++, "_SetSharedControl", prSetSharedControl
, 3, 0);
1335 definePrimitive(base
, index
++, "_GetSharedControl", prGetSharedControl
, 2, 0);
1336 definePrimitive(base
, index
++, "_OpenUDPPort", prOpenUDPPort
, 2, 0);
1338 // server shared memory interface
1339 definePrimitive(base
, index
++, "_ServerShmInterface_connectSharedMem", prConnectSharedMem
, 2, 0);
1340 definePrimitive(base
, index
++, "_ServerShmInterface_disconnectSharedMem", prDisconnectSharedMem
, 1, 0);
1341 definePrimitive(base
, index
++, "_ServerShmInterface_getControlBusValue", prGetControlBusValue
, 2, 0);
1342 definePrimitive(base
, index
++, "_ServerShmInterface_getControlBusValues", prGetControlBusValues
, 3, 0);
1344 definePrimitive(base
, index
++, "_ServerShmInterface_setControlBusValue", prSetControlBusValue
, 2, 0);
1345 definePrimitive(base
, index
++, "_ServerShmInterface_setControlBusValues", prSetControlBusValues
, 3, 0);
1347 //post("initOSCRecs###############\n");
1348 s_call
= getsym("call");
1349 s_write
= getsym("write");
1350 s_recvoscmsg
= getsym("recvOSCmessage");
1351 s_recvoscbndl
= getsym("recvOSCbundle");
1352 s_netaddr
= getsym("NetAddr");