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
Dependencies: NetServices mbed
Revision 0:49cdaebd52d5, committed 2012-03-13
- Comitter:
- tobyspark
- Date:
- Tue Mar 13 22:42:25 2012 +0000
- Child:
- 1:ab7dc9550de6
- Commit message:
- Changes:
- udpRec.setOnEvent is now properly encapsulated within the class
- the message received callback is now a public property using mbed\s FunctionPointer class
- swapped out the EthernetNetIf source for the NetService library, which despite the name is an updated version.
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/NetServices.lib Tue Mar 13 22:42:25 2012 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/segundo/code/NetServices/#4e2468d7d5cb
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Tue Mar 13 22:42:25 2012 +0000 @@ -0,0 +1,154 @@ +#include "mbed.h" +#include "mbedOSC.h" + +DigitalOut myled(LED1); + +// mbed IP address (server): +#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 + +//uint8_t serverMac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; +uint8_t serverIp[] = { 10, 0, 0, 2 }; // not needed perhaps! +int serverPort = 10000; + +uint8_t destIp[] = { 10, 0, 0, 1}; +int destPort = 12000; + +char *topAddress="/mbed"; +char *subAddress[3]={ "/test1" , "/test2" , "/test3" }; + +OSCMessage recMes; +OSCMessage sendMes; + +OSCClass osc; +//OSCClass osc(&recMes); // instantiate OSC communication object, and set the receiver container from the OSC packets + + Serial pc(USBTX, USBRX); + +void processOSC(); + +int main() { + + // make debug port: + pc.baud(115200); + + // Set the Ethernet port: + printf("Setting up...\r\n"); + EthernetErr ethErr = eth.setup(); + if(ethErr) + { + printf("Error %d in setup.\r\n", ethErr); + return -1; + } + printf("Setup OK\r\n"); + + + //(1) Sending message: + // Set IP and Port: + sendMes.setIp( destIp ); + sendMes.setPort( destPort ); + // Set data: + // sendMes.setTopAddress(topAddress); + + //setting osc functionnality: + //(2) Receiving: + // recMes.setIp( serverIp ); // not needed? + osc.setReceiveMessage(&recMes); // this sets the receiver container for the OSC packets (we can avoid doing this if we use osc.getMessage() to get messages) + osc.begin(serverPort); // binds the upd (osc) messages to an arbitrary listening port ("server" port), and callback function + osc.messageReceivedCallback.attach(&processOSC); + + //========================================== INFINITE LOOP (in USER PROGRAM CONTEXT) =================================================================== + while(true) { + Net::poll(); + + // ... Do whatever needs to be done (note: the osc processing is done in the processOSC function. + // BUT DO NOT FORGET to call osc.onUDPSocketEvent(e). This is messy... should find a better way to do it. + + } +} + +void processOSC() { + + if (osc.newMessage) { // in fact, there is no need to check this if using the method of a global callback function - it is clear this is a new packet... however, it may be + // interesting to use a timer, and process data (answers, etc) only after a certain amount of time, so as to avoid blocking the program in IRQ context... + + //pc.printf("we received top address %s\n", recMes.getAddress(0) ); + + osc.newMessage=false; // note: if using: message=osc.getMessage(), then we don't need to do this explicitly. + + // Test: + if( !strcmp( recMes.getAddress(0) , "mbed" ) ) { + pc.printf("we received topAddress= mbed \n"); + if( !strcmp( recMes.getAddress(1) , "test1" ) ) + pc.printf("we received subAddress= test1 \n"); + + // Send some osc message: + sendMes.setTopAddress("/working..."); + osc.sendOsc(&sendMes); + } + } + +} + + +/* 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/mbed.bld Tue Mar 13 22:42:25 2012 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed/builds/63bcd7ba4912
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbedOSC.cpp Tue Mar 13 22:42:25 2012 +0000 @@ -0,0 +1,532 @@ +/* + 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); +} + +/* + Set PortNo for the OSC Message + @param[in] _port PortNo (unsigned int) + @return None + */ +void OSCMessage::setPort(uint16_t _port){ + host.setPort(_port); +} + +/* + 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 OSCMessage::setIp(uint8_t *_ip){ + host.setIp(IpAddr(_ip[0], _ip[1], _ip[2], _ip[3])); +} + + +/*! + Set IP Address to the OSC Message container (not through pointer) + Example: IP=192.168.0.99 => setIp(192,168,0,99) + */ +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(); +} + + +/* + Gets the number of the OSC message address + param[in] None + 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 OSCMessage::getAddressNum(){ + + return addressNum; +} + + +/* + Gets the number of the OSC message args + param[in] None + 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 OSCMessage::getArgNum(){ + + return argNum; +} + + +/* + Gets the address string of the OSC message + param [in] <-- _index is 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 * OSCMessage::getAddress(uint8_t _index){ + if(_index>MAX_ADDRESS) _index=MAX_ADDRESS-1; + return address[_index]; + +} + + +/* + Gets the TopAddress string of the OSC message (this is just the address with index 0) + param[in] None + return pointer of the TopAddress string (char *), i.e. address[0] + Example: In the case "/ard/test", getTopAddress() = "/ard" (WITH the slash "/") + */ +char * OSCMessage::getTopAddress(){ + + return getAddress(0); + +} + +/* + Gets the "SubAddress" string of the OSC message (this is just the address with index 1) + param[in] None + return pointer of the SubAddress string (char *), i.e. address[1] + Example: in the case "/ard/test", getSubAddress() = "/test" (WITH the slash "/") + */ +char * OSCMessage::getSubAddress(){ + + return getAddress(1); + +} + +/* + Gets the TypeTag string (with index) of the OSC message + param[in] <--_index is 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 OSCMessage::getTypeTag(uint8_t _index){ + if(_index>MAX_ARG) _index=MAX_ARG-1; + return typeTag[_index]; +} + +/* + Get the args of the OSC message with an integer value + param[in] <--_index is (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 OSCMessage::getArgInt(uint8_t _index){ + int32_t *value; + if(_index > argNum) _index=argNum; + value = (int32_t *)arg[_index]; // cast to int32_t + return *value; +} + +/* + Get the args of the OSC message with a float value + param[in] <--_index is 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 OSCMessage::getArgFloat(uint8_t _index){ + double *value; + if(_index > argNum) _index=argNum; + value = (double *)arg[_index]; + return *value; +} + +/* + Set TopAddress string of OSC Message + param[in] <-- _address is a string pointer for the TopAddress String (char *). NOTE: is this a good idea? why not pass as const, and do allocation here? + return: None + 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 OSCMessage::setTopAddress(char *_address){ + address[0]=_address; + address[1]=0; + addressNum=1; // Note: this "erases" the subaddress! (is this a good idea?) +} + +/* + Set SubAddress string of the OSC Message + param[in] <-- _address is a string pointer for the SubAddress String (char *) + return: None + 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 OSCMessage::setSubAddress(char *_address){ + address[1]=_address; + addressNum=2; // Note: this assumes the top address was already set! +} + + +/* + Set the complete Address string of the OSC Message (top and sub addresses) + param[in] <-- _topAddress and _subAddress are the string pointers to top and sub addresses (char *) + return: None + 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 OSCMessage::setAddress(char *_topAddress,char *_subAddress){ + setTopAddress(_topAddress); + setSubAddress(_subAddress); + addressNum=2; // (unnecessary...) +} + +/* + 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 OSCMessage::setAddress(uint8_t _index, char *_address){ + if(_index>MAX_ADDRESS) _index=MAX_ADDRESS-1; + address[_index]=_address; + addressNum=_index+1; +} + + +/* + 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) .. + @return None + @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 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; +} + +/* + This sets "binds" the received message to the receiver container of the communication object + param[in]<--_mes is a pointer to the "receiveing" OSC message (OSCMessage *) + */ +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; +} + +/* + This initializes the OSC communication object with default receiving port (DEFAULT_REC_PORT) + param[in]: None + return: None + */ +void OSCClass::begin() +{ + // setup receiver udp socket: + udpRec.bind(receiverMessage->host); +} + +/* + Initialize an OSC object with arbitrary listening port + param[in] <-- _recievePort, is the listening ("receiving") Port No (unsigned int) + return: None + */ +void OSCClass::begin(uint16_t _recievePort) +{ + receiverMessage->host.setPort(_recievePort); + // setup receiver udp socket: + udpRec.bind(receiverMessage->host); +} + +/* + Set a OSC receive message container + param[in] _mes Pointer to the OSC receive message container (OSCMessage *) + return None + */ +void OSCClass::setReceiveMessage(OSCMessage *_mes){ + receiverMessage = _mes; +} + +/* + callback function when an upd message arrives (it will be transformed as OSC message) + */ +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--; + } + + } + + +} + + +/* + 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 * OSCClass::getMessage(){ + newMessage=false; // this indicate the user READ the message + return receiverMessage; +} + +/* + 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 *) + return None + */ +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() ){} +} +*/ + +/* + Stop OSC communication (in fact, only the receiver - the server side) + */ +void OSCClass::stop() { + //close( socketNo ); + udpSend.resetOnEvent(); // disables callback +} + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbedOSC.h Tue Mar 13 22:42:25 2012 +0000 @@ -0,0 +1,177 @@ +/* mbedOSC.h + This is an OSC library for the mbed, created to be compatible with Recotana's OSCClass library (http://recotana.com) for the + Arduino with Ethernet shield. I have also used parts of the OSC Transceiver(Sender/Receiver) code by xshige + written by: Alvaro Cassinelli, 7.10.2011 + tweaked by: Toby Harris / *spark audio-visual, 13.4.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/ + + mbedOSC version 0.1 Specification (similar to Recotana's OSCClass library) + + ******** + 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 + + ******* + Example of an OSC message: "/mbed/test1, if 50 32.4" (Note: this is not the byte string + sent as UDP packet - there are no spaces, and arguments are in binary, BIG ENDIAN) +*/ + +#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) +*/ +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: + + OSCMessage(); + + const IpAddr& getIp(); // return IpAddr object + const int& getPort(); // return port + + //ex. address patern "/adr/test" + // address[2]={"/ard" , "/test"} + char *getAddress(uint8_t _index); //retturn address + char *getTopAddress(); //return address[0] :"/ard" + char *getSubAddress(); //return address[1] :"/test" + uint8_t getAddressNum(); //return 2 + + // 'i': long(int32_t) + // 'f': double + //ex 'if' 123 54.21 + char getTypeTag(uint8_t _index); //_index=0 ->'i' + //_index=1 ->'f' + + uint8_t getArgNum(); //return 2 + + int32_t getArgInt(uint8_t _index); //_index=0 -> 123 + double getArgFloat(uint8_t _index); //_index=1 -> 54.21 + + + void setTopAddress(char *_address); //set address[0] + void setSubAddress(char *_address); //set address[1] + void setAddress(char *_topAddress, + char *_subAddress); + void setAddress(uint8_t _index, //set 0,address[0] + char *_address); + //set 1,address[1] + + void setIp( uint8_t *_ip ); //set ip + + void setIp(uint8_t _ip1, //set(192, + uint8_t _ip2, // 168, + uint8_t _ip3, // 0, + uint8_t _ip4); // 100) + + void setPort( uint16_t _port ); + + //ex. long v1=100 + // double v2=123.21 + void setArgs( char *types , ... ); //set ("if",&v1,&v2) + + friend class OSCClass; + +}; + + + +/* ==================================== OSCClass for sending and receiving OSC messages using UDP protocol ===================================== */ + +#include "UDPSocket.h" + +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 decodePacket( OSCMessage *_mes); // makes OSC message from packet + +public: + + OSCClass(); + OSCClass(OSCMessage *_mes); // set the receiver message container + void onUDPSocketEvent(UDPSocketEvent e); + + //init osc + void begin(); + void begin(uint16_t _recievePort); + void stop(); + + //new OSC data in the receiver message container: + bool newMessage; + + void setReceiveMessage( OSCMessage *_mes ); //set receive OSCmessage container (note: the message has a "host" object from which we get the upd packets) + OSCMessage *getMessage(); //return received OSCmessage + + //buffer clear + //void flush(); + + //OSC send + void sendOsc( OSCMessage *_mes ); //set&send OSCmessage (note: it will be sent to the host defined in the message container) + + //to be set by host program, will be called on receipt of an OSC message + FunctionPointer messageReceivedCallback; +}; + +#endif