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

Dependents:   SPK-DVIMXR

Revision:
0:fdea65150534
Child:
1:63b72e393989
--- /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;
+    
+    //&#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() ){}
+}
+*/
+
+
+void OSCClass::stop() {
+    //close( socketNo );
+    udpSend.resetOnEvent(); // disables callback
+}
+
+