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

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers mbedOSC.cpp Source File

mbedOSC.cpp

00001 /*
00002  mbedOSC.cpp 
00003 */                    
00004    
00005 #include "mbed.h"
00006 #include "mbedOSC.h"
00007 #include "stdarg.h"
00008 
00009 OSCMessage::OSCMessage() {
00010  // Initialize host address and port by default (as if this where the receiver message):
00011  //    host=new Host(IpAddr(10, 0, 0, 1), DEFAULT_RECEIVE_PORT, NULL);
00012 }
00013 
00014 void OSCMessage::setPort(uint16_t _port){
00015      host.setPort(_port);
00016 }
00017 
00018 
00019 void OSCMessage::setIp(uint8_t *_ip){
00020     host.setIp(IpAddr(_ip[0], _ip[1], _ip[2], _ip[3]));
00021 }
00022 
00023 
00024 
00025 void OSCMessage::setIp(    uint8_t _ip1,
00026                         uint8_t _ip2,
00027                         uint8_t _ip3,
00028                         uint8_t _ip4 ){
00029     
00030     host.setIp(IpAddr(_ip1, _ip2, _ip3, _ip4));
00031 }
00032 
00033 const IpAddr& OSCMessage::getIp(){
00034     return host.getIp();
00035 }
00036 
00037 
00038  const int& OSCMessage::getPort(){
00039     return host.getPort();
00040 }
00041 
00042 
00043 
00044 uint8_t    OSCMessage::getAddressNum(){
00045     
00046     return addressNum;
00047 }
00048 
00049 
00050 uint8_t    OSCMessage::getArgNum(){
00051     
00052     return argNum;
00053 }
00054 
00055 
00056 
00057 char * OSCMessage::getAddress(uint8_t _index){
00058     if(_index>MAX_ADDRESS) _index=MAX_ADDRESS-1;
00059     return address[_index];
00060     
00061 }
00062 
00063 
00064 
00065 char * OSCMessage::getTopAddress(){
00066     
00067     return getAddress(0);
00068     
00069 }
00070 
00071 
00072 char * OSCMessage::getSubAddress(){
00073     
00074     return getAddress(1);
00075     
00076 }
00077 
00078 
00079 char  OSCMessage::getTypeTag(uint8_t _index){
00080     if(_index>MAX_ARG) _index=MAX_ARG-1;
00081     return typeTag[_index];
00082 }
00083 
00084 
00085 int32_t OSCMessage::getArgInt(uint8_t _index){
00086     int32_t *value;
00087     if(_index > argNum) _index=argNum;
00088     value = (int32_t *)arg[_index]; // cast to int32_t
00089     return *value;
00090 }
00091 
00092 
00093 double OSCMessage::getArgFloat(uint8_t _index){
00094     float *value;
00095     if(_index > argNum) _index=argNum;
00096     value = (float *)arg[_index]; // cast to float not double for correct parsing on mbed!
00097     return *value;
00098 }
00099 
00100 
00101 void OSCMessage::setTopAddress(char *_address){
00102     address[0]=_address;
00103     address[1]=0;
00104     addressNum=1; // Note: this "erases" the subaddress! (is this a good idea?)
00105 }
00106 
00107 
00108 void OSCMessage::setSubAddress(char *_address){
00109     address[1]=_address;
00110     addressNum=2; // Note: this assumes the top address was already set!
00111 }
00112 
00113 
00114 
00115 void OSCMessage::setAddress(char *_topAddress,char *_subAddress){
00116     setTopAddress(_topAddress);
00117     setSubAddress(_subAddress);
00118     addressNum=2; // (unnecessary...)
00119 }
00120 
00121 
00122 void OSCMessage::setAddress(uint8_t _index, char *_address){
00123     if(_index>MAX_ADDRESS) _index=MAX_ADDRESS-1;
00124     address[_index]=_address;
00125     addressNum=_index+1;
00126 }
00127 
00128 
00129 
00130 void OSCMessage::setArgs(char *types,...){
00131     
00132     va_list argList;
00133     
00134     argNum = strlen(types);
00135     if(argNum>MAX_ARG) argNum=MAX_ARG-1;
00136     
00137     va_start( argList, types );
00138     for(uint8_t i=0 ; i < argNum ; i++){
00139         
00140         typeTag[i]=types[i];
00141         
00142         switch(types[i]) {
00143             case 'i':
00144                 arg[i]=(uint32_t *)va_arg(argList, uint32_t *);
00145                 break;
00146             case 'f':
00147                 arg[i]=va_arg(argList, double *);
00148                 break;
00149         }   
00150     }
00151 }
00152 
00153 // ================================================================================================================================================
00154 // ====================================  OSCClass for sending and receiving OSC messages using UDP protocol =======================================
00155 // ================================================================================================================================================
00156 //The class define an object wrapping the UDP functions to send and receive OSC messages
00157 
00158 OSCClass::OSCClass(){
00159     udpRec.setOnEvent(this, &OSCClass::onUDPSocketEvent);
00160     newMessage=false;
00161 }
00162 
00163 OSCClass::~OSCClass(){
00164     udpSend.resetOnEvent();
00165     udpRec.close();
00166 }
00167 
00168 OSCClass::OSCClass(OSCMessage *_mes){
00169     udpRec.setOnEvent(this, &OSCClass::onUDPSocketEvent);
00170     receiverMessage = _mes; // note: receiverMessage MUST be a pointer to the message, because we will modify things in it
00171     newMessage=false;
00172 }
00173 
00174 void OSCClass::begin()
00175 {    
00176   // setup receiver udp socket:
00177   udpRec.bind(receiverMessage->host);
00178 }
00179 
00180 
00181 void OSCClass::begin(uint16_t _recievePort)
00182 {
00183   receiverMessage->host.setPort(_recievePort);
00184   // setup receiver udp socket:
00185   udpRec.bind(receiverMessage->host);
00186 }
00187 
00188 
00189 void OSCClass::setReceiveMessage(OSCMessage *_mes){
00190     receiverMessage = _mes;
00191 }
00192 
00193 void OSCClass::onUDPSocketEvent(UDPSocketEvent e)
00194 {
00195   switch(e)
00196   {
00197   case UDPSOCKET_READABLE: //The only event for now
00198     //char buf[256] = {0};
00199     Host auxhost;
00200     buflength = udpRec.recvfrom( rcvBuff, 256, &auxhost ); // QUESTION: auxhost should be equal to the receiver host I guess...
00201     if ( buflength > 0 ) {
00202       //printf("\r\nFrom %d.%d.%d.%d:\r\n", host.getIp()[0], host.getIp()[1], host.getIp()[2], host.getIp()[3]);   
00203       decodePacket(receiverMessage); // convert to OSC message, and save it in receiverMessage
00204       newMessage=true;
00205       
00206       messageReceivedCallback.call();
00207     }
00208   break;
00209   }
00210 }
00211 
00212 /*
00213  Decode UDP packet and save it in the OSCMessage structure
00214  */
00215 void OSCClass::decodePacket( OSCMessage *_mes) {
00216     
00217     //uint16_t    lenBuff;
00218     uint8_t        d;    
00219     uint8_t        messagePos=0;    
00220     uint8_t        adrCount=0;
00221     uint8_t        adrMesPos=0;    
00222     uint8_t        packetCount=0;
00223     uint8_t        packetPos=4;
00224     
00225     
00226     //W5100.writeSn(socketNo, SnIR, SnIR::RECV);
00227     //lenBuff=recvfrom(socketNo, rcvBuff, 1, receiverMessage->ip, &receiverMessage->port);    
00228     
00229     receiverMessage->address[0]=tempAddress[0];
00230 
00231     //(1) address process start =========================================
00232     do{
00233         d=rcvBuff[messagePos];
00234 
00235         
00236         if( (d=='/') && (messagePos>0) ){
00237 
00238             if(adrCount<MAX_ADDRESS){
00239                 tempAddress[adrCount][adrMesPos]=0;
00240 
00241                 adrCount++;
00242                 adrMesPos=0;
00243 
00244                 receiverMessage->address[adrCount]=tempAddress[adrCount];
00245             }
00246 
00247         }
00248         
00249         if(adrCount<MAX_ADDRESS){
00250         //Added this in to remove the slashes out of final output
00251         if(d!='/'){
00252         tempAddress[adrCount][adrMesPos]=d;            
00253     
00254         if(packetCount>3)  {
00255             packetCount=0;
00256             packetPos+=4;
00257         }
00258         
00259         adrMesPos++;
00260         }
00261         }
00262         messagePos++;
00263         packetCount++;
00264         
00265     }while(d!=0);
00266 
00267     
00268     if(adrCount<MAX_ADDRESS) adrCount++;
00269     receiverMessage->addressNum=adrCount;
00270     
00271     messagePos=packetPos;
00272 
00273     //(2) type tag process starts =========================================
00274     packetCount=0;
00275     packetPos+=4;
00276 
00277     uint8_t  typeTagPos=0;
00278     uint8_t     tempArgNum=0;
00279 
00280     while(rcvBuff[messagePos]!=0 ){
00281             
00282         if(rcvBuff[messagePos] != ',') {
00283         
00284                 if(typeTagPos<MAX_ARG){
00285                     receiverMessage->typeTag[tempArgNum]=rcvBuff[messagePos];
00286                     tempArgNum++;
00287                 }
00288                 typeTagPos++;
00289                 
00290             }
00291         
00292         packetCount++;
00293         
00294         if(packetCount>3)  {
00295             packetCount=0;
00296             packetPos+=4;
00297         }
00298         
00299         messagePos++;
00300     }
00301     
00302     receiverMessage->argNum=tempArgNum;
00303 
00304     messagePos=packetPos;
00305 
00306     //(3) tempArg process starts =========================================
00307     for(int i=0;i<tempArgNum;i++){
00308         
00309         adrMesPos=3;
00310 
00311         receiverMessage->arg[i]=tempArg[i];
00312     
00313         for(int j=0;j<4;j++){
00314 
00315             tempArg[i][adrMesPos]=rcvBuff[messagePos];
00316 
00317             messagePos++;
00318             adrMesPos--;
00319         }
00320     
00321     }
00322 
00323 
00324 }
00325 
00326 
00327 
00328 OSCMessage * OSCClass::getMessage(){
00329     newMessage=false; // this indicate the user READ the message
00330     return receiverMessage;
00331 }
00332 
00333 
00334 void OSCClass::sendOsc( OSCMessage *_mes )
00335 {
00336     uint8_t lengthEnd;
00337     uint8_t lengthStart;    
00338     char  buff[128];
00339     
00340     sendContainer = _mes;
00341     
00342     //&#12496;&#12483;&#12501;&#12449;&#21021;&#26399;&#20516;
00343     buff[0]=0;
00344     
00345     //1) Add name spaces:
00346     for(int i=0;i<sendContainer->addressNum;i++){
00347         
00348         strcat(buff,sendContainer->address[i]); // note: an address is for instance: "/test" (including the "/")
00349         
00350     }
00351 
00352     // pad with 0s to align in multiples of 4:
00353     lengthStart=strlen(buff);
00354     lengthEnd=lengthStart+(4-(lengthStart%4));
00355     for(int i=lengthStart ; i<lengthEnd; i++){
00356         buff[i]=0;  
00357     }
00358 
00359     lengthStart=lengthEnd;
00360     
00361     //2) Add TypeTag:
00362     buff[lengthEnd++]=','; // Note: type tag is for instance: ",if"
00363     for(int i=0;i<sendContainer->argNum;i++){
00364         buff[lengthEnd++]=sendContainer->typeTag[i];
00365     }
00366     
00367     // pad with 0s to align in multiples of 4:
00368     lengthStart=lengthEnd;
00369     lengthEnd=lengthStart+(4-(lengthStart%4));
00370     for(int i=lengthStart ; i<lengthEnd; i++){
00371         buff[i]=0;
00372     }
00373     
00374     //3) add argument values (Note: here only big endian):
00375     uint8_t *v;
00376     for(int i=0;i<sendContainer->argNum;i++){
00377         uint8_t valuePos=3;
00378         v=(uint8_t *)sendContainer->arg[i];
00379 
00380         buff[lengthEnd++]=v[valuePos--];
00381         buff[lengthEnd++]=v[valuePos--];
00382         buff[lengthEnd++]=v[valuePos--];
00383         buff[lengthEnd++]=v[valuePos]; 
00384         
00385     }
00386     
00387     //4) Send udp packet: 
00388     //sendto(    socketNo, (uint8_t *)buff, lengthEnd, sendContainer->ip, sendContainer->port );
00389     udpSend.sendto(buff , lengthEnd, &(sendContainer->host));
00390 }
00391 
00392 
00393 /*
00394  flush a receive buffer
00395 void OSCClass::flush() {    
00396     while ( available() ){}
00397 }
00398 */
00399 
00400 
00401 void OSCClass::stop() {
00402     //close( socketNo );
00403     udpSend.resetOnEvent(); // disables callback
00404 }
00405 
00406