Alvaro Cassinelli / Mbed 2 deprecated skinGames_forktest

Dependencies:   mbed

Fork of scoreLight_Advanced by Alvaro Cassinelli

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 /*
00015  Set PortNo for the OSC Message
00016  @param[in] _port PortNo (unsigned int)
00017  @return None
00018  */
00019 void OSCMessage::setPort(uint16_t _port){
00020      host.setPort(_port);
00021 }
00022 
00023 /*
00024  Set IP Address of the OSC Message (for SENDING messages - for receiving this will be done when receiving something ) 
00025  param[in] <-- _ip pointer of IP Address array (byte *)
00026  Example: IP=192.168.0.99, then we have to do: ip[]={192,168,0,1}, then setIp(ip)
00027  */
00028 void OSCMessage::setIp(uint8_t *_ip){
00029     host.setIp(IpAddr(_ip[0], _ip[1], _ip[2], _ip[3]));
00030 }
00031 
00032 
00033 /*!
00034  Set IP Address to the OSC Message container (not through pointer)
00035  Example: IP=192.168.0.99 => setIp(192,168,0,99)
00036  */
00037 void OSCMessage::setIp(    uint8_t _ip1,
00038                         uint8_t _ip2,
00039                         uint8_t _ip3,
00040                         uint8_t _ip4 ){
00041     
00042     host.setIp(IpAddr(_ip1, _ip2, _ip3, _ip4));
00043 }
00044 
00045 const IpAddr& OSCMessage::getIp(){
00046     return host.getIp();
00047 }
00048 
00049 
00050  const int& OSCMessage::getPort(){
00051     return host.getPort();
00052 }
00053 
00054 
00055 /*
00056  Gets the number of the OSC message address
00057  param[in] None
00058  return number of the OSC message address (byte)
00059  Examples: "/ard"      --> the number of the addresses is 1
00060            "/ard/test" --> the number of the addresses is 2
00061  Attention: the maximum number of addresses is 2 (MAX_ADDRESS)
00062 */
00063 uint8_t    OSCMessage::getAddressNum(){
00064     
00065     return addressNum;
00066 }
00067 
00068 
00069 /*
00070  Gets the number of the OSC message args
00071  param[in] None
00072  return number of the args (byte)
00073  Example: "i" 123 --> number of the OSC message args is 1
00074           "if" 123 54.24 --> number of the OSC message args is 2
00075  Attention: the maximum number of args is 2 (MAX_ARG)
00076  */
00077 uint8_t    OSCMessage::getArgNum(){
00078     
00079     return argNum;
00080 }
00081 
00082 
00083 /*
00084  Gets the address string of the OSC message
00085  param [in] <-- _index is the index of the address string (byte)
00086  return pointer of the address string (char *)
00087  @note ex. "/ard/test"<br>
00088  getAddress(0) = "/ard"<br>
00089  getAddress(1) = "/test"
00090  @attention It is maximum number of the addresses is 2<br>
00091  In this case "/ard/test1/test2"<br>
00092  ignore it after "/test2"
00093  */
00094 char * OSCMessage::getAddress(uint8_t _index){
00095     if(_index>MAX_ADDRESS) _index=MAX_ADDRESS-1;
00096     return address[_index];
00097     
00098 }
00099 
00100 
00101 /*
00102  Gets the TopAddress string of the OSC message (this is just the address with index 0)
00103  param[in] None
00104  return pointer of the TopAddress string (char *), i.e. address[0]
00105  Example: In the case "/ard/test", getTopAddress() = "/ard" (WITH the slash "/") 
00106  */
00107 char * OSCMessage::getTopAddress(){
00108     
00109     return getAddress(0);
00110     
00111 }
00112 
00113 /*
00114  Gets the "SubAddress" string of the OSC message (this is just the address with index 1)
00115  param[in] None
00116  return pointer of the SubAddress string (char *), i.e. address[1]
00117  Example: in the case "/ard/test", getSubAddress() = "/test" (WITH the slash "/") 
00118  */
00119 char * OSCMessage::getSubAddress(){
00120     
00121     return getAddress(1);
00122     
00123 }
00124 
00125 /*
00126  Gets the TypeTag string (with index) of the OSC message
00127  param[in] <--_index is the index of the TypeTag string (byte)
00128  return: TypeTag char (char)
00129  Example: in the case of a total typetag string equal to "if", getTypeTag(0) = 'i' and getTypeTag(1) = 'f'
00130  Attention: MAX_ARG is maximum number of the args, if the index argument is larger, it will be constrained to this max. 
00131  */
00132 char  OSCMessage::getTypeTag(uint8_t _index){
00133     if(_index>MAX_ARG) _index=MAX_ARG-1;
00134     return typeTag[_index];
00135 }
00136 
00137 /*
00138  Get the args of the OSC message with an integer value
00139  param[in] <--_index is (an int, or uint8_t), corresponding to the index of the args (byte)
00140  return: integer value (long, or int32_t)
00141  Example: in the case "if" 123 54.24, getArgInt(0) = 123
00142  Noe: "i" is integer, but the return type is "long"
00143  Note: When a index is bigger than the number of the args, it is set to the number of the args
00144  */
00145 int32_t OSCMessage::getArgInt(uint8_t _index){
00146     int32_t *value;
00147     if(_index > argNum) _index=argNum;
00148     value = (int32_t *)arg[_index]; // cast to int32_t
00149     return *value;
00150 }
00151 
00152 /*
00153  Get the args of the OSC message with a float value
00154  param[in] <--_index is the index of the args
00155  return: float value (double)
00156  note: In this case "if" 123 54.24, getArgFloat(1) = 54.24
00157  attention: arg declared as float, but return value cast as "double"
00158  attention: When index is bigger than the number of the args, it is set to the number of the args
00159  */
00160 double OSCMessage::getArgFloat(uint8_t _index){
00161     double *value;
00162     if(_index > argNum) _index=argNum;
00163     value = (double *)arg[_index];
00164     return *value;
00165 }
00166 
00167 /*
00168  Set TopAddress string of OSC Message 
00169  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?
00170  return: None
00171  Example: if the complete address string is "/ard/test", we set the topaddress as follows: char top[]="/ard" (allocation done here!), then setTopAddress(top)
00172  */
00173 void OSCMessage::setTopAddress(char *_address){
00174     address[0]=_address;
00175     address[1]=0;
00176     addressNum=1; // Note: this "erases" the subaddress! (is this a good idea?)
00177 }
00178 
00179 /*
00180  Set SubAddress string of the OSC Message
00181  param[in] <-- _address is a string pointer for the SubAddress String (char *)
00182  return: None
00183  Example:  if the complete address string is "/ard/test", we set the subaddress as follows: char sub[]="/test" (allocation done here!), then setSubAddress(sub)
00184  Attention: we should call first setTopAddress, and then setSubAddress. The order is important. This does not seems like a good idea...
00185  */
00186 void OSCMessage::setSubAddress(char *_address){
00187     address[1]=_address;
00188     addressNum=2; // Note: this assumes the top address was already set!
00189 }
00190 
00191 
00192 /*
00193  Set the complete Address string of the OSC Message (top and sub addresses)
00194  param[in] <-- _topAddress and _subAddress are the string pointers to top and sub addresses (char *)
00195  return: None
00196  Example: in the case "/ard/test", we need to do: char top[]="/ard", char sub[]="/test", and then setAddress(top,sub)
00197  Reminder: in this implementation, the maximum number of addresses is MAX_ADDRESS=2
00198  */
00199 void OSCMessage::setAddress(char *_topAddress,char *_subAddress){
00200     setTopAddress(_topAddress);
00201     setSubAddress(_subAddress);
00202     addressNum=2; // (unnecessary...)
00203 }
00204 
00205 /*
00206  Set address string using index (here 0 or 1)
00207  Example: "/ard/test", char adr[]="/ard", setAddress(0,adr), char adr2[]="/test", setAddress(1,adr)
00208  */
00209 void OSCMessage::setAddress(uint8_t _index, char *_address){
00210     if(_index>MAX_ADDRESS) _index=MAX_ADDRESS-1;
00211     address[_index]=_address;
00212     addressNum=_index+1;
00213 }
00214 
00215 
00216 /*
00217  Set TypeTag and args to the OSC Message container
00218  @param[in] types TypeTag string "i"(integer) or"f"(float) (char *)
00219  @param[in] ... Pointer of the Args(variable argument) ..
00220  @return None
00221  @Example: 
00222  (1) integer 123: (NOTE: integers are LONG)
00223  long v1=123; sendMes.setArgs("i",&v1)
00224  (2)integer:123 and float:52.14
00225  long v1=123; double v2=52.14; sendMes.setArgs("if",&v1,&v2)
00226  Attention: in this implementation, the maximum number of the args is 2
00227  (if setArgs("iff",&v1,&v2,&v3), data is ignored after &v3)
00228  */
00229 void OSCMessage::setArgs(char *types,...){
00230     
00231     va_list argList;
00232     
00233     argNum = strlen(types);
00234     if(argNum>MAX_ARG) argNum=MAX_ARG-1;
00235     
00236     va_start( argList, types );
00237     for(uint8_t i=0 ; i < argNum ; i++){
00238         
00239         typeTag[i]=types[i];
00240         
00241         switch(types[i]) {
00242             case 'i':
00243                 arg[i]=(uint32_t *)va_arg(argList, uint32_t *);
00244                 break;
00245             case 'f':
00246                 arg[i]=va_arg(argList, double *);
00247                 break;
00248            // case 'b': // blob
00249            //     arg[i]=va_arg(argList, double *);
00250            //     break;
00251         }
00252         
00253     }
00254     
00255 }
00256 
00257 void OSCMessage::clearArgs() {
00258     argNum=0;
00259 }
00260 
00261 // ================================================================================================================================================
00262 // ====================================  OSCClass for sending and receiving OSC messages using UDP protocol =======================================
00263 // ================================================================================================================================================
00264 //The class define an object wrapping the UDP functions to send and receive OSC messages
00265 
00266 OSCClass::OSCClass(){
00267     newMessage=false;
00268 }
00269 
00270 /*
00271  This sets "binds" the received message to the receiver container of the communication object
00272  param[in]<--_mes is a pointer to the "receiveing" OSC message (OSCMessage *)
00273  */
00274 OSCClass::OSCClass(OSCMessage *_mes){
00275     receiverMessage = _mes; // note: receiverMessage MUST be a pointer to the message, because we will modify things in it
00276     newMessage=false;
00277 }
00278 
00279 /*
00280  This initializes the OSC communication object with default receiving port (DEFAULT_REC_PORT)
00281  param[in]: None
00282  return: None
00283  */
00284 void OSCClass::begin(void (*pcallbackOnPacketArrival)(UDPSocketEvent))
00285 {    
00286   // setup receiver udp socket, as well as callback function:
00287   udpRec.bind(receiverMessage->host);
00288   udpRec.setOnEvent(pcallbackOnPacketArrival); // note: onUDPSocketEvent is a member of OSCClass
00289 }
00290 
00291 /*
00292  Initialize an OSC object with arbitrary listening port
00293  param[in] <-- _recievePort, is the listening ("receiving") Port No (unsigned int)
00294  return: None
00295  */
00296 void OSCClass::begin(uint16_t _recievePort, void (*pcallbackOnPacketArrival)(UDPSocketEvent))
00297 {
00298   receiverMessage->host.setPort(_recievePort);
00299   // setup receiver udp socket, as well as callback function:
00300   udpRec.bind(receiverMessage->host);
00301   udpRec.setOnEvent(pcallbackOnPacketArrival);
00302 }
00303 
00304 /*
00305  Set a OSC receive message container
00306  param[in] _mes Pointer to the OSC receive message container (OSCMessage *)
00307  return None
00308  */
00309 void OSCClass::setReceiveMessage(OSCMessage *_mes){
00310     receiverMessage = _mes;
00311 }
00312 
00313 /*
00314  callback function when an upd message arrives (it will be transformed as OSC message)
00315  */
00316 void OSCClass::onUDPSocketEvent(UDPSocketEvent e)
00317 {
00318   switch(e)
00319   {
00320   case UDPSOCKET_READABLE: //The only event for now
00321     //char buf[256] = {0};
00322     Host auxhost;
00323     buflength = udpRec.recvfrom( rcvBuff, 256, &auxhost ); // QUESTION: auxhost should be equal to the receiver host I guess...
00324     if ( buflength > 0 ) {
00325       //printf("\r\nFrom %d.%d.%d.%d:\r\n", host.getIp()[0], host.getIp()[1], host.getIp()[2], host.getIp()[3]);   
00326       decodePacket(receiverMessage); // convert to OSC message, and save it in receiverMessage
00327       newMessage=true;
00328     }
00329   break;
00330   }
00331 }
00332 
00333 /*
00334  Decode UDP packet and save it in the OSCMessage structure
00335  */
00336 void OSCClass::decodePacket( OSCMessage *_mes) {
00337     
00338     //uint16_t    lenBuff;
00339     uint8_t        d;    
00340     uint8_t        messagePos=0;    
00341     uint8_t        adrCount=0;
00342     uint8_t        adrMesPos=0;    
00343     uint8_t        packetCount=0;
00344     uint8_t        packetPos=4;
00345     
00346     
00347     //W5100.writeSn(socketNo, SnIR, SnIR::RECV);
00348     //lenBuff=recvfrom(socketNo, rcvBuff, 1, receiverMessage->ip, &receiverMessage->port);    
00349     
00350     receiverMessage->address[0]=tempAddress[0];
00351 
00352     //(1) address process start =========================================
00353     do{
00354         d=rcvBuff[messagePos];
00355 
00356         
00357         if( (d=='/') && (messagePos>0) ){
00358 
00359             if(adrCount<MAX_ADDRESS){
00360                 tempAddress[adrCount][adrMesPos]=0;
00361 
00362                 adrCount++;
00363                 adrMesPos=0;
00364 
00365                 receiverMessage->address[adrCount]=tempAddress[adrCount];
00366             }
00367 
00368         }
00369         
00370         if(adrCount<MAX_ADDRESS){
00371         //Added this in to remove the slashes out of final output
00372         if(d!='/'){
00373         tempAddress[adrCount][adrMesPos]=d;            
00374     
00375         if(packetCount>3)  {
00376             packetCount=0;
00377             packetPos+=4;
00378         }
00379         
00380         adrMesPos++;
00381         }
00382         }
00383         messagePos++;
00384         packetCount++;
00385         
00386     }while(d!=0);
00387 
00388     
00389     if(adrCount<MAX_ADDRESS) adrCount++;
00390     receiverMessage->addressNum=adrCount;
00391     
00392     messagePos=packetPos;
00393 
00394     //(2) type tag process starts =========================================
00395     packetCount=0;
00396     packetPos+=4;
00397 
00398     uint8_t  typeTagPos=0;
00399     uint8_t     tempArgNum=0;
00400 
00401     while(rcvBuff[messagePos]!=0 ){
00402             
00403         if(rcvBuff[messagePos] != ',') {
00404         
00405                 if(typeTagPos<MAX_ARG){
00406                     receiverMessage->typeTag[tempArgNum]=rcvBuff[messagePos];
00407                     tempArgNum++;
00408                 }
00409                 typeTagPos++;
00410                 
00411             }
00412         
00413         packetCount++;
00414         
00415         if(packetCount>3)  {
00416             packetCount=0;
00417             packetPos+=4;
00418         }
00419         
00420         messagePos++;
00421     }
00422     
00423     receiverMessage->argNum=tempArgNum;
00424 
00425     messagePos=packetPos;
00426 
00427     //(3) tempArg process starts =========================================
00428     for(int i=0;i<tempArgNum;i++){
00429         
00430         adrMesPos=3;
00431 
00432         receiverMessage->arg[i]=tempArg[i];
00433     
00434         for(int j=0;j<4;j++){
00435 
00436             tempArg[i][adrMesPos]=rcvBuff[messagePos];
00437 
00438             messagePos++;
00439             adrMesPos--;
00440         }
00441     
00442     }
00443 
00444 
00445 }
00446 
00447 
00448 /*
00449  Get the received OSC message (note: this is another way to access the message directly from the OSCClass object).
00450  The advantage is that we will signal that we read the message, and will be able to query if a NEW message arrived
00451  (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) 
00452  */
00453 OSCMessage * OSCClass::getMessage(){
00454     newMessage=false; // this indicate the user READ the message
00455     return receiverMessage;
00456 }
00457 
00458 /*
00459  Send an OSC Message (message contain the host ip and port where the message data has to be sent)
00460  param[in] _mes Pointer to the OSC message container (OSCMessage *)
00461  return None
00462  */
00463 void OSCClass::sendOsc( OSCMessage *_mes )
00464 {
00465     uint8_t lengthEnd;
00466     uint8_t lengthStart;    
00467     char  buff[128];
00468     
00469     sendContainer = _mes;
00470     
00471     //&#12496;&#12483;&#12501;&#12449;&#21021;&#26399;&#20516;
00472     buff[0]=0;
00473     
00474     //1) Add name spaces:
00475     for(int i=0;i<sendContainer->addressNum;i++){
00476         
00477         strcat(buff,sendContainer->address[i]); // note: an address is for instance: "/test" (including the "/")
00478         
00479     }
00480 
00481     // pad with 0s to align in multiples of 4:
00482     lengthStart=strlen(buff);
00483     lengthEnd=lengthStart+(4-(lengthStart%4));
00484     for(int i=lengthStart ; i<lengthEnd; i++){
00485         buff[i]=0;  
00486     }
00487 
00488     lengthStart=lengthEnd;
00489     
00490     //2) Add TypeTag:
00491     buff[lengthEnd++]=','; // Note: type tag is for instance: ",if"
00492     for(int i=0;i<sendContainer->argNum;i++){
00493         buff[lengthEnd++]=sendContainer->typeTag[i];
00494     }
00495     
00496     // pad with 0s to align in multiples of 4:
00497     lengthStart=lengthEnd;
00498     lengthEnd=lengthStart+(4-(lengthStart%4));
00499     for(int i=lengthStart ; i<lengthEnd; i++){
00500         buff[i]=0;
00501     }
00502     
00503     //3) add argument values (Note: here only big endian, this is, FIRST the MOST SIGNIFICANT BYTE):
00504     uint8_t *v;
00505     for(int i=0;i<sendContainer->argNum;i++){
00506         uint8_t valuePos=3;
00507         v=(uint8_t *)sendContainer->arg[i];
00508 
00509         buff[lengthEnd++]=v[valuePos--];
00510         buff[lengthEnd++]=v[valuePos--];
00511         buff[lengthEnd++]=v[valuePos--];
00512         buff[lengthEnd++]=v[valuePos]; 
00513         
00514     }
00515     
00516     //4) Send udp packet: 
00517     //sendto(    socketNo, (uint8_t *)buff, lengthEnd, sendContainer->ip, sendContainer->port );
00518     udpSend.sendto(buff , lengthEnd, &(sendContainer->host));
00519 }
00520 
00521 // this is bad, should be integrated on the above, but no time:
00522 void OSCClass::sendOscBlob( uint8_t * myblob, int sizeblob, OSCMessage *_mes )
00523 {  
00524     
00525     // esto es mamarrachezco: 
00526      sendContainer = _mes;
00527      
00528     uint8_t lengthEnd;
00529     uint8_t lengthStart;    
00530     
00531     char  buff[50+sizeblob];
00532     buff[0]=0;
00533     
00534     //1) Add name spaces (will be just '/posblob' for the blob)
00535     strcat(buff,"/posblob"); 
00536 
00537     // pad with 0s to align in multiples of 4:
00538     lengthStart=strlen(buff);
00539     lengthEnd=lengthStart+(4-(lengthStart%4));
00540     for(int i=lengthStart ; i<lengthEnd; i++){
00541         buff[i]=0;  
00542     }
00543 
00544     lengthStart=lengthEnd;
00545     
00546     //2) Add TypeTag:
00547     buff[lengthEnd++]=','; //here type tag is just ",b" (one blob)
00548     buff[lengthEnd++]='b';
00549     
00550     // pad with 0s to align in multiples of 4:
00551     lengthStart=lengthEnd;
00552     lengthEnd=lengthStart+(4-(lengthStart%4));
00553     for(int i=lengthStart ; i<lengthEnd; i++){
00554         buff[i]=0;
00555     }
00556     
00557     //3) add blob (Note: here it is up to the user to get the values right - big endian?):
00558     // First the size (as an int32, where the type int32 is a 32-bit big-endian two's complement integer) 
00559     buff[lengthEnd++]=0;
00560     buff[lengthEnd++]=0;
00561     buff[lengthEnd++]=0;
00562     buff[lengthEnd++]=(char)sizeblob; // note: the loops always have less than 255 points...
00563     // Add blob data: 
00564     memcpy(&(buff[lengthEnd]), myblob, sizeblob);
00565     // pad with 0s to align in multiples of 4:
00566     lengthStart=lengthEnd+sizeblob;
00567     lengthEnd=lengthStart+(4-(lengthStart%4));
00568     for(int i=lengthStart ; i<lengthEnd; i++){
00569         buff[i]=0;
00570     }
00571     
00572     //4) Send udp packet: 
00573     //sendto(    socketNo, (uint8_t *)buff, lengthEnd, sendContainer->ip, sendContainer->port );
00574     udpSend.sendto(buff , lengthEnd, &(sendContainer->host));
00575 }
00576 
00577 // NOT FINISHED!!!!
00578 void OSCClass::sendOscString( uint8_t * myblob, int sizeblob, OSCMessage *_mes )
00579 {  
00580     uint8_t lengthEnd;
00581     uint8_t lengthStart;    
00582     
00583     char  buff[50+sizeblob];
00584     buff[0]=0;
00585     
00586     //1) Add name spaces (will be just '/posblob' for the blob)
00587     strcat(buff,"/posString"); 
00588 
00589     // pad with 0s to align in multiples of 4:
00590     lengthStart=strlen(buff);
00591     lengthEnd=lengthStart+(4-(lengthStart%4));
00592     for(int i=lengthStart ; i<lengthEnd; i++){
00593         buff[i]=0;  
00594     }
00595 
00596     lengthStart=lengthEnd;
00597     
00598     //2) Add TypeTag:
00599     buff[lengthEnd++]=','; //here type tag is just ",b" (one blob)
00600     buff[lengthEnd++]='s';
00601     
00602     // pad with 0s to align in multiples of 4:
00603     lengthStart=lengthEnd;
00604     lengthEnd=lengthStart+(4-(lengthStart%4));
00605     for(int i=lengthStart ; i<lengthEnd; i++){
00606         buff[i]=0;
00607     }
00608     
00609     // Add blob data: 
00610     memcpy(&(buff[lengthEnd]), myblob, sizeblob);
00611     // pad with 0s to align in multiples of 4:
00612     lengthStart=lengthEnd+sizeblob;
00613     lengthEnd=lengthStart+(4-(lengthStart%4));
00614     for(int i=lengthStart ; i<lengthEnd; i++){
00615         buff[i]=0;
00616     }
00617     
00618     //4) Send udp packet: 
00619     //sendto(    socketNo, (uint8_t *)buff, lengthEnd, sendContainer->ip, sendContainer->port );
00620     udpSend.sendto(buff , lengthEnd, &(sendContainer->host));
00621 }
00622 
00623 /*
00624  flush a receive buffer
00625 void OSCClass::flush() {    
00626     while ( available() ){}
00627 }
00628 */
00629 
00630 /*
00631  Stop OSC communication (in fact, only the receiver - the server side)
00632  */
00633 void OSCClass::stop() {
00634     //close( socketNo );
00635     udpSend.resetOnEvent(); // disables callback
00636 }
00637 
00638