An Open Sound Control library for the mbed, created to be compatible with Recotana's OSCClass library (http://recotana.com) for the Arduino with Ethernet shield. It also uses parts of the OSC Transceiver(Sender/Receiver) code by xshige written by: Alvaro Cassinelli, October 2011 tweaked by: Toby Harris / *spark audio-visual, March 2012
Revision 0:fdea65150534, committed 2012-04-15
- Comitter:
- tobyspark
- Date:
- Sun Apr 15 15:50:42 2012 +0000
- Child:
- 1:63b72e393989
- Commit message:
- mbedOSC__spk as program to OSC as library
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/example-processing.h Sun Apr 15 15:50:42 2012 +0000 @@ -0,0 +1,52 @@ +/* EXAMPLE SEND/RECEIVE on PROCESSING: + +// oscP5sendreceive by andreas schlegel +// example shows how to send and receive osc messages. +// oscP5 website at http://www.sojamo.de/oscP5 + +*/ + +import oscP5.*; +import netP5.*; + +OscP5 oscP5; +NetAddress myRemoteLocation; + +void setup() { + size(400,400); + frameRate(25); + // start oscP5, listening for incoming messages at port 12000 + oscP5 = new OscP5(this,12000); + + // myRemoteLocation is a NetAddress. a NetAddress takes 2 parameters, + // an ip address and a port number. myRemoteLocation is used as parameter in + // oscP5.send() when sending osc packets to another computer, device, + // application. usage see below. for testing purposes the listening port + // and the port of the remote location address are the same, hence you will + // send messages back to this sketch. + myRemoteLocation = new NetAddress("10.0.0.2",10000); +} + + +void draw() { + background(0); +} + +void mousePressed() { + // in the following different ways of creating osc messages are shown by example + OscMessage myMessage = new OscMessage("/mbed/test1"); + + myMessage.add(123); // add an int to the osc message + + // send the message + oscP5.send(myMessage, myRemoteLocation); +} + + +// incoming osc message are forwarded to the oscEvent method. +void oscEvent(OscMessage theOscMessage) { + // print the address pattern and the typetag of the received OscMessage + print("### received an osc message."); + print(" addrpattern: "+theOscMessage.addrPattern()); + println(" typetag: "+theOscMessage.typetag()); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/example.h Sun Apr 15 15:50:42 2012 +0000 @@ -0,0 +1,117 @@ +#include "mbed.h" +#include "mbedOSC.h" + +//// ETHERNET + +// Ethernet can be created with *either* an address assigned by DHCP or a static IP address. Uncomment the define line for DHCP +//#define DHCP +#ifdef DHCP +EthernetNetIf eth; +#else +EthernetNetIf eth( + IpAddr(10,0,0,2), //IP Address + IpAddr(255,255,255,0), //Network Mask + IpAddr(10,0,0,1), //Gateway + IpAddr(10,0,0,1) //DNS +); +#endif + +//// OSC + +// The object to do the work of sending and receiving +OSCClass osc; + +// The message objects to send and receive with +OSCMessage recMes; +OSCMessage sendMes; + +// Setting - The port we're listening to on the mbed for OSC messages +int mbedListenPort = 10000; + +// Setting - The address and port we're going to send to, from the mbed +uint8_t destIp[] = { 10, 0, 0, 1}; +int destPort = 12000; + +//// mbed input + +DigitalIn button(p21); +bool buttonLastState; + +//// Our messageReceivedCallback function +void processOSC() { + + // If this function has been called, the OSC message just received will have been parsed into our recMes OSCMessage object + // Note we can access recMes here, outside of the main loop, as we created it as a global variable. + + // TASK: If this message one we want, do something about it. + // In this example we're listening for messages with a top address of "mbed". + // Note the strcmp function returns 0 if identical, so !strcmp is true if the two strings are the same + if ( !strcmp( recMes.getAddress(0) , "mbed" ) ) { + printf("OSC Message received addressed to mbed \r\n"); + if ( !strcmp( recMes.getAddress(1) , "test1" ) ) + printf("Received subAddress= test1 \r\n"); + + // Send some osc message: + sendMes.setTopAddress("/working..."); + osc.sendOsc(&sendMes); + } +} + +//// M A I N +int main() { + + //// TASK: Set up the Ethernet port + printf("Setting up ethernet...\r\n"); + EthernetErr ethErr = eth.setup(); + if (ethErr) { + printf("Ethernet Failed to setup. Error: %d\r\n", ethErr); + return -1; + } + printf("Ethernet OK\r\n"); + + //// TASK: Set up OSC message sending + + // In the OSC message container we've made for send messages, set where we want it to go: + sendMes.setIp( destIp ); + sendMes.setPort( destPort ); + + //// TASK: Set up OSC message receiving + + // In the OSC send/receive object... + // Set the OSC message container for it to parse received messages into + osc.setReceiveMessage(&recMes); + + // Tell it to begin listening for OSC messages at the port specified (the IP address we know already, it's the mbed's!). + osc.begin(mbedListenPort); + + // Rather than constantly checking to see whether there are new messages waiting, the object can call some code of ours to run when a message is received. + // This line does that, attaching a callback function we've written before getting to this point, in this case it's called processOSC + // For more info how this works, see http://mbed.org/cookbook/FunctionPointer + osc.messageReceivedCallback.attach(&processOSC); + + //// TASK: Prime button change detection + buttonLastState = button; + + //// TASK: GO! + + // We've finished setting up, now loop this forever... + while (true) { + // This polls the network connection for new activity, without keeping on calling this you won't receive any OSC! + Net::poll(); + + // Has the button changed? + if (button != buttonLastState) { + // If so, lets update the lastState variable and then send an OSC message + buttonLastState = button; + + sendMes.setTopAddress("/mbed"); + sendMes.setSubAddress("/button"); + sendMes.setArgs("i", (long)button); // The payload will be the button state as an integer, ie. 0 or 1. We need to cast to 'long' for ints (and 'double' for floats).// The payload will be the button state as an integer, ie. 0 or 1. We need to cast to 'long' for ints (and 'double' for floats). + osc.sendOsc(&sendMes); + + printf("Sent OSC message /mbed/button \r\n"); + } + + // ... Do whatever needs to be done by your mbed otherwise. If an OSC message is received, your messageReceivedCallback will run (in this case, processOSC()). + } +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbedOSC.cpp Sun Apr 15 15:50:42 2012 +0000 @@ -0,0 +1,403 @@ +/* + mbedOSC.cpp +*/ + +#include "mbed.h" +#include "mbedOSC.h" +#include "stdarg.h" + +OSCMessage::OSCMessage() { + // Initialize host address and port by default (as if this where the receiver message): + // host=new Host(IpAddr(10, 0, 0, 1), DEFAULT_RECEIVE_PORT, NULL); +} + +void OSCMessage::setPort(uint16_t _port){ + host.setPort(_port); +} + + +void OSCMessage::setIp(uint8_t *_ip){ + host.setIp(IpAddr(_ip[0], _ip[1], _ip[2], _ip[3])); +} + + + +void OSCMessage::setIp( uint8_t _ip1, + uint8_t _ip2, + uint8_t _ip3, + uint8_t _ip4 ){ + + host.setIp(IpAddr(_ip1, _ip2, _ip3, _ip4)); +} + +const IpAddr& OSCMessage::getIp(){ + return host.getIp(); +} + + + const int& OSCMessage::getPort(){ + return host.getPort(); +} + + + +uint8_t OSCMessage::getAddressNum(){ + + return addressNum; +} + + +uint8_t OSCMessage::getArgNum(){ + + return argNum; +} + + + +char * OSCMessage::getAddress(uint8_t _index){ + if(_index>MAX_ADDRESS) _index=MAX_ADDRESS-1; + return address[_index]; + +} + + + +char * OSCMessage::getTopAddress(){ + + return getAddress(0); + +} + + +char * OSCMessage::getSubAddress(){ + + return getAddress(1); + +} + + +char OSCMessage::getTypeTag(uint8_t _index){ + if(_index>MAX_ARG) _index=MAX_ARG-1; + return typeTag[_index]; +} + + +int32_t OSCMessage::getArgInt(uint8_t _index){ + int32_t *value; + if(_index > argNum) _index=argNum; + value = (int32_t *)arg[_index]; // cast to int32_t + return *value; +} + + +double OSCMessage::getArgFloat(uint8_t _index){ + double *value; + if(_index > argNum) _index=argNum; + value = (double *)arg[_index]; + return *value; +} + + +void OSCMessage::setTopAddress(char *_address){ + address[0]=_address; + address[1]=0; + addressNum=1; // Note: this "erases" the subaddress! (is this a good idea?) +} + + +void OSCMessage::setSubAddress(char *_address){ + address[1]=_address; + addressNum=2; // Note: this assumes the top address was already set! +} + + + +void OSCMessage::setAddress(char *_topAddress,char *_subAddress){ + setTopAddress(_topAddress); + setSubAddress(_subAddress); + addressNum=2; // (unnecessary...) +} + + +void OSCMessage::setAddress(uint8_t _index, char *_address){ + if(_index>MAX_ADDRESS) _index=MAX_ADDRESS-1; + address[_index]=_address; + addressNum=_index+1; +} + + + +void OSCMessage::setArgs(char *types,...){ + + va_list argList; + + argNum = strlen(types); + if(argNum>MAX_ARG) argNum=MAX_ARG-1; + + va_start( argList, types ); + for(uint8_t i=0 ; i < argNum ; i++){ + + typeTag[i]=types[i]; + + switch(types[i]) { + case 'i': + arg[i]=(uint32_t *)va_arg(argList, uint32_t *); + break; + case 'f': + arg[i]=va_arg(argList, double *); + break; + } + + } + +} + +// ================================================================================================================================================ +// ==================================== OSCClass for sending and receiving OSC messages using UDP protocol ======================================= +// ================================================================================================================================================ +//The class define an object wrapping the UDP functions to send and receive OSC messages + +OSCClass::OSCClass(){ + udpRec.setOnEvent(this, &OSCClass::onUDPSocketEvent); + newMessage=false; +} + +OSCClass::OSCClass(OSCMessage *_mes){ + udpRec.setOnEvent(this, &OSCClass::onUDPSocketEvent); + receiverMessage = _mes; // note: receiverMessage MUST be a pointer to the message, because we will modify things in it + newMessage=false; +} + +void OSCClass::begin() +{ + // setup receiver udp socket: + udpRec.bind(receiverMessage->host); +} + + +void OSCClass::begin(uint16_t _recievePort) +{ + receiverMessage->host.setPort(_recievePort); + // setup receiver udp socket: + udpRec.bind(receiverMessage->host); +} + + +void OSCClass::setReceiveMessage(OSCMessage *_mes){ + receiverMessage = _mes; +} + +void OSCClass::onUDPSocketEvent(UDPSocketEvent e) +{ + switch(e) + { + case UDPSOCKET_READABLE: //The only event for now + //char buf[256] = {0}; + Host auxhost; + buflength = udpRec.recvfrom( rcvBuff, 256, &auxhost ); // QUESTION: auxhost should be equal to the receiver host I guess... + if ( buflength > 0 ) { + //printf("\r\nFrom %d.%d.%d.%d:\r\n", host.getIp()[0], host.getIp()[1], host.getIp()[2], host.getIp()[3]); + decodePacket(receiverMessage); // convert to OSC message, and save it in receiverMessage + newMessage=true; + + messageReceivedCallback.call(); + } + break; + } +} + +/* + Decode UDP packet and save it in the OSCMessage structure + */ +void OSCClass::decodePacket( OSCMessage *_mes) { + + //uint16_t lenBuff; + uint8_t d; + uint8_t messagePos=0; + uint8_t adrCount=0; + uint8_t adrMesPos=0; + uint8_t packetCount=0; + uint8_t packetPos=4; + + + //W5100.writeSn(socketNo, SnIR, SnIR::RECV); + //lenBuff=recvfrom(socketNo, rcvBuff, 1, receiverMessage->ip, &receiverMessage->port); + + receiverMessage->address[0]=tempAddress[0]; + + //(1) address process start ========================================= + do{ + d=rcvBuff[messagePos]; + + + if( (d=='/') && (messagePos>0) ){ + + if(adrCount<MAX_ADDRESS){ + tempAddress[adrCount][adrMesPos]=0; + + adrCount++; + adrMesPos=0; + + receiverMessage->address[adrCount]=tempAddress[adrCount]; + } + + } + + if(adrCount<MAX_ADDRESS){ + //Added this in to remove the slashes out of final output + if(d!='/'){ + tempAddress[adrCount][adrMesPos]=d; + + if(packetCount>3) { + packetCount=0; + packetPos+=4; + } + + adrMesPos++; + } + } + messagePos++; + packetCount++; + + }while(d!=0); + + + if(adrCount<MAX_ADDRESS) adrCount++; + receiverMessage->addressNum=adrCount; + + messagePos=packetPos; + + //(2) type tag process starts ========================================= + packetCount=0; + packetPos+=4; + + uint8_t typeTagPos=0; + uint8_t tempArgNum=0; + + while(rcvBuff[messagePos]!=0 ){ + + if(rcvBuff[messagePos] != ',') { + + if(typeTagPos<MAX_ARG){ + receiverMessage->typeTag[tempArgNum]=rcvBuff[messagePos]; + tempArgNum++; + } + typeTagPos++; + + } + + packetCount++; + + if(packetCount>3) { + packetCount=0; + packetPos+=4; + } + + messagePos++; + } + + receiverMessage->argNum=tempArgNum; + + messagePos=packetPos; + + //(3) tempArg process starts ========================================= + for(int i=0;i<tempArgNum;i++){ + + adrMesPos=3; + + receiverMessage->arg[i]=tempArg[i]; + + for(int j=0;j<4;j++){ + + tempArg[i][adrMesPos]=rcvBuff[messagePos]; + + messagePos++; + adrMesPos--; + } + + } + + +} + + + +OSCMessage * OSCClass::getMessage(){ + newMessage=false; // this indicate the user READ the message + return receiverMessage; +} + + +void OSCClass::sendOsc( OSCMessage *_mes ) +{ + uint8_t lengthEnd; + uint8_t lengthStart; + char buff[128]; + + sendContainer = _mes; + + //バッファ初期値 + buff[0]=0; + + //1) Add name spaces: + for(int i=0;i<sendContainer->addressNum;i++){ + + strcat(buff,sendContainer->address[i]); // note: an address is for instance: "/test" (including the "/") + + } + + // pad with 0s to align in multiples of 4: + lengthStart=strlen(buff); + lengthEnd=lengthStart+(4-(lengthStart%4)); + for(int i=lengthStart ; i<lengthEnd; i++){ + buff[i]=0; + } + + lengthStart=lengthEnd; + + //2) Add TypeTag: + buff[lengthEnd++]=','; // Note: type tag is for instance: ",if" + for(int i=0;i<sendContainer->argNum;i++){ + buff[lengthEnd++]=sendContainer->typeTag[i]; + } + + // pad with 0s to align in multiples of 4: + lengthStart=lengthEnd; + lengthEnd=lengthStart+(4-(lengthStart%4)); + for(int i=lengthStart ; i<lengthEnd; i++){ + buff[i]=0; + } + + //3) add argument values (Note: here only big endian): + uint8_t *v; + for(int i=0;i<sendContainer->argNum;i++){ + uint8_t valuePos=3; + v=(uint8_t *)sendContainer->arg[i]; + + buff[lengthEnd++]=v[valuePos--]; + buff[lengthEnd++]=v[valuePos--]; + buff[lengthEnd++]=v[valuePos--]; + buff[lengthEnd++]=v[valuePos]; + + } + + //4) Send udp packet: + //sendto( socketNo, (uint8_t *)buff, lengthEnd, sendContainer->ip, sendContainer->port ); + udpSend.sendto(buff , lengthEnd, &(sendContainer->host)); +} + + +/* + flush a receive buffer +void OSCClass::flush() { + while ( available() ){} +} +*/ + + +void OSCClass::stop() { + //close( socketNo ); + udpSend.resetOnEvent(); // disables callback +} + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbedOSC.h Sun Apr 15 15:50:42 2012 +0000 @@ -0,0 +1,312 @@ +/* mbed OSC Library + This is an Open Sound Control library for the mbed, created to be compatible with Recotana's OSCClass library (http://recotana.com) for the + Arduino with Ethernet shield. It also uses parts of the OSC Transceiver(Sender/Receiver) code by xshige + written by: Alvaro Cassinelli, October 2011 + tweaked by: Toby Harris / *spark audio-visual, March 2012 + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + Open Sound Control http://opensoundcontrol.org/ +*/ + +#ifndef mbedOSC_h +#define mbedOSC_h + +#include "mbed.h" +#include "EthernetNetIf.h" +#include "UDPSocket.h" + +// setup IP of destination (computer): +#define DEFAULT_SEND_PORT 12000 +//Host sendHost(IpAddr(10, 0, 0, 1), DEFAULT_SEND_PORT, NULL); // Send Port +// set IP of origin of UDP packets - the mbed acts as a SERVER here, and needs to bind the socket to the "client" (the computer) +#define DEFAULT_RECEIVE_PORT 57130 +//Host recHost(IpAddr(10, 0, 0, 1), DEFAULT_RECEIVE_PORT, NULL); // Receive Port +//UDPSocket udpRec,udpSend; + + +#define MAX_ADDRESS 2 +#define MAX_ARG 2 + +#define TYPE_INT 1 +#define TYPE_FLOAT 2 + + +/** Container class for OSC messages (receiving or sending) + @note mbedOSC version 0.1 Specification (similar to Recotana's OSCClass library) + Example of an OSC message: "/mbed/test1, if 50 32.4" + ie. "Address TypeTag Args" + Address : max 2 + "/ard" + "/ard/output" + --address[0]="/ard" :max 15character + --address[1]="/output" :max 15character + TypeTag : max 2 + "i" - long or unsigned long + "f" - double + arg : max 2 + (Note: The byte string as seen here is not sent as UDP packet directly - there are no spaces, and arguments are in binary, BIG ENDIAN) +*/ +class OSCMessage{ + + private: + + char *address[MAX_ADDRESS]; // these are strings (as char*) + uint8_t addressNum; // current number of addresses in the message (ex: "/ard/test" --> the number of the addresses is 2) + + char typeTag[MAX_ARG]; + + void *arg[MAX_ARG]; + uint8_t argNum; + + // Information about the connection: + //uint8_t ip[4]; + //uint16_t port; + Host host; + + public: + /** Create a container for an OSC message to be received or sent */ + OSCMessage(); + + /** Return the IpAddr object */ + const IpAddr& getIp(); + /** Return the port */ + const int& getPort(); + +/** Gets the address string of the OSC message + * + * @param[in] _index The index of the address string (byte) + * @return pointer of the address string (char *) + * @note ex. "/ard/test"<br> + * getAddress(0) = "/ard"<br> + * getAddress(1) = "/test" + * @attention It is maximum number of the addresses is 2<br> + * In this case "/ard/test1/test2"<br> + * ignore it after "/test2" + */ + char *getAddress(uint8_t _index); //retturn address + +/** Gets the TopAddress string of the OSC message (this is just the address with index 0) + @return pointer of the TopAddress string (char *), i.e. address[0] + Example: In the case "/ard/test", getTopAddress() = "/ard" (WITH the slash "/") + */ + char *getTopAddress(); //return address[0] :"/ard" + +/** + Gets the "SubAddress" string of the OSC message (this is just the address with index 1) + @return pointer of the SubAddress string (char *), i.e. address[1] + Example: in the case "/ard/test", getSubAddress() = "/test" (WITH the slash "/") + */ + char *getSubAddress(); //return address[1] :"/test" + +/** + Gets the number of the OSC message address + @return number of the OSC message address (byte) + Examples: "/ard" --> the number of the addresses is 1 + "/ard/test" --> the number of the addresses is 2 + Attention: the maximum number of addresses is 2 (MAX_ADDRESS) +*/ + uint8_t getAddressNum(); //return 2 + +/** + Gets the TypeTag string (with index) of the OSC message + @param[in] _index The index of the TypeTag string (byte) + @return: TypeTag char (char) + Example: in the case of a total typetag string equal to "if", getTypeTag(0) = 'i' and getTypeTag(1) = 'f' + Attention: MAX_ARG is maximum number of the args, if the index argument is larger, it will be constrained to this max. + */ + char getTypeTag(uint8_t _index); //_index=0 ->'i' + //_index=1 ->'f' + +/** + Gets the number of the OSC message args + @return number of the args (byte) + Example: "i" 123 --> number of the OSC message args is 1 + "if" 123 54.24 --> number of the OSC message args is 2 + Attention: the maximum number of args is 2 (MAX_ARG) + */ + uint8_t getArgNum(); //return 2 + +/** + Get the args of the OSC message with an integer value + @param[in] _index An int or uint8_t corresponding to the index of the args (byte) + @return: integer value (long, or int32_t) + Example: in the case "if" 123 54.24, getArgInt(0) = 123 + Noe: "i" is integer, but the return type is "long" + Note: When a index is bigger than the number of the args, it is set to the number of the args + */ + int32_t getArgInt(uint8_t _index); //_index=0 -> 123 + +/** + Get the args of the OSC message with a float value + @param[in] _index The index of the args + @return: float value (double) + note: In this case "if" 123 54.24, getArgFloat(1) = 54.24 + attention: arg declared as float, but return value cast as "double" + attention: When index is bigger than the number of the args, it is set to the number of the args + */ + double getArgFloat(uint8_t _index); //_index=1 -> 54.21 + + +/** + Set TopAddress string of OSC Message + @param[in] _address A string pointer for the TopAddress String (char *). NOTE: is this a good idea? why not pass as const, and do allocation here? + Example: if the complete address string is "/ard/test", we set the topaddress as follows: char top[]="/ard" (allocation done here!), then setTopAddress(top) + */ + void setTopAddress(char *_address); //set address[0] + +/** + Set SubAddress string of the OSC Message + @param[in] _address A string pointer for the SubAddress String (char *) + Example: if the complete address string is "/ard/test", we set the subaddress as follows: char sub[]="/test" (allocation done here!), then setSubAddress(sub) + Attention: we should call first setTopAddress, and then setSubAddress. The order is important. This does not seems like a good idea... + */ + void setSubAddress(char *_address); //set address[1] + +/** + Set the complete Address string of the OSC Message (top and sub addresses) + @param[in] _topAddress, _subAddress The string pointers to top and sub addresses (char *) + Example: in the case "/ard/test", we need to do: char top[]="/ard", char sub[]="/test", and then setAddress(top,sub) + Reminder: in this implementation, the maximum number of addresses is MAX_ADDRESS=2 + */ + void setAddress(char *_topAddress, + char *_subAddress); + +/** + Set address string using index (here 0 or 1) + Example: "/ard/test", char adr[]="/ard", setAddress(0,adr), char adr2[]="/test", setAddress(1,adr) + */ + void setAddress(uint8_t _index, //set 0,address[0] + char *_address); + //set 1,address[1] + +/** + Set IP Address of the OSC Message (for SENDING messages - for receiving this will be done when receiving something ) + @param[in] _ip Pointer of IP Address array (byte *) + Example: IP=192.168.0.99, then we have to do: ip[]={192,168,0,1}, then setIp(ip) + */ + void setIp( uint8_t *_ip ); //set ip + +/** + Set IP Address to the OSC Message container (not through pointer) + Example: IP=192.168.0.99 => setIp(192,168,0,99) + */ + void setIp(uint8_t _ip1, //set(192, + uint8_t _ip2, // 168, + uint8_t _ip3, // 0, + uint8_t _ip4); // 100) + + /* + Set PortNo for the OSC Message + @param[in] _port PortNo (unsigned int) + @return None + */ + void setPort( uint16_t _port ); + +/** + Set TypeTag and args to the OSC Message container + @param[in] types TypeTag string "i"(integer) or"f"(float) (char *) + @param[in] ... Pointer of the Args(variable argument) .. + @Example: + (1) integer 123: (NOTE: integers are LONG) + long v1=123; sendMes.setArgs("i",&v1) + (2)integer:123 and float:52.14 + long v1=123; double v2=52.14; sendMes.setArgs("if",&v1,&v2) + Attention: in this implementation, the maximum number of the args is 2 + (if setArgs("iff",&v1,&v2,&v3), data is ignored after &v3) + */ + void setArgs( char *types , ... ); //set ("if",&v1,&v2) + + friend class OSCClass; + +}; + + + +/* ==================================== OSCClass for sending and receiving OSC messages using UDP protocol ===================================== */ + +#include "UDPSocket.h" + +/** Wraps the UDP functions to send and receive OSC messages */ +class OSCClass { + +private: + + UDPSocket udpRec,udpSend; + char rcvBuff[256]; // raw buffer for UDP packets (udpRec.recvfrom( buf, 256, &host ) )) + int buflength; + + OSCMessage *receiverMessage; + OSCMessage *sendContainer; + + char tempAddress[MAX_ADDRESS][16]; + uint8_t tempArg[MAX_ARG][4]; + + void onUDPSocketEvent(UDPSocketEvent e); + + void decodePacket( OSCMessage *_mes); // makes OSC message from packet + +public: + + friend class UDPSocket; + + /** Create an object to send and receive OSC messages */ + OSCClass(); + +/** + This sets "binds" the received message to the receiver container of the communication object + @param[in] _mes A pointer to the "receiveing" OSC message (OSCMessage *) + */ + OSCClass(OSCMessage *_mes); // set the receiver message container + +/** + This initializes the OSC communication object with default receiving port (DEFAULT_REC_PORT) + */ + void begin(); + +/** + Initialize an OSC object with arbitrary listening port + @param[in] _recievePort The listening ("receiving") Port No (unsigned int) + */ + void begin(uint16_t _recievePort); + +/** + Stop OSC communication (in fact, only the receiver - the server side) + */ + void stop(); + +/** + Returns whether there is new OSC data in the receiver message container. + */ + bool newMessage; + +/** + Set a OSC receive message container + @param[in] _mes Pointer to the OSC receive message container (OSCMessage *) + */ + void setReceiveMessage( OSCMessage *_mes ); //set receive OSCmessage container (note: the message has a "host" object from which we get the upd packets) + +/** + Get the received OSC message (note: this is another way to access the message directly from the OSCClass object). + The advantage is that we will signal that we read the message, and will be able to query if a NEW message arrived + (Alternatively, one could have a function pointer to pass to the OSC object, that will be called each time a new packet is received: TO DO) + */ + OSCMessage *getMessage(); //return received OSCmessage + +/** + Send an OSC Message (message contain the host ip and port where the message data has to be sent) + @param[in] _mes Pointer to the OSC message container (OSCMessage *) + */ + void sendOsc( OSCMessage *_mes ); //set&send OSCmessage (note: it will be sent to the host defined in the message container) + +/** + A function pointer to be set by host program that will be called on receipt of an OSC message + @code + osc.messageReceivedCallback.attach(&processOSC); + @endcode + */ + FunctionPointer messageReceivedCallback; +}; + +#endif