OSC Transceiver(Sender/Receiver) program on mbed supporting types i:int32, b:blob, s:string, f:float32, m:MIDI. Attached OSC test program(in processing). Plese refer for detail:http://opensoundcontrol.org/introduction-osc

Dependencies:   EthernetNetIf mbed

OSCTransceiver.cpp

Committer:
xshige
Date:
2011-01-11
Revision:
0:a11a5771a1a9

File content as of revision 0:a11a5771a1a9:

// 
// OSC Transceiver(Sender/Receiver)
//
// date: 2011/1/11
// version: 0.7
// written by: xshige
//
// please find OSC Sender/Receiver test program at the bottom of this file
//
// please refer to: http://opensoundcontrol.org/introduction-osc for OSC(Open Sound Control)
/*
  The followings are supported:

    Transport Type: 
      UDP

    Features: 
     Packet Parsing (Client)
     Packet Construction (Server)
     Bundle NOT Support
     Timetag NOT Support

    Type Support: 
     i: int32
     b: blob
     s: string
     f: float32
     m: MIDI message(port id, status byte, data1, data2) // I don't know the detail
 
*/


#include "mbed.h"
#include "EthernetNetIf.h"
#include "UDPSocket.h"

//#define DHCP
//#define LED
//int ledsOSC;

#define INPUT_PORT 57130
#define OUTPUT_PORT 12000
// setup your mbed IP address
Host sendHost(IpAddr(192, 168, 0, 7), OUTPUT_PORT, NULL); // Send Port
Host recHost(IpAddr(192, 168, 0, 7), INPUT_PORT, NULL);  // Receive Port
UDPSocket udpRec,udpSend;

#ifdef DHCP
EthernetNetIf eth;
#else
EthernetNetIf eth(
  IpAddr(192,168,0,25), //IP Address
  IpAddr(255,255,255,0), //Network Mask
  IpAddr(192,168,0,1), //Gateway
  IpAddr(192,168,0,1)  //DNS
);
#endif


//--- OSC related stuff ---
int putOSCmsg(char *packet , union OSCarg *msg); // makes packet from OSC message and returns packet size
void getOSCmsg(char *packet , union OSCarg *msg); // makes OSC message from packet

union OSCarg {
// char*, int and float are assumed four bytes
        char *address;
        char *typeTag;
        int i;
        float f;
        char *s;
        struct {
            int len; // is "int i"
            char *p;
        } blob;
        char m[4];  // for MIDI
        char _b[4]; // endian conversion temp variable
};

int putOSCmsg(char *packet , union OSCarg *msg){
    char *p, *s, *d, *typeTag; char c;

    p=packet;
    d=p;
    s=msg[0].address; // address
    for(int i=0; i<strlen(msg[0].address); i++) *d++ = *s++;
    *d=0; // terminator
    p += 4*(strlen(msg[1].address)/4+1);
    // 
    s=msg[1].typeTag;
    d=p;
    for(int i=0; i<strlen(msg[1].typeTag); i++) *d++ = *s++; 
    *d=0; // terminator   
    p += 4*(strlen(msg[1].s)/4+1);
    //
    typeTag=msg[1].s+1; // skip ','
    for(int n=0; n<strlen(typeTag); n++){
        c = typeTag[n];
        if (('s'==c)) {
            s=msg[n+2].s;
            d=p;
            for(int i=0; i<strlen(msg[n+2].s); i++) *d++ = *s++;
            *d=0; // terminater    
            p += 4*(strlen(msg[n+2].s)/4+1);
        } else if (('i'==c)||('f'==c)) {
            // chang endian (little to big)
            p[0]=msg[n+2]._b[3]; 
            p[1]=msg[n+2]._b[2]; 
            p[2]=msg[n+2]._b[1];
            p[3]=msg[n+2]._b[0];
            p +=4;  
        } else if ('b'==c) {
            // chang endian (little to big)
            // put length of blog
            p[0]=msg[n+2]._b[3]; 
            p[1]=msg[n+2]._b[2]; 
            p[2]=msg[n+2]._b[1];
            p[3]=msg[n+2]._b[0];
            p +=4;  
            // get ponter of blog (copy to msg[n].blog.p)
            s=msg[n+2].blob.p;
            d=p;
            for(int i=0; i<msg[n+2].blob.len; i++) *d++ = *s++;    
            p += 4*(msg[n+2].blob.len/4+1);       
        } else if ('m'==c) {
            // get midi data (copy to msg[n].m[])
            p[0]=msg[n+2].m[0]; 
            p[1]=msg[n+2].m[1]; 
            p[2]=msg[n+2].m[2];
            p[3]=msg[n+2].m[3];
            p +=4;  
        } else {
            printf("*** Not Supported TypeTag:%s ****\n",typeTag);
        }
    };
    return (p-packet); // return packet size    
}

void getOSCmsg(char *packet , union OSCarg *msg){
// Caution: the returned result points to packet as blobs or strings (not newly allocatd)
    char *p, *typeTag; char c;
        
    msg[0].address = packet; // address
    msg[1].typeTag = packet+4*(strlen(msg[0].s)/4+1);//typeTag
    typeTag=msg[1].s+1; // skip ','
    p= msg[1].s+4*(strlen(msg[1].s)/4+1);
    for(int n=0; n<strlen(typeTag); n++){
        c = typeTag[n];
        if (('s'==c)) {
            msg[n+2].s=p;
            p += 4*(strlen(msg[n+2].s)/4+1);
        } else if (('i'==c)||('f'==c)) {
            // chang endian (big to little)
            msg[n+2]._b[3]=p[0]; 
            msg[n+2]._b[2]=p[1]; 
            msg[n+2]._b[1]=p[2];
            msg[n+2]._b[0]=p[3];
            p +=4;  
        } else if ('b'==c) {
            // chang endian (big to little)
            // get lenth of blog (copy to msg[n].blog.len)
            msg[n+2]._b[3]=p[0]; 
            msg[n+2]._b[2]=p[1]; 
            msg[n+2]._b[1]=p[2];
            msg[n+2]._b[0]=p[3];
            p +=4;
            // get ponter of blog (copy to msg[n].blog.p)
            msg[n+2].blob.p=p;
            p += 4*(msg[n+2].blob.len/4+1);       
        } else if ('m'==c) {
            // get midi data (copy to msg[n].m[])
            msg[n+2].m[0]=p[0]; 
            msg[n+2].m[1]=p[1]; 
            msg[n+2].m[2]=p[2];
            msg[n+2].m[3]=p[3];
            p +=4;  
        } else {
            printf("*** Not Supported TypeTag:%s ****\n",typeTag);
        }
    };
    
}
//-------------------------------------------

void onUDPSocketEvent(UDPSocketEvent e)
{
  union OSCarg msg[10];

  switch(e)
  {
  case UDPSOCKET_READABLE: //The only event for now
    char buf[256] = {0};
    Host host;
    while( int len = udpRec.recvfrom( buf, 256, &host ) )
    {
      if( len <= 0 )
        break;
      printf("\r\nFrom %d.%d.%d.%d:\r\n", 
      host.getIp()[0], host.getIp()[1], host.getIp()[2], host.getIp()[3]);
      
      getOSCmsg(buf,msg);

      // address pattern samples
      if (strcmp(msg[0].address,"/test")==0) {
        printf("OSCmsg: %s %s %d %f %s %d\n", 
            msg[0].address, msg[1].typeTag,msg[2].i, msg[3].f, msg[4].s, msg[5].blob.len);
        printf("blob content:\n");
        char *p=msg[5].blob.p;
        for(int n=0; n<msg[5].blob.len; p++,n++) printf(" %02X",(unsigned char)(*p));
        printf("\n");
        break;
      }
      if (strcmp(msg[0].address,"/kb/m")==0) {
        printf("OSCmsg: %s %s %d %d %d\n", 
            msg[0].address, msg[1].typeTag,msg[2].i, msg[3].i, msg[4].i);
        break;
      }
      if (strcmp(msg[0].address,"/cc/m")==0) {
        printf("OSCmsg: %s %s %d %d %d\n", 
            msg[0].address, msg[1].typeTag,msg[2].i, msg[3].i, msg[4].i);
        break;
      }
      if (strcmp(msg[0].address,"/1/fader1")==0) {
        printf("OSCmsg: %s %s %f\n", 
            msg[0].address, msg[1].typeTag,msg[2].f);
        break;
      }
      if (strcmp(msg[0].address,"/1/knob1")==0) {
        printf("OSCmsg: %s %s %f\n", 
            msg[0].address, msg[1].typeTag, msg[2].f);
        break;
      } 
      if (strcmp(msg[0].address,"/1/butt/A1")==0) {
        printf("OSCmsg: %s %s %i\n", 
            msg[0].address, msg[1].typeTag, msg[2].i);
        break;
      }
      if (strcmp(msg[0].address,"/1/butt/B1")==0) {
        printf("OSCmsg: %s %s %i\n", 
            msg[0].address, msg[1].typeTag, msg[2].i);
        break;
      }
      if (strcmp(msg[0].address,"/mouse/dragged")==0) {
        printf("OSCmsg: %s %s %i %i\n", 
            msg[0].address, msg[1].typeTag, msg[2].i, msg[3].i);
        break;
      }
      if (strcmp(msg[0].address,"/mouse/pressed")==0) {
        printf("OSCmsg: %s %s %i %i\n", 
            msg[0].address, msg[1].typeTag, msg[2].i, msg[3].i);
        break;
      }
      if (strcmp(msg[0].address,"/1/xy")==0) {
        printf("OSCmsg: %s %s %f %f %d\n", 
            msg[0].address, msg[1].typeTag, msg[2].f, msg[3].f, msg[4].i);
#ifdef LED
        ledsOSC=16*msg[2].f;
#endif
        break;
      }
      printf("undefined OSCmsg:%s %s\n",msg[0].address, msg[1].typeTag);
    } // while
    break;
  } // case
}

#ifdef LED
BusOut myleds(LED1, LED2, LED3, LED4);
#endif


int counter=1; // for test
void sendTestOSCmsg(){
    char packet[128]; int len;
    
    union OSCarg outmsg[10];
    char bb[17]={0x00, 0x01, 0x10, 0x20,0x30,0x40,0x50,0x60,0x7F,0x80,0x90,0xA0,0xB0,0xC0,0xD0,0xE0,0xFF};
    // setup OSC message
    outmsg[0].address="/test2";
    outmsg[1].typeTag=",ifsb";
    outmsg[2].i=counter; counter++;
    outmsg[3].f=34.55*counter;
    outmsg[4].s="Hello! Everything is going right?";
    outmsg[5].blob.len=sizeof(bb);
    outmsg[5].blob.p=bb;
    // make packet from OSC message
    len=putOSCmsg(packet,outmsg);
       
    // send it
     udpSend.sendto(packet, len, &sendHost );

//debug code
#if 0
    union OSCarg msg[10]; //debug
    getOSCmsg(packet,msg);
    if (strcmp(msg[0].address,"/test2")==0) {
        printf("\nsend packet debugging:\n");
        printf("OSCmsg: %s %s %d %f %s %d\n", 
            msg[0].address, msg[1].typeTag,msg[2].i, msg[3].f, msg[4].s, msg[5].blob.len);
        printf("blob content:\n");
        char *p=msg[5].blob.p;
        for(int n=0; n<msg[5].blob.len; p++,n++) printf(" %02X",(unsigned char)(*p));
        printf("\n");
    }
#endif
}


int main() {
// make debug port Fast
   Serial pc(USBTX, USBRX);
//    pc.baud(9600);
    pc.baud(115200);
//  pc.baud(230400);

  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");
  

  // setup receiver
  udpRec.setOnEvent(&onUDPSocketEvent);
  udpRec.bind(recHost);
  
  
  Timer tmr;
  tmr.start();
  while(true)
  {
    Net::poll();
    if(tmr.read() > 2)
    {
      tmr.reset();
      sendTestOSCmsg();
    }
    
//   sendTestOSCmsg();
    
#ifdef LED
    myleds=ledsOSC%16;
#endif
  } 
}

//----------------------------------------------------------------------------------------------------------
/*
//
// OSC Sender/Receiver test
//
// written in: processing(refer to: http://processing.org/)
//
// this program is based on oscP5plug in examples of oscP5 lib.
//
// please install oscP5 lib
// you can download this from: http://www.sojamo.de/libraries/oscP5/
 
import oscP5.*;
import netP5.*;

// change them to fit your environment
int INPUT_PORT=12000; // receive port
int OUTPUT_PORT=57130; // send port
String remoteIP="192.168.0.25"; // mbed IP address

OscP5 oscP5;
NetAddress remoteHost;

void setup() {
  size(400,400);
  // setup receiver
  oscP5 = new OscP5(this,INPUT_PORT);
  // setup mbed IP & sender
  remoteHost = new NetAddress(remoteIP,OUTPUT_PORT);
  
  // setup OSC message address for receiving
  oscP5.plug(this,"received_test2","/test2");
  
  // send test message
  sendTestMsg();
}

public void received_test2(int a1, float a2, String a3, byte[] a4) {
  println("\nreceived /test2 "+a1+", "+a2+" "+a3);
  println("Blob contents:");
  for(int n=0; n<a4.length; n++) print(" "+hex(a4[n]));
  println();  
}

void draw() {
  background(0);
}

void sendTestMsg() {        
  OscMessage oscMsg= oscP5.newMsg("/test");
  oscMsg.add(mouseY);
  oscMsg.add(54.32);
  oscMsg.add("Can you chatch this?"); 
  // add a byte blob to the osc message
  oscMsg.add(
     new byte[] {0x00, 0x01, 0x10, 0x20,0x30,0x40,0x50,0x60,0x7F,
       -128,-1,(byte)0x80,(byte)0x90,(byte)0xA0,(byte)0xB0,(byte)0xC0,
     (byte)0xD0,(byte)0xE0,(byte)0xFF});
 // 0x80,0x90,0xFE,0xFF etc do not work because byte is 127 thru -128.
 // so do it like: (byte)0xFF
  oscP5.send(oscMsg, remoteHost); 
}

void mousePressed() {
  OscMessage myMessage = new OscMessage("/mouse/pressed");
  myMessage.add(mouseX); // add an int to the osc message
  myMessage.add(mouseY); // add a second int to the osc message
  // send the message
  oscP5.send(myMessage, remoteHost);
 // 
  sendTestMsg();
}

void mouseDragged() { 
  OscMessage oscMsg= oscP5.newMsg("/mouse/dragged");
  oscMsg.add(mouseX);
  oscMsg.add(mouseY);
  oscP5.send(oscMsg, remoteHost); 
//
  oscMsg= oscP5.newMsg("/1/xy");
  oscMsg.add(mouseX*1.0/width);
  oscMsg.add(mouseY*1.0/height);
  oscMsg.add(1); // button status:pressed
  oscP5.send(oscMsg, remoteHost); 
}

void mouseReleased() {        
  OscMessage oscMsg= oscP5.newMsg("/1/xy");
  oscMsg.add(mouseX*1.0/width);
  oscMsg.add(mouseY*1.0/height);
  oscMsg.add(0); // button status:released
  oscP5.send(oscMsg, remoteHost); 
}

// incoming osc message are forwarded to the oscEvent method.
void oscEvent(OscMessage theOscMessage) {
  // with theOscMessage.isPlugged() you check if the osc message has already been
  // forwarded to a plugged method. if theOscMessage.isPlugged()==true, it has already 
  // been forwared to another method in your sketch. theOscMessage.isPlugged() can 
  // be used for double posting but is not required.
  //  
  if(theOscMessage.isPlugged()==false) {
  // print the address pattern and the typetag of the received OscMessage
  println("### received an osc message.");
  println("### addrpattern\t"+theOscMessage.addrPattern());
  println("### typetag\t"+theOscMessage.typetag());
  }
}

*/
//----------------------------------------------------------------------------------------------------------