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

Files at this revision

API Documentation at this revision

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

NetServices.lib Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
mbedOSC.cpp Show annotated file Show diff for this revision Revisions of this file
mbedOSC.h Show annotated file Show diff for this revision Revisions of this file
--- /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;
+    
+    //&#12496;&#12483;&#12501;&#12449;&#21021;&#26399;&#20516;
+    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