8void XSleep(
int ms) { usleep(ms?ms*1000:100); }
11OSCDevice::OSCDevice(
const char* dest,
int maxpacket,
int sendsleep, sockaddr_in* listen_addr)
13 mHasOutput = dest !=
nullptr;
14 mHasInput = listen_addr !=
nullptr;
16 memset(&mSendAddress, 0,
sizeof(mSendAddress));
17 mMaxMacketSize = maxpacket > 0 ? maxpacket : 1024;
18 mSendSleep = sendsleep >= 0 ? sendsleep : 10;
19 mSendSocket = socket(AF_INET, SOCK_DGRAM, 0);
21 if (mSendSocket == INVALID_SOCKET)
27 mReceiveAddress = *listen_addr;
29 setsockopt(mSendSocket, SOL_SOCKET, SO_BROADCAST, (
char*)&on,
sizeof(on));
30 if (!bind(mSendSocket, (
struct sockaddr*) & mReceiveAddress,
sizeof(
struct sockaddr)))
32 SET_SOCK_BLOCK(mSendSocket,
false);
36 closesocket(mSendSocket);
37 mSendSocket = INVALID_SOCKET;
42 mDestination.Set(dest);
46 char* p = strstr(tmp.Get(),
":");
52 if (!sendport) sendport = 8000;
54 mSendAddress.sin_family = AF_INET;
55 mSendAddress.sin_addr.s_addr = inet_addr(tmp.Get());
56 mSendAddress.sin_port = htons(sendport);
59 setsockopt(mSendSocket, SOL_SOCKET, SO_BROADCAST, (
char*)&on,
sizeof(on));
60 SET_SOCK_BLOCK(mSendSocket,
false);
64OSCDevice::~OSCDevice()
66 if (mSendSocket != INVALID_SOCKET)
68 shutdown(mSendSocket, SHUT_RDWR);
69 closesocket(mSendSocket);
70 mSendSocket = INVALID_SOCKET;
74void OSCDevice::RunInput()
76 if (mSendSocket == INVALID_SOCKET)
79 struct sockaddr* p = mDestination.GetLength() ? nullptr : (
struct sockaddr*) & mSendAddress;
85 socklen_t plen = (socklen_t)
sizeof(mSendAddress);
86 const int len = (int)recvfrom(mSendSocket, buf,
sizeof(buf), 0, p, p ? &plen :
nullptr);
91 OnMessage(1, (
const unsigned char*)buf, len);
95void OSCDevice::RunOutput()
97 static char hdr[16] = {
'#',
'b',
'u',
'n',
'd',
'l',
'e', 0, 0, 0, 0, 0, 1, 0, 0, 0 };
100 if (mSendQueue.Available() <= 16)
102 if (mSendQueue.Available() > 0) mSendQueue.Clear();
107 char* packetstart = (
char*)mSendQueue.Get();
109 bool hasbundle =
false;
110 mSendQueue.Advance(16);
112 SET_SOCK_BLOCK(mSendSocket,
true);
114 while (mSendQueue.Available() >=
sizeof(
int))
116 int len = *(
int*)mSendQueue.Get();
117 OSC_MAKEINTMEM4BE((
char*)&len);
119 if (len < 1 || len > MAX_OSC_MSG_LEN || len > mSendQueue.Available())
break;
121 if (packetlen > 16 && packetlen +
sizeof(
int) + len > mMaxMacketSize)
131 memcpy(packetstart, hdr, 16);
134 sendto(mSendSocket, packetstart, packetlen, 0, (
struct sockaddr*) & mSendAddress,
sizeof(mSendAddress));
138 packetstart = (
char*)mSendQueue.Get() - 16;
143 if (packetlen > 16) hasbundle =
true;
144 mSendQueue.Advance(
sizeof(
int) + len);
145 packetlen +=
sizeof(int) + len;
157 memcpy(packetstart, hdr, 16);
159 sendto(mSendSocket, packetstart, packetlen, 0, (
struct sockaddr*) & mSendAddress,
sizeof(mSendAddress));
163 SET_SOCK_BLOCK(mSendSocket,
false);
168void OSCDevice::AddInstance(
void(*callback)(
void* d1,
int dev_idx,
int msglen,
void* msg),
void* d1,
int dev_idx)
170 const rec r = { callback, d1, dev_idx };
174void OSCDevice::OnMessage(
char type,
const unsigned char* msg,
int len)
176 const int n = mInstances.GetSize();
177 const rec* r = mInstances.Get();
178 for (
int x = 0; x < n; x++)
179 if (r[x].callback) r[x].callback(r[x].data1, r[x].dev_idx, len, (
void*)msg);
182void OSCDevice::SendOSC(
const char* src,
int len)
184 if (!mSendQueue.GetSize())
185 mSendQueue.Add(
nullptr, 16);
188 OSC_MAKEINTMEM4BE(&tlen);
189 mSendQueue.Add(&tlen,
sizeof(tlen));
190 mSendQueue.Add(src, len);
194void OSCInterface::MessageCallback(
void* d1,
int dev_idx,
int len,
void* msg)
200 if (_this->mIncomingEvents.GetSize() < 65536 * 8)
202 const int this_sz = ((
sizeof(incomingEvent) + (len - 3)) + 7) & ~7;
204 _this->mIncomingEvents_mutex.Enter();
205 const int oldsz = _this->mIncomingEvents.GetSize();
206 _this->mIncomingEvents.Resize(oldsz + this_sz,
false);
208 if (_this->mIncomingEvents.GetSize() == oldsz + this_sz)
210 incomingEvent* item = (incomingEvent*)((
char*)_this->mIncomingEvents.Get() + oldsz);
211 item->dev_ptr = _this->mDevices.Get(dev_idx);
213 memcpy(item->msg, msg, len);
215 _this->mIncomingEvents_mutex.Leave();
220void OSCInterface::OnTimer(
Timer& timer)
223 const int nDevices = mDevices.GetSize();
225 for (
auto i = 0; i < nDevices; i++)
227 auto* pDev = mDevices.Get(i);
232 if (mIncomingEvents.GetSize())
236 mIncomingEvents_mutex.Enter();
237 tmp.CopyFrom(&mIncomingEvents,
false);
238 mIncomingEvents.Resize(0,
false);
239 mIncomingEvents_mutex.Leave();
242 const int endpos = tmp.GetSize();
243 while (pos < endpos + 1 -
sizeof(incomingEvent))
245 incomingEvent* evt = (incomingEvent*)((
char*)tmp.Get() + pos);
247 const int this_sz = ((
sizeof(incomingEvent) + (evt->sz - 3)) + 7) & ~7;
249 if (pos + this_sz > endpos)
break;
254 if (evt->sz > 20 && !strcmp((
char*)evt->msg,
"#bundle"))
256 rd_sz = *(
int*)(evt->msg + 16);
257 OSC_MAKEINTMEM4BE(&rd_sz);
261 while (rd_pos + rd_sz <= evt->sz && rd_sz >= 0)
265 const char* mstr = rmsg.GetMessage();
270 if (rd_pos >= evt->sz)
break;
272 rd_sz = *(
int*)(evt->msg + rd_pos - 4);
273 OSC_MAKEINTMEM4BE(&rd_sz);
278 for (
auto i = 0; i < nDevices; i++)
280 auto* pDev = mDevices.Get(i);
281 if (pDev->mHasOutput)
286OSCInterface::OSCInterface(OSCLogFunc logFunc)
289 JNL::open_socketlib();
292 mTimer = std::unique_ptr<Timer>(Timer::Create(std::bind(&OSCInterface::OnTimer,
this, std::placeholders::_1), OSC_TIMER_RATE));
295OSCInterface::~OSCInterface()
304 mDevices.Empty(
true);
311 int idx = mDevices.Find(device);
313 mDevices.Delete(idx,
true);
317OSCDevice* OSCInterface::CreateReceiver(WDL_String& log,
int port)
319 const char buf[] =
"127.0.0.1";
321 struct sockaddr_in addr;
322 addr.sin_addr.s_addr = INADDR_ANY;
323 addr.sin_family = AF_INET;
324 if (buf[0] && buf[0] !=
'*') addr.sin_addr.s_addr = inet_addr(buf);
325 if (addr.sin_addr.s_addr == INADDR_NONE) addr.sin_addr.s_addr = INADDR_ANY;
326 addr.sin_port = htons(port);
329 bool isReuse =
false;
331 for (
int x = 0; x < mDevices.GetSize(); x++)
334 if (dev && dev->mHasInput)
336 if (dev->mReceiveAddress.sin_port == addr.sin_port && dev->mReceiveAddress.sin_addr.s_addr == addr.sin_addr.s_addr)
341 log.AppendFormatted(1024,
"Attached to already-opened listener '%s:%i'\r\n", buf, port);
350 std::unique_ptr<OSCDevice> device(
new OSCDevice(
nullptr, 0, -1, &addr));
352 if (device->mSendSocket == INVALID_SOCKET)
354 log.AppendFormatted(1024,
"Error listening for '%s:%i'\r\n", buf, port);
358 r = device.release();
359 log.AppendFormatted(1024,
"Listening for OSC on '%s:%i'\r\n", buf, port);
365 r->AddInstance(MessageCallback,
this, mDevices.GetSize());
374OSCDevice* OSCInterface::CreateSender(WDL_String& log,
const char* ip,
int port)
377 destStr.SetFormatted(256,
"%s:%i", ip, port);
381 bool isReuse =
false;
382 for (
auto x = 0; x < mDevices.GetSize(); x++)
385 if (d && d->mHasOutput)
387 if (!strcmp(d->mDestination.Get(), destStr.Get()))
399 std::unique_ptr<OSCDevice> device(
new OSCDevice(destStr.Get(), 0, -1,
nullptr));
400 if (device->mSendSocket == INVALID_SOCKET)
402 log.AppendFormatted(1024,
"Warning: failed creating destination for output '%s'\n", destStr.Get());
406 r = device.release();
412 log.AppendFormatted(1024,
"Set destination: '%s'\n", destStr.Get());
414 r->AddInstance(MessageCallback,
this, mDevices.GetSize());
void RemoveDevice(OSCDevice *device)
Remove a device from the device list and delete it.