40 struct OSCOutputStream
42 OSCOutputStream() noexcept {}
45 const void* getData()
const noexcept {
return output.getData(); }
48 size_t getDataSize()
const noexcept {
return output.getDataSize(); }
51 bool writeInt32 (
int32 value)
53 return output.writeIntBigEndian (value);
58 return output.writeInt64BigEndian (
int64 (value));
63 return output.writeFloatBigEndian (value);
66 bool writeString (
const String& value)
68 if (! output.writeString (value))
78 if (! (output.writeIntBigEndian ((
int) blob.getSize())
79 && output.write (blob.getData(), blob.getSize())))
87 bool writeColour (OSCColour colour)
89 return output.writeIntBigEndian ((
int32) colour.toInt32());
94 return output.writeInt64BigEndian (
int64 (timeTag.getRawTimeTag()));
99 return writeString (address.toString());
104 return writeString (
ap.toString());
109 output.writeByte (
',');
114 output.writeByte (
'\0');
124 switch (
arg.getType())
126 case OSCTypes::int32:
return writeInt32 (
arg.getInt32());
128 case OSCTypes::string:
return writeString (
arg.getString());
130 case OSCTypes::colour:
return writeColour (
arg.getColour());
147 for (
auto&
arg : msg)
153 for (
auto&
arg : msg)
162 if (! writeString (
"#bundle"))
168 for (
auto& element : bundle)
178 const int64 startPos = output.getPosition();
180 if (! writeInt32 (0))
183 if (element.isBundle())
194 const int64 endPos = output.getPosition();
197 return output.setPosition (startPos)
199 && output.setPosition (endPos);
203 MemoryOutputStream output;
215 ~Pimpl()
noexcept { disconnect(); }
227 if (socket->bindToPort (0))
252 bool send (
const OSCMessage& message,
const String& hostName,
int portNumber)
257 && sendOutputStream (
outStream, hostName, portNumber);
260 bool send (
const OSCBundle& bundle,
const String& hostName,
int portNumber)
265 && sendOutputStream (
outStream, hostName, portNumber);
268 bool send (
const OSCMessage& message) {
return send (message, targetHostName, targetPortNumber); }
269 bool send (
const OSCBundle& bundle) {
return send (bundle, targetHostName, targetPortNumber); }
273 bool sendOutputStream (OSCOutputStream&
outStream,
const String& hostName,
int portNumber)
275 if (socket !=
nullptr)
279 const int bytesWritten = socket->write (hostName, portNumber,
294 int targetPortNumber = 0;
314 return pimpl->connect (targetHostName, targetPortNumber);
319 return pimpl->connectToSocket (
socket, targetHostName, targetPortNumber);
324 return pimpl->disconnect();
346 void runTest()
override
348 beginTest (
"writing OSC addresses");
351 const char check[16] = {
'/',
't',
'e',
's',
't',
'/',
'f',
'a',
'd',
'e',
'r',
'7',
'\0',
'\0',
'\0',
'\0' };
353 OSCAddress address (
"/test/fader7");
354 expect (
outStream.writeAddress (address));
360 beginTest (
"writing OSC address patterns");
363 const char check[20] = {
'/',
'*',
'/',
'*',
'p',
'u',
't',
'/',
'f',
'a',
'd',
'e',
'r',
'[',
'0',
'-',
'9',
']',
'\0',
'\0' };
365 OSCAddressPattern
ap (
"/*/*put/fader[0-9]");
372 beginTest (
"writing OSC time tags");
375 const char check[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 };
383 beginTest (
"writing OSC type tag strings");
390 const char check[4] = {
',',
'\0',
'\0',
'\0' };
391 expect (
outStream.writeTypeTagString (list));
400 list.add (OSCTypes::int32);
401 list.add (OSCTypes::float32);
403 const char check[4] = {
',',
'i',
'f',
'\0' };
404 expect (
outStream.writeTypeTagString (list));
413 list.add (OSCTypes::blob);
414 list.add (OSCTypes::blob);
415 list.add (OSCTypes::string);
417 const char check[8] = {
',',
'b',
'b',
's',
'\0',
'\0',
'\0',
'\0' };
418 expect (
outStream.writeTypeTagString (list));
424 beginTest (
"writing OSC arguments");
434 const char testStringRepresentation[] = {
'H',
'e',
'l',
'l',
'o',
',',
' ',
'W',
'o',
'r',
'l',
'd',
'!',
'\0',
'\0',
'\0' };
438 const uint8 testBlobRepresentation[] = { 0x00, 0x00, 0x00, 0x05, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x00, 0x00, 0x00 };
476 expect (
testBlob.getSize() % 4 != 0);
489 beginTest (
"Writing strings with correct padding");
533 beginTest (
"Writing blobs with correct padding");
535 const char buffer[20] = {};
537 OSCArgument
with15Bytes (MemoryBlock (buffer, 15));
543 OSCArgument
with16Bytes (MemoryBlock (buffer, 16));
549 OSCArgument
with17Bytes (MemoryBlock (buffer, 17));
555 OSCArgument
with18Bytes (MemoryBlock (buffer, 18));
561 OSCArgument
with19Bytes (MemoryBlock (buffer, 19));
567 OSCArgument
with20Bytes (MemoryBlock (buffer, 20));
574 beginTest (
"Writing OSC messages.");
584 uint8 check[52] = {
'/',
't',
'e',
's',
't',
'\0',
'\0',
'\0',
585 ',',
'i',
'f',
's',
'b',
'\0',
'\0',
'\0',
586 0xFF, 0xFF, 0xF8, 0x21,
587 0x43, 0xAC, 0xCE, 0x66,
588 'H',
'e',
'l',
'l',
'o',
',',
' ',
'W',
'o',
'r',
'l',
'd',
'!',
'\0',
'\0',
'\0',
589 0x00, 0x00, 0x00, 0x05, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x00, 0x00, 0x00
594 OSCMessage msg (
"/test");
607 beginTest (
"Writing OSC bundle.");
617 '#',
'b',
'u',
'n',
'd',
'l',
'e',
'\0',
618 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
620 0x00, 0x00, 0x00, 0x34,
622 '/',
't',
'e',
's',
't',
'/',
'1',
'\0',
623 ',',
'i',
'f',
's',
'b',
'\0',
'\0',
'\0',
624 0xFF, 0xFF, 0xF8, 0x21,
625 0x43, 0xAC, 0xCE, 0x66,
626 'H',
'e',
'l',
'l',
'o',
',',
' ',
'W',
'o',
'r',
'l',
'd',
'!',
'\0',
'\0',
'\0',
627 0x00, 0x00, 0x00, 0x05, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x00, 0x00, 0x00,
629 0x00, 0x00, 0x00, 0x0C,
631 '/',
't',
'e',
's',
't',
'/',
'2',
'\0',
632 ',',
'\0',
'\0',
'\0',
634 0x00, 0x00, 0x00, 0x10,
636 '#',
'b',
'u',
'n',
'd',
'l',
'e',
'\0',
637 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01
644 OSCMessage
msg1 (
"/test/1");
649 bundle.addElement (
msg1);
651 OSCMessage
msg2 (
"/test/2");
652 bundle.addElement (
msg2);
675 void runTest()
override
677 beginTest (
"Empty OSC message");
681 OSCOutputStream output;
684 OSCInputStream input (output.getData(), output.getDataSize());
685 OSCMessage
inMessage = input.readMessage();
690 beginTest (
"OSC message with single argument");
694 OSCOutputStream output;
697 OSCInputStream input (output.getData(), output.getDataSize());
698 OSCMessage
inMessage = input.readMessage();
701 expectEquals (
inMessage[0].getInt32(), 42);
704 beginTest (
"OSC message with multiple arguments");
706 OSCMessage
outMessage (
"/test/four_args", 42, 0.5f, String (
"foo"), String (
"bar"));
708 OSCOutputStream output;
711 OSCInputStream input (output.getData(), output.getDataSize());
712 OSCMessage
inMessage = input.readMessage();
715 expectEquals (
inMessage[0].getInt32(), 42);
716 expectEquals (
inMessage[1].getFloat32(), 0.5f);
717 expectEquals (
inMessage[2].getString(), String (
"foo"));
718 expectEquals (
inMessage[3].getString(), String (
"bar"));
721 beginTest (
"Empty OSC bundle");
725 OSCOutputStream output;
728 OSCInputStream input (output.getData(), output.getDataSize());
729 OSCBundle
inBundle = input.readBundle();
734 beginTest (
"OSC bundle with single message");
740 OSCOutputStream output;
743 OSCInputStream input (output.getData(), output.getDataSize());
744 OSCBundle
inBundle = input.readBundle();
750 expectEquals (
inMessage.getAddressPattern().toString(), String (
"/test/one_arg"));
752 expectEquals (
inMessage[0].getInt32(), 42);
755 beginTest (
"OSC bundle with multiple messages");
759 OSCMessage
outMessage3 (
"/test/four_args", 42, 0.5f, String (
"foo"), String (
"bar"));
766 OSCOutputStream output;
769 OSCInputStream input (output.getData(), output.getDataSize());
770 OSCBundle
inBundle = input.readBundle();
777 expectEquals (
inMessage.getAddressPattern().toString(), String (
"/test/empty"));
783 expectEquals (
inMessage.getAddressPattern().toString(), String (
"/test/one_arg"));
785 expectEquals (
inMessage[0].getInt32(), 42);
790 expectEquals (
inMessage.getAddressPattern().toString(), String (
"/test/four_args"));
792 expectEquals (
inMessage[0].getInt32(), 42);
793 expectEquals (
inMessage[1].getFloat32(), 0.5f);
794 expectEquals (
inMessage[2].getString(), String (
"foo"));
795 expectEquals (
inMessage[3].getString(), String (
"bar"));
799 beginTest (
"OSC bundle containing another bundle");
807 OSCOutputStream output;
810 OSCInputStream input (output.getData(), output.getDataSize());
811 OSCBundle
inBundle = input.readBundle();
821 expectEquals (msg.getAddressPattern().toString(), String (
"/test/one_arg"));
822 expectEquals (msg.size(), 1);
823 expectEquals (msg[0].getInt32(), 42);
826 beginTest (
"OSC bundle containing multiple other bundles");
837 OSCOutputStream output;
840 OSCInputStream input (output.getData(), output.getDataSize());
841 OSCBundle
inBundle = input.readBundle();
853 expectEquals (msg.getAddressPattern().toString(), String (
"/test/empty"));
854 expectEquals (msg.size(), 0);
864 expectEquals (msg.getAddressPattern().toString(), String (
"/test/one_arg"));
865 expectEquals (msg.size(), 1);
866 expectEquals (msg[0].getInt32(), 42);
A wrapper for a datagram (UDP) socket.
bool connectToSocket(DatagramSocket &socket, const String &targetHostName, int targetPortNumber)
Uses an existing datagram socket for sending OSC packets to the specified target.
bool disconnect()
Disconnects from the currently used UDP port.
OSCSender()
Constructs a new OSCSender.
bool connect(const String &targetHostName, int targetPortNumber)
Connects to a datagram socket and prepares the socket for sending OSC packets to the specified target...
bool sendToIPAddress(const String &targetIPAddress, int targetPortNumber, const OSCMessage &message)
Sends an OSC message to a specific IP address and port.
bool send(const OSCMessage &message)
Sends an OSC message to the target.
Holds a pointer to an object which can optionally be deleted when this pointer goes out of scope.
This is a base class for classes that perform a unit test.
signed int int32
A platform-independent 32-bit signed integer type.
Array< OSCType > OSCTypeList
The type used for OSC type tag strings.
unsigned long long uint64
A platform-independent 64-bit unsigned integer type.
Type unalignedPointerCast(void *ptr) noexcept
Casts a pointer to another type via void*, which suppresses the cast-align warning which sometimes ar...
unsigned char uint8
A platform-independent 8-bit unsigned integer type.
long long int64
A platform-independent 64-bit integer type.