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

Dependencies:   NetServices mbed

Committer:
tobyspark
Date:
Tue Mar 13 22:42:25 2012 +0000
Revision:
0:49cdaebd52d5
Child:
1:ab7dc9550de6
Changes:
- udpRec.setOnEvent is now properly encapsulated within the class
- the message received callback is now a public property using mbed\s FunctionPointer class
- swapped out the EthernetNetIf source for the NetService library, which despite the name is an updated version.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
tobyspark 0:49cdaebd52d5 1 /*
tobyspark 0:49cdaebd52d5 2 mbedOSC.cpp
tobyspark 0:49cdaebd52d5 3 */
tobyspark 0:49cdaebd52d5 4
tobyspark 0:49cdaebd52d5 5 #include "mbed.h"
tobyspark 0:49cdaebd52d5 6 #include "mbedOSC.h"
tobyspark 0:49cdaebd52d5 7 #include "stdarg.h"
tobyspark 0:49cdaebd52d5 8
tobyspark 0:49cdaebd52d5 9 OSCMessage::OSCMessage() {
tobyspark 0:49cdaebd52d5 10 // Initialize host address and port by default (as if this where the receiver message):
tobyspark 0:49cdaebd52d5 11 // host=new Host(IpAddr(10, 0, 0, 1), DEFAULT_RECEIVE_PORT, NULL);
tobyspark 0:49cdaebd52d5 12 }
tobyspark 0:49cdaebd52d5 13
tobyspark 0:49cdaebd52d5 14 /*
tobyspark 0:49cdaebd52d5 15 Set PortNo for the OSC Message
tobyspark 0:49cdaebd52d5 16 @param[in] _port PortNo (unsigned int)
tobyspark 0:49cdaebd52d5 17 @return None
tobyspark 0:49cdaebd52d5 18 */
tobyspark 0:49cdaebd52d5 19 void OSCMessage::setPort(uint16_t _port){
tobyspark 0:49cdaebd52d5 20 host.setPort(_port);
tobyspark 0:49cdaebd52d5 21 }
tobyspark 0:49cdaebd52d5 22
tobyspark 0:49cdaebd52d5 23 /*
tobyspark 0:49cdaebd52d5 24 Set IP Address of the OSC Message (for SENDING messages - for receiving this will be done when receiving something )
tobyspark 0:49cdaebd52d5 25 param[in] <-- _ip pointer of IP Address array (byte *)
tobyspark 0:49cdaebd52d5 26 Example: IP=192.168.0.99, then we have to do: ip[]={192,168,0,1}, then setIp(ip)
tobyspark 0:49cdaebd52d5 27 */
tobyspark 0:49cdaebd52d5 28 void OSCMessage::setIp(uint8_t *_ip){
tobyspark 0:49cdaebd52d5 29 host.setIp(IpAddr(_ip[0], _ip[1], _ip[2], _ip[3]));
tobyspark 0:49cdaebd52d5 30 }
tobyspark 0:49cdaebd52d5 31
tobyspark 0:49cdaebd52d5 32
tobyspark 0:49cdaebd52d5 33 /*!
tobyspark 0:49cdaebd52d5 34 Set IP Address to the OSC Message container (not through pointer)
tobyspark 0:49cdaebd52d5 35 Example: IP=192.168.0.99 => setIp(192,168,0,99)
tobyspark 0:49cdaebd52d5 36 */
tobyspark 0:49cdaebd52d5 37 void OSCMessage::setIp( uint8_t _ip1,
tobyspark 0:49cdaebd52d5 38 uint8_t _ip2,
tobyspark 0:49cdaebd52d5 39 uint8_t _ip3,
tobyspark 0:49cdaebd52d5 40 uint8_t _ip4 ){
tobyspark 0:49cdaebd52d5 41
tobyspark 0:49cdaebd52d5 42 host.setIp(IpAddr(_ip1, _ip2, _ip3, _ip4));
tobyspark 0:49cdaebd52d5 43 }
tobyspark 0:49cdaebd52d5 44
tobyspark 0:49cdaebd52d5 45 const IpAddr& OSCMessage::getIp(){
tobyspark 0:49cdaebd52d5 46 return host.getIp();
tobyspark 0:49cdaebd52d5 47 }
tobyspark 0:49cdaebd52d5 48
tobyspark 0:49cdaebd52d5 49
tobyspark 0:49cdaebd52d5 50 const int& OSCMessage::getPort(){
tobyspark 0:49cdaebd52d5 51 return host.getPort();
tobyspark 0:49cdaebd52d5 52 }
tobyspark 0:49cdaebd52d5 53
tobyspark 0:49cdaebd52d5 54
tobyspark 0:49cdaebd52d5 55 /*
tobyspark 0:49cdaebd52d5 56 Gets the number of the OSC message address
tobyspark 0:49cdaebd52d5 57 param[in] None
tobyspark 0:49cdaebd52d5 58 return number of the OSC message address (byte)
tobyspark 0:49cdaebd52d5 59 Examples: "/ard" --> the number of the addresses is 1
tobyspark 0:49cdaebd52d5 60 "/ard/test" --> the number of the addresses is 2
tobyspark 0:49cdaebd52d5 61 Attention: the maximum number of addresses is 2 (MAX_ADDRESS)
tobyspark 0:49cdaebd52d5 62 */
tobyspark 0:49cdaebd52d5 63 uint8_t OSCMessage::getAddressNum(){
tobyspark 0:49cdaebd52d5 64
tobyspark 0:49cdaebd52d5 65 return addressNum;
tobyspark 0:49cdaebd52d5 66 }
tobyspark 0:49cdaebd52d5 67
tobyspark 0:49cdaebd52d5 68
tobyspark 0:49cdaebd52d5 69 /*
tobyspark 0:49cdaebd52d5 70 Gets the number of the OSC message args
tobyspark 0:49cdaebd52d5 71 param[in] None
tobyspark 0:49cdaebd52d5 72 return number of the args (byte)
tobyspark 0:49cdaebd52d5 73 Example: "i" 123 --> number of the OSC message args is 1
tobyspark 0:49cdaebd52d5 74 "if" 123 54.24 --> number of the OSC message args is 2
tobyspark 0:49cdaebd52d5 75 Attention: the maximum number of args is 2 (MAX_ARG)
tobyspark 0:49cdaebd52d5 76 */
tobyspark 0:49cdaebd52d5 77 uint8_t OSCMessage::getArgNum(){
tobyspark 0:49cdaebd52d5 78
tobyspark 0:49cdaebd52d5 79 return argNum;
tobyspark 0:49cdaebd52d5 80 }
tobyspark 0:49cdaebd52d5 81
tobyspark 0:49cdaebd52d5 82
tobyspark 0:49cdaebd52d5 83 /*
tobyspark 0:49cdaebd52d5 84 Gets the address string of the OSC message
tobyspark 0:49cdaebd52d5 85 param [in] <-- _index is the index of the address string (byte)
tobyspark 0:49cdaebd52d5 86 return pointer of the address string (char *)
tobyspark 0:49cdaebd52d5 87 @note ex. "/ard/test"<br>
tobyspark 0:49cdaebd52d5 88 getAddress(0) = "/ard"<br>
tobyspark 0:49cdaebd52d5 89 getAddress(1) = "/test"
tobyspark 0:49cdaebd52d5 90 @attention It is maximum number of the addresses is 2<br>
tobyspark 0:49cdaebd52d5 91 In this case "/ard/test1/test2"<br>
tobyspark 0:49cdaebd52d5 92 ignore it after "/test2"
tobyspark 0:49cdaebd52d5 93 */
tobyspark 0:49cdaebd52d5 94 char * OSCMessage::getAddress(uint8_t _index){
tobyspark 0:49cdaebd52d5 95 if(_index>MAX_ADDRESS) _index=MAX_ADDRESS-1;
tobyspark 0:49cdaebd52d5 96 return address[_index];
tobyspark 0:49cdaebd52d5 97
tobyspark 0:49cdaebd52d5 98 }
tobyspark 0:49cdaebd52d5 99
tobyspark 0:49cdaebd52d5 100
tobyspark 0:49cdaebd52d5 101 /*
tobyspark 0:49cdaebd52d5 102 Gets the TopAddress string of the OSC message (this is just the address with index 0)
tobyspark 0:49cdaebd52d5 103 param[in] None
tobyspark 0:49cdaebd52d5 104 return pointer of the TopAddress string (char *), i.e. address[0]
tobyspark 0:49cdaebd52d5 105 Example: In the case "/ard/test", getTopAddress() = "/ard" (WITH the slash "/")
tobyspark 0:49cdaebd52d5 106 */
tobyspark 0:49cdaebd52d5 107 char * OSCMessage::getTopAddress(){
tobyspark 0:49cdaebd52d5 108
tobyspark 0:49cdaebd52d5 109 return getAddress(0);
tobyspark 0:49cdaebd52d5 110
tobyspark 0:49cdaebd52d5 111 }
tobyspark 0:49cdaebd52d5 112
tobyspark 0:49cdaebd52d5 113 /*
tobyspark 0:49cdaebd52d5 114 Gets the "SubAddress" string of the OSC message (this is just the address with index 1)
tobyspark 0:49cdaebd52d5 115 param[in] None
tobyspark 0:49cdaebd52d5 116 return pointer of the SubAddress string (char *), i.e. address[1]
tobyspark 0:49cdaebd52d5 117 Example: in the case "/ard/test", getSubAddress() = "/test" (WITH the slash "/")
tobyspark 0:49cdaebd52d5 118 */
tobyspark 0:49cdaebd52d5 119 char * OSCMessage::getSubAddress(){
tobyspark 0:49cdaebd52d5 120
tobyspark 0:49cdaebd52d5 121 return getAddress(1);
tobyspark 0:49cdaebd52d5 122
tobyspark 0:49cdaebd52d5 123 }
tobyspark 0:49cdaebd52d5 124
tobyspark 0:49cdaebd52d5 125 /*
tobyspark 0:49cdaebd52d5 126 Gets the TypeTag string (with index) of the OSC message
tobyspark 0:49cdaebd52d5 127 param[in] <--_index is the index of the TypeTag string (byte)
tobyspark 0:49cdaebd52d5 128 return: TypeTag char (char)
tobyspark 0:49cdaebd52d5 129 Example: in the case of a total typetag string equal to "if", getTypeTag(0) = 'i' and getTypeTag(1) = 'f'
tobyspark 0:49cdaebd52d5 130 Attention: MAX_ARG is maximum number of the args, if the index argument is larger, it will be constrained to this max.
tobyspark 0:49cdaebd52d5 131 */
tobyspark 0:49cdaebd52d5 132 char OSCMessage::getTypeTag(uint8_t _index){
tobyspark 0:49cdaebd52d5 133 if(_index>MAX_ARG) _index=MAX_ARG-1;
tobyspark 0:49cdaebd52d5 134 return typeTag[_index];
tobyspark 0:49cdaebd52d5 135 }
tobyspark 0:49cdaebd52d5 136
tobyspark 0:49cdaebd52d5 137 /*
tobyspark 0:49cdaebd52d5 138 Get the args of the OSC message with an integer value
tobyspark 0:49cdaebd52d5 139 param[in] <--_index is (an int, or uint8_t), corresponding to the index of the args (byte)
tobyspark 0:49cdaebd52d5 140 return: integer value (long, or int32_t)
tobyspark 0:49cdaebd52d5 141 Example: in the case "if" 123 54.24, getArgInt(0) = 123
tobyspark 0:49cdaebd52d5 142 Noe: "i" is integer, but the return type is "long"
tobyspark 0:49cdaebd52d5 143 Note: When a index is bigger than the number of the args, it is set to the number of the args
tobyspark 0:49cdaebd52d5 144 */
tobyspark 0:49cdaebd52d5 145 int32_t OSCMessage::getArgInt(uint8_t _index){
tobyspark 0:49cdaebd52d5 146 int32_t *value;
tobyspark 0:49cdaebd52d5 147 if(_index > argNum) _index=argNum;
tobyspark 0:49cdaebd52d5 148 value = (int32_t *)arg[_index]; // cast to int32_t
tobyspark 0:49cdaebd52d5 149 return *value;
tobyspark 0:49cdaebd52d5 150 }
tobyspark 0:49cdaebd52d5 151
tobyspark 0:49cdaebd52d5 152 /*
tobyspark 0:49cdaebd52d5 153 Get the args of the OSC message with a float value
tobyspark 0:49cdaebd52d5 154 param[in] <--_index is the index of the args
tobyspark 0:49cdaebd52d5 155 return: float value (double)
tobyspark 0:49cdaebd52d5 156 note: In this case "if" 123 54.24, getArgFloat(1) = 54.24
tobyspark 0:49cdaebd52d5 157 attention: arg declared as float, but return value cast as "double"
tobyspark 0:49cdaebd52d5 158 attention: When index is bigger than the number of the args, it is set to the number of the args
tobyspark 0:49cdaebd52d5 159 */
tobyspark 0:49cdaebd52d5 160 double OSCMessage::getArgFloat(uint8_t _index){
tobyspark 0:49cdaebd52d5 161 double *value;
tobyspark 0:49cdaebd52d5 162 if(_index > argNum) _index=argNum;
tobyspark 0:49cdaebd52d5 163 value = (double *)arg[_index];
tobyspark 0:49cdaebd52d5 164 return *value;
tobyspark 0:49cdaebd52d5 165 }
tobyspark 0:49cdaebd52d5 166
tobyspark 0:49cdaebd52d5 167 /*
tobyspark 0:49cdaebd52d5 168 Set TopAddress string of OSC Message
tobyspark 0:49cdaebd52d5 169 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?
tobyspark 0:49cdaebd52d5 170 return: None
tobyspark 0:49cdaebd52d5 171 Example: if the complete address string is "/ard/test", we set the topaddress as follows: char top[]="/ard" (allocation done here!), then setTopAddress(top)
tobyspark 0:49cdaebd52d5 172 */
tobyspark 0:49cdaebd52d5 173 void OSCMessage::setTopAddress(char *_address){
tobyspark 0:49cdaebd52d5 174 address[0]=_address;
tobyspark 0:49cdaebd52d5 175 address[1]=0;
tobyspark 0:49cdaebd52d5 176 addressNum=1; // Note: this "erases" the subaddress! (is this a good idea?)
tobyspark 0:49cdaebd52d5 177 }
tobyspark 0:49cdaebd52d5 178
tobyspark 0:49cdaebd52d5 179 /*
tobyspark 0:49cdaebd52d5 180 Set SubAddress string of the OSC Message
tobyspark 0:49cdaebd52d5 181 param[in] <-- _address is a string pointer for the SubAddress String (char *)
tobyspark 0:49cdaebd52d5 182 return: None
tobyspark 0:49cdaebd52d5 183 Example: if the complete address string is "/ard/test", we set the subaddress as follows: char sub[]="/test" (allocation done here!), then setSubAddress(sub)
tobyspark 0:49cdaebd52d5 184 Attention: we should call first setTopAddress, and then setSubAddress. The order is important. This does not seems like a good idea...
tobyspark 0:49cdaebd52d5 185 */
tobyspark 0:49cdaebd52d5 186 void OSCMessage::setSubAddress(char *_address){
tobyspark 0:49cdaebd52d5 187 address[1]=_address;
tobyspark 0:49cdaebd52d5 188 addressNum=2; // Note: this assumes the top address was already set!
tobyspark 0:49cdaebd52d5 189 }
tobyspark 0:49cdaebd52d5 190
tobyspark 0:49cdaebd52d5 191
tobyspark 0:49cdaebd52d5 192 /*
tobyspark 0:49cdaebd52d5 193 Set the complete Address string of the OSC Message (top and sub addresses)
tobyspark 0:49cdaebd52d5 194 param[in] <-- _topAddress and _subAddress are the string pointers to top and sub addresses (char *)
tobyspark 0:49cdaebd52d5 195 return: None
tobyspark 0:49cdaebd52d5 196 Example: in the case "/ard/test", we need to do: char top[]="/ard", char sub[]="/test", and then setAddress(top,sub)
tobyspark 0:49cdaebd52d5 197 Reminder: in this implementation, the maximum number of addresses is MAX_ADDRESS=2
tobyspark 0:49cdaebd52d5 198 */
tobyspark 0:49cdaebd52d5 199 void OSCMessage::setAddress(char *_topAddress,char *_subAddress){
tobyspark 0:49cdaebd52d5 200 setTopAddress(_topAddress);
tobyspark 0:49cdaebd52d5 201 setSubAddress(_subAddress);
tobyspark 0:49cdaebd52d5 202 addressNum=2; // (unnecessary...)
tobyspark 0:49cdaebd52d5 203 }
tobyspark 0:49cdaebd52d5 204
tobyspark 0:49cdaebd52d5 205 /*
tobyspark 0:49cdaebd52d5 206 Set address string using index (here 0 or 1)
tobyspark 0:49cdaebd52d5 207 Example: "/ard/test", char adr[]="/ard", setAddress(0,adr), char adr2[]="/test", setAddress(1,adr)
tobyspark 0:49cdaebd52d5 208 */
tobyspark 0:49cdaebd52d5 209 void OSCMessage::setAddress(uint8_t _index, char *_address){
tobyspark 0:49cdaebd52d5 210 if(_index>MAX_ADDRESS) _index=MAX_ADDRESS-1;
tobyspark 0:49cdaebd52d5 211 address[_index]=_address;
tobyspark 0:49cdaebd52d5 212 addressNum=_index+1;
tobyspark 0:49cdaebd52d5 213 }
tobyspark 0:49cdaebd52d5 214
tobyspark 0:49cdaebd52d5 215
tobyspark 0:49cdaebd52d5 216 /*
tobyspark 0:49cdaebd52d5 217 Set TypeTag and args to the OSC Message container
tobyspark 0:49cdaebd52d5 218 @param[in] types TypeTag string "i"(integer) or"f"(float) (char *)
tobyspark 0:49cdaebd52d5 219 @param[in] ... Pointer of the Args(variable argument) ..
tobyspark 0:49cdaebd52d5 220 @return None
tobyspark 0:49cdaebd52d5 221 @Example:
tobyspark 0:49cdaebd52d5 222 (1) integer 123: (NOTE: integers are LONG)
tobyspark 0:49cdaebd52d5 223 long v1=123; sendMes.setArgs("i",&v1)
tobyspark 0:49cdaebd52d5 224 (2)integer:123 and float:52.14
tobyspark 0:49cdaebd52d5 225 long v1=123; double v2=52.14; sendMes.setArgs("if",&v1,&v2)
tobyspark 0:49cdaebd52d5 226 Attention: in this implementation, the maximum number of the args is 2
tobyspark 0:49cdaebd52d5 227 (if setArgs("iff",&v1,&v2,&v3), data is ignored after &v3)
tobyspark 0:49cdaebd52d5 228 */
tobyspark 0:49cdaebd52d5 229 void OSCMessage::setArgs(char *types,...){
tobyspark 0:49cdaebd52d5 230
tobyspark 0:49cdaebd52d5 231 va_list argList;
tobyspark 0:49cdaebd52d5 232
tobyspark 0:49cdaebd52d5 233 argNum = strlen(types);
tobyspark 0:49cdaebd52d5 234 if(argNum>MAX_ARG) argNum=MAX_ARG-1;
tobyspark 0:49cdaebd52d5 235
tobyspark 0:49cdaebd52d5 236 va_start( argList, types );
tobyspark 0:49cdaebd52d5 237 for(uint8_t i=0 ; i < argNum ; i++){
tobyspark 0:49cdaebd52d5 238
tobyspark 0:49cdaebd52d5 239 typeTag[i]=types[i];
tobyspark 0:49cdaebd52d5 240
tobyspark 0:49cdaebd52d5 241 switch(types[i]) {
tobyspark 0:49cdaebd52d5 242 case 'i':
tobyspark 0:49cdaebd52d5 243 arg[i]=(uint32_t *)va_arg(argList, uint32_t *);
tobyspark 0:49cdaebd52d5 244 break;
tobyspark 0:49cdaebd52d5 245 case 'f':
tobyspark 0:49cdaebd52d5 246 arg[i]=va_arg(argList, double *);
tobyspark 0:49cdaebd52d5 247 break;
tobyspark 0:49cdaebd52d5 248 }
tobyspark 0:49cdaebd52d5 249
tobyspark 0:49cdaebd52d5 250 }
tobyspark 0:49cdaebd52d5 251
tobyspark 0:49cdaebd52d5 252 }
tobyspark 0:49cdaebd52d5 253
tobyspark 0:49cdaebd52d5 254 // ================================================================================================================================================
tobyspark 0:49cdaebd52d5 255 // ==================================== OSCClass for sending and receiving OSC messages using UDP protocol =======================================
tobyspark 0:49cdaebd52d5 256 // ================================================================================================================================================
tobyspark 0:49cdaebd52d5 257 //The class define an object wrapping the UDP functions to send and receive OSC messages
tobyspark 0:49cdaebd52d5 258
tobyspark 0:49cdaebd52d5 259 OSCClass::OSCClass(){
tobyspark 0:49cdaebd52d5 260 udpRec.setOnEvent(this, &OSCClass::onUDPSocketEvent);
tobyspark 0:49cdaebd52d5 261 newMessage=false;
tobyspark 0:49cdaebd52d5 262 }
tobyspark 0:49cdaebd52d5 263
tobyspark 0:49cdaebd52d5 264 /*
tobyspark 0:49cdaebd52d5 265 This sets "binds" the received message to the receiver container of the communication object
tobyspark 0:49cdaebd52d5 266 param[in]<--_mes is a pointer to the "receiveing" OSC message (OSCMessage *)
tobyspark 0:49cdaebd52d5 267 */
tobyspark 0:49cdaebd52d5 268 OSCClass::OSCClass(OSCMessage *_mes){
tobyspark 0:49cdaebd52d5 269 udpRec.setOnEvent(this, &OSCClass::onUDPSocketEvent);
tobyspark 0:49cdaebd52d5 270 receiverMessage = _mes; // note: receiverMessage MUST be a pointer to the message, because we will modify things in it
tobyspark 0:49cdaebd52d5 271 newMessage=false;
tobyspark 0:49cdaebd52d5 272 }
tobyspark 0:49cdaebd52d5 273
tobyspark 0:49cdaebd52d5 274 /*
tobyspark 0:49cdaebd52d5 275 This initializes the OSC communication object with default receiving port (DEFAULT_REC_PORT)
tobyspark 0:49cdaebd52d5 276 param[in]: None
tobyspark 0:49cdaebd52d5 277 return: None
tobyspark 0:49cdaebd52d5 278 */
tobyspark 0:49cdaebd52d5 279 void OSCClass::begin()
tobyspark 0:49cdaebd52d5 280 {
tobyspark 0:49cdaebd52d5 281 // setup receiver udp socket:
tobyspark 0:49cdaebd52d5 282 udpRec.bind(receiverMessage->host);
tobyspark 0:49cdaebd52d5 283 }
tobyspark 0:49cdaebd52d5 284
tobyspark 0:49cdaebd52d5 285 /*
tobyspark 0:49cdaebd52d5 286 Initialize an OSC object with arbitrary listening port
tobyspark 0:49cdaebd52d5 287 param[in] <-- _recievePort, is the listening ("receiving") Port No (unsigned int)
tobyspark 0:49cdaebd52d5 288 return: None
tobyspark 0:49cdaebd52d5 289 */
tobyspark 0:49cdaebd52d5 290 void OSCClass::begin(uint16_t _recievePort)
tobyspark 0:49cdaebd52d5 291 {
tobyspark 0:49cdaebd52d5 292 receiverMessage->host.setPort(_recievePort);
tobyspark 0:49cdaebd52d5 293 // setup receiver udp socket:
tobyspark 0:49cdaebd52d5 294 udpRec.bind(receiverMessage->host);
tobyspark 0:49cdaebd52d5 295 }
tobyspark 0:49cdaebd52d5 296
tobyspark 0:49cdaebd52d5 297 /*
tobyspark 0:49cdaebd52d5 298 Set a OSC receive message container
tobyspark 0:49cdaebd52d5 299 param[in] _mes Pointer to the OSC receive message container (OSCMessage *)
tobyspark 0:49cdaebd52d5 300 return None
tobyspark 0:49cdaebd52d5 301 */
tobyspark 0:49cdaebd52d5 302 void OSCClass::setReceiveMessage(OSCMessage *_mes){
tobyspark 0:49cdaebd52d5 303 receiverMessage = _mes;
tobyspark 0:49cdaebd52d5 304 }
tobyspark 0:49cdaebd52d5 305
tobyspark 0:49cdaebd52d5 306 /*
tobyspark 0:49cdaebd52d5 307 callback function when an upd message arrives (it will be transformed as OSC message)
tobyspark 0:49cdaebd52d5 308 */
tobyspark 0:49cdaebd52d5 309 void OSCClass::onUDPSocketEvent(UDPSocketEvent e)
tobyspark 0:49cdaebd52d5 310 {
tobyspark 0:49cdaebd52d5 311 switch(e)
tobyspark 0:49cdaebd52d5 312 {
tobyspark 0:49cdaebd52d5 313 case UDPSOCKET_READABLE: //The only event for now
tobyspark 0:49cdaebd52d5 314 //char buf[256] = {0};
tobyspark 0:49cdaebd52d5 315 Host auxhost;
tobyspark 0:49cdaebd52d5 316 buflength = udpRec.recvfrom( rcvBuff, 256, &auxhost ); // QUESTION: auxhost should be equal to the receiver host I guess...
tobyspark 0:49cdaebd52d5 317 if ( buflength > 0 ) {
tobyspark 0:49cdaebd52d5 318 //printf("\r\nFrom %d.%d.%d.%d:\r\n", host.getIp()[0], host.getIp()[1], host.getIp()[2], host.getIp()[3]);
tobyspark 0:49cdaebd52d5 319 decodePacket(receiverMessage); // convert to OSC message, and save it in receiverMessage
tobyspark 0:49cdaebd52d5 320 newMessage=true;
tobyspark 0:49cdaebd52d5 321
tobyspark 0:49cdaebd52d5 322 messageReceivedCallback.call();
tobyspark 0:49cdaebd52d5 323 }
tobyspark 0:49cdaebd52d5 324 break;
tobyspark 0:49cdaebd52d5 325 }
tobyspark 0:49cdaebd52d5 326 }
tobyspark 0:49cdaebd52d5 327
tobyspark 0:49cdaebd52d5 328 /*
tobyspark 0:49cdaebd52d5 329 Decode UDP packet and save it in the OSCMessage structure
tobyspark 0:49cdaebd52d5 330 */
tobyspark 0:49cdaebd52d5 331 void OSCClass::decodePacket( OSCMessage *_mes) {
tobyspark 0:49cdaebd52d5 332
tobyspark 0:49cdaebd52d5 333 //uint16_t lenBuff;
tobyspark 0:49cdaebd52d5 334 uint8_t d;
tobyspark 0:49cdaebd52d5 335 uint8_t messagePos=0;
tobyspark 0:49cdaebd52d5 336 uint8_t adrCount=0;
tobyspark 0:49cdaebd52d5 337 uint8_t adrMesPos=0;
tobyspark 0:49cdaebd52d5 338 uint8_t packetCount=0;
tobyspark 0:49cdaebd52d5 339 uint8_t packetPos=4;
tobyspark 0:49cdaebd52d5 340
tobyspark 0:49cdaebd52d5 341
tobyspark 0:49cdaebd52d5 342 //W5100.writeSn(socketNo, SnIR, SnIR::RECV);
tobyspark 0:49cdaebd52d5 343 //lenBuff=recvfrom(socketNo, rcvBuff, 1, receiverMessage->ip, &receiverMessage->port);
tobyspark 0:49cdaebd52d5 344
tobyspark 0:49cdaebd52d5 345 receiverMessage->address[0]=tempAddress[0];
tobyspark 0:49cdaebd52d5 346
tobyspark 0:49cdaebd52d5 347 //(1) address process start =========================================
tobyspark 0:49cdaebd52d5 348 do{
tobyspark 0:49cdaebd52d5 349 d=rcvBuff[messagePos];
tobyspark 0:49cdaebd52d5 350
tobyspark 0:49cdaebd52d5 351
tobyspark 0:49cdaebd52d5 352 if( (d=='/') && (messagePos>0) ){
tobyspark 0:49cdaebd52d5 353
tobyspark 0:49cdaebd52d5 354 if(adrCount<MAX_ADDRESS){
tobyspark 0:49cdaebd52d5 355 tempAddress[adrCount][adrMesPos]=0;
tobyspark 0:49cdaebd52d5 356
tobyspark 0:49cdaebd52d5 357 adrCount++;
tobyspark 0:49cdaebd52d5 358 adrMesPos=0;
tobyspark 0:49cdaebd52d5 359
tobyspark 0:49cdaebd52d5 360 receiverMessage->address[adrCount]=tempAddress[adrCount];
tobyspark 0:49cdaebd52d5 361 }
tobyspark 0:49cdaebd52d5 362
tobyspark 0:49cdaebd52d5 363 }
tobyspark 0:49cdaebd52d5 364
tobyspark 0:49cdaebd52d5 365 if(adrCount<MAX_ADDRESS){
tobyspark 0:49cdaebd52d5 366 //Added this in to remove the slashes out of final output
tobyspark 0:49cdaebd52d5 367 if(d!='/'){
tobyspark 0:49cdaebd52d5 368 tempAddress[adrCount][adrMesPos]=d;
tobyspark 0:49cdaebd52d5 369
tobyspark 0:49cdaebd52d5 370 if(packetCount>3) {
tobyspark 0:49cdaebd52d5 371 packetCount=0;
tobyspark 0:49cdaebd52d5 372 packetPos+=4;
tobyspark 0:49cdaebd52d5 373 }
tobyspark 0:49cdaebd52d5 374
tobyspark 0:49cdaebd52d5 375 adrMesPos++;
tobyspark 0:49cdaebd52d5 376 }
tobyspark 0:49cdaebd52d5 377 }
tobyspark 0:49cdaebd52d5 378 messagePos++;
tobyspark 0:49cdaebd52d5 379 packetCount++;
tobyspark 0:49cdaebd52d5 380
tobyspark 0:49cdaebd52d5 381 }while(d!=0);
tobyspark 0:49cdaebd52d5 382
tobyspark 0:49cdaebd52d5 383
tobyspark 0:49cdaebd52d5 384 if(adrCount<MAX_ADDRESS) adrCount++;
tobyspark 0:49cdaebd52d5 385 receiverMessage->addressNum=adrCount;
tobyspark 0:49cdaebd52d5 386
tobyspark 0:49cdaebd52d5 387 messagePos=packetPos;
tobyspark 0:49cdaebd52d5 388
tobyspark 0:49cdaebd52d5 389 //(2) type tag process starts =========================================
tobyspark 0:49cdaebd52d5 390 packetCount=0;
tobyspark 0:49cdaebd52d5 391 packetPos+=4;
tobyspark 0:49cdaebd52d5 392
tobyspark 0:49cdaebd52d5 393 uint8_t typeTagPos=0;
tobyspark 0:49cdaebd52d5 394 uint8_t tempArgNum=0;
tobyspark 0:49cdaebd52d5 395
tobyspark 0:49cdaebd52d5 396 while(rcvBuff[messagePos]!=0 ){
tobyspark 0:49cdaebd52d5 397
tobyspark 0:49cdaebd52d5 398 if(rcvBuff[messagePos] != ',') {
tobyspark 0:49cdaebd52d5 399
tobyspark 0:49cdaebd52d5 400 if(typeTagPos<MAX_ARG){
tobyspark 0:49cdaebd52d5 401 receiverMessage->typeTag[tempArgNum]=rcvBuff[messagePos];
tobyspark 0:49cdaebd52d5 402 tempArgNum++;
tobyspark 0:49cdaebd52d5 403 }
tobyspark 0:49cdaebd52d5 404 typeTagPos++;
tobyspark 0:49cdaebd52d5 405
tobyspark 0:49cdaebd52d5 406 }
tobyspark 0:49cdaebd52d5 407
tobyspark 0:49cdaebd52d5 408 packetCount++;
tobyspark 0:49cdaebd52d5 409
tobyspark 0:49cdaebd52d5 410 if(packetCount>3) {
tobyspark 0:49cdaebd52d5 411 packetCount=0;
tobyspark 0:49cdaebd52d5 412 packetPos+=4;
tobyspark 0:49cdaebd52d5 413 }
tobyspark 0:49cdaebd52d5 414
tobyspark 0:49cdaebd52d5 415 messagePos++;
tobyspark 0:49cdaebd52d5 416 }
tobyspark 0:49cdaebd52d5 417
tobyspark 0:49cdaebd52d5 418 receiverMessage->argNum=tempArgNum;
tobyspark 0:49cdaebd52d5 419
tobyspark 0:49cdaebd52d5 420 messagePos=packetPos;
tobyspark 0:49cdaebd52d5 421
tobyspark 0:49cdaebd52d5 422 //(3) tempArg process starts =========================================
tobyspark 0:49cdaebd52d5 423 for(int i=0;i<tempArgNum;i++){
tobyspark 0:49cdaebd52d5 424
tobyspark 0:49cdaebd52d5 425 adrMesPos=3;
tobyspark 0:49cdaebd52d5 426
tobyspark 0:49cdaebd52d5 427 receiverMessage->arg[i]=tempArg[i];
tobyspark 0:49cdaebd52d5 428
tobyspark 0:49cdaebd52d5 429 for(int j=0;j<4;j++){
tobyspark 0:49cdaebd52d5 430
tobyspark 0:49cdaebd52d5 431 tempArg[i][adrMesPos]=rcvBuff[messagePos];
tobyspark 0:49cdaebd52d5 432
tobyspark 0:49cdaebd52d5 433 messagePos++;
tobyspark 0:49cdaebd52d5 434 adrMesPos--;
tobyspark 0:49cdaebd52d5 435 }
tobyspark 0:49cdaebd52d5 436
tobyspark 0:49cdaebd52d5 437 }
tobyspark 0:49cdaebd52d5 438
tobyspark 0:49cdaebd52d5 439
tobyspark 0:49cdaebd52d5 440 }
tobyspark 0:49cdaebd52d5 441
tobyspark 0:49cdaebd52d5 442
tobyspark 0:49cdaebd52d5 443 /*
tobyspark 0:49cdaebd52d5 444 Get the received OSC message (note: this is another way to access the message directly from the OSCClass object).
tobyspark 0:49cdaebd52d5 445 The advantage is that we will signal that we read the message, and will be able to query if a NEW message arrived
tobyspark 0:49cdaebd52d5 446 (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)
tobyspark 0:49cdaebd52d5 447 */
tobyspark 0:49cdaebd52d5 448 OSCMessage * OSCClass::getMessage(){
tobyspark 0:49cdaebd52d5 449 newMessage=false; // this indicate the user READ the message
tobyspark 0:49cdaebd52d5 450 return receiverMessage;
tobyspark 0:49cdaebd52d5 451 }
tobyspark 0:49cdaebd52d5 452
tobyspark 0:49cdaebd52d5 453 /*
tobyspark 0:49cdaebd52d5 454 Send an OSC Message (message contain the host ip and port where the message data has to be sent)
tobyspark 0:49cdaebd52d5 455 param[in] _mes Pointer to the OSC message container (OSCMessage *)
tobyspark 0:49cdaebd52d5 456 return None
tobyspark 0:49cdaebd52d5 457 */
tobyspark 0:49cdaebd52d5 458 void OSCClass::sendOsc( OSCMessage *_mes )
tobyspark 0:49cdaebd52d5 459 {
tobyspark 0:49cdaebd52d5 460 uint8_t lengthEnd;
tobyspark 0:49cdaebd52d5 461 uint8_t lengthStart;
tobyspark 0:49cdaebd52d5 462 char buff[128];
tobyspark 0:49cdaebd52d5 463
tobyspark 0:49cdaebd52d5 464 sendContainer = _mes;
tobyspark 0:49cdaebd52d5 465
tobyspark 0:49cdaebd52d5 466 //&#12496;&#12483;&#12501;&#12449;&#21021;&#26399;&#20516;
tobyspark 0:49cdaebd52d5 467 buff[0]=0;
tobyspark 0:49cdaebd52d5 468
tobyspark 0:49cdaebd52d5 469 //1) Add name spaces:
tobyspark 0:49cdaebd52d5 470 for(int i=0;i<sendContainer->addressNum;i++){
tobyspark 0:49cdaebd52d5 471
tobyspark 0:49cdaebd52d5 472 strcat(buff,sendContainer->address[i]); // note: an address is for instance: "/test" (including the "/")
tobyspark 0:49cdaebd52d5 473
tobyspark 0:49cdaebd52d5 474 }
tobyspark 0:49cdaebd52d5 475
tobyspark 0:49cdaebd52d5 476 // pad with 0s to align in multiples of 4:
tobyspark 0:49cdaebd52d5 477 lengthStart=strlen(buff);
tobyspark 0:49cdaebd52d5 478 lengthEnd=lengthStart+(4-(lengthStart%4));
tobyspark 0:49cdaebd52d5 479 for(int i=lengthStart ; i<lengthEnd; i++){
tobyspark 0:49cdaebd52d5 480 buff[i]=0;
tobyspark 0:49cdaebd52d5 481 }
tobyspark 0:49cdaebd52d5 482
tobyspark 0:49cdaebd52d5 483 lengthStart=lengthEnd;
tobyspark 0:49cdaebd52d5 484
tobyspark 0:49cdaebd52d5 485 //2) Add TypeTag:
tobyspark 0:49cdaebd52d5 486 buff[lengthEnd++]=','; // Note: type tag is for instance: ",if"
tobyspark 0:49cdaebd52d5 487 for(int i=0;i<sendContainer->argNum;i++){
tobyspark 0:49cdaebd52d5 488 buff[lengthEnd++]=sendContainer->typeTag[i];
tobyspark 0:49cdaebd52d5 489 }
tobyspark 0:49cdaebd52d5 490
tobyspark 0:49cdaebd52d5 491 // pad with 0s to align in multiples of 4:
tobyspark 0:49cdaebd52d5 492 lengthStart=lengthEnd;
tobyspark 0:49cdaebd52d5 493 lengthEnd=lengthStart+(4-(lengthStart%4));
tobyspark 0:49cdaebd52d5 494 for(int i=lengthStart ; i<lengthEnd; i++){
tobyspark 0:49cdaebd52d5 495 buff[i]=0;
tobyspark 0:49cdaebd52d5 496 }
tobyspark 0:49cdaebd52d5 497
tobyspark 0:49cdaebd52d5 498 //3) add argument values (Note: here only big endian):
tobyspark 0:49cdaebd52d5 499 uint8_t *v;
tobyspark 0:49cdaebd52d5 500 for(int i=0;i<sendContainer->argNum;i++){
tobyspark 0:49cdaebd52d5 501 uint8_t valuePos=3;
tobyspark 0:49cdaebd52d5 502 v=(uint8_t *)sendContainer->arg[i];
tobyspark 0:49cdaebd52d5 503
tobyspark 0:49cdaebd52d5 504 buff[lengthEnd++]=v[valuePos--];
tobyspark 0:49cdaebd52d5 505 buff[lengthEnd++]=v[valuePos--];
tobyspark 0:49cdaebd52d5 506 buff[lengthEnd++]=v[valuePos--];
tobyspark 0:49cdaebd52d5 507 buff[lengthEnd++]=v[valuePos];
tobyspark 0:49cdaebd52d5 508
tobyspark 0:49cdaebd52d5 509 }
tobyspark 0:49cdaebd52d5 510
tobyspark 0:49cdaebd52d5 511 //4) Send udp packet:
tobyspark 0:49cdaebd52d5 512 //sendto( socketNo, (uint8_t *)buff, lengthEnd, sendContainer->ip, sendContainer->port );
tobyspark 0:49cdaebd52d5 513 udpSend.sendto(buff , lengthEnd, &(sendContainer->host));
tobyspark 0:49cdaebd52d5 514 }
tobyspark 0:49cdaebd52d5 515
tobyspark 0:49cdaebd52d5 516
tobyspark 0:49cdaebd52d5 517 /*
tobyspark 0:49cdaebd52d5 518 flush a receive buffer
tobyspark 0:49cdaebd52d5 519 void OSCClass::flush() {
tobyspark 0:49cdaebd52d5 520 while ( available() ){}
tobyspark 0:49cdaebd52d5 521 }
tobyspark 0:49cdaebd52d5 522 */
tobyspark 0:49cdaebd52d5 523
tobyspark 0:49cdaebd52d5 524 /*
tobyspark 0:49cdaebd52d5 525 Stop OSC communication (in fact, only the receiver - the server side)
tobyspark 0:49cdaebd52d5 526 */
tobyspark 0:49cdaebd52d5 527 void OSCClass::stop() {
tobyspark 0:49cdaebd52d5 528 //close( socketNo );
tobyspark 0:49cdaebd52d5 529 udpSend.resetOnEvent(); // disables callback
tobyspark 0:49cdaebd52d5 530 }
tobyspark 0:49cdaebd52d5 531
tobyspark 0:49cdaebd52d5 532