Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of scoreLight_Advanced by
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 //バッファ初期値 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
Generated on Tue Jul 12 2022 18:50:27 by
1.7.2
