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

Committer:
tobyspark
Date:
Fri Jul 26 22:10:20 2013 +0000
Revision:
1:63b72e393989
Parent:
0:fdea65150534
Fixed double receive bug! Or rather, a platform quirk. Gah!

Who changed what in which revision?

UserRevisionLine numberNew contents of line
tobyspark 0:fdea65150534 1 /* mbed OSC Library
tobyspark 0:fdea65150534 2 This is an Open Sound Control library for the mbed, created to be compatible with Recotana's OSCClass library (http://recotana.com) for the
tobyspark 0:fdea65150534 3 Arduino with Ethernet shield. It also uses parts of the OSC Transceiver(Sender/Receiver) code by xshige
tobyspark 0:fdea65150534 4 written by: Alvaro Cassinelli, October 2011
tobyspark 0:fdea65150534 5 tweaked by: Toby Harris / *spark audio-visual, March 2012
tobyspark 0:fdea65150534 6
tobyspark 0:fdea65150534 7 This library is free software; you can redistribute it and/or
tobyspark 0:fdea65150534 8 modify it under the terms of the GNU Lesser General Public
tobyspark 0:fdea65150534 9 License version 2.1 as published by the Free Software Foundation.
tobyspark 0:fdea65150534 10 Open Sound Control http://opensoundcontrol.org/
tobyspark 0:fdea65150534 11 */
tobyspark 0:fdea65150534 12
tobyspark 0:fdea65150534 13 #ifndef mbedOSC_h
tobyspark 0:fdea65150534 14 #define mbedOSC_h
tobyspark 0:fdea65150534 15
tobyspark 0:fdea65150534 16 #include "mbed.h"
tobyspark 0:fdea65150534 17 #include "EthernetNetIf.h"
tobyspark 0:fdea65150534 18 #include "UDPSocket.h"
tobyspark 0:fdea65150534 19
tobyspark 0:fdea65150534 20 // setup IP of destination (computer):
tobyspark 0:fdea65150534 21 #define DEFAULT_SEND_PORT 12000
tobyspark 0:fdea65150534 22 //Host sendHost(IpAddr(10, 0, 0, 1), DEFAULT_SEND_PORT, NULL); // Send Port
tobyspark 0:fdea65150534 23 // set IP of origin of UDP packets - the mbed acts as a SERVER here, and needs to bind the socket to the "client" (the computer)
tobyspark 0:fdea65150534 24 #define DEFAULT_RECEIVE_PORT 57130
tobyspark 0:fdea65150534 25 //Host recHost(IpAddr(10, 0, 0, 1), DEFAULT_RECEIVE_PORT, NULL); // Receive Port
tobyspark 0:fdea65150534 26 //UDPSocket udpRec,udpSend;
tobyspark 0:fdea65150534 27
tobyspark 0:fdea65150534 28
tobyspark 0:fdea65150534 29 #define MAX_ADDRESS 2
tobyspark 0:fdea65150534 30 #define MAX_ARG 2
tobyspark 0:fdea65150534 31
tobyspark 0:fdea65150534 32 #define TYPE_INT 1
tobyspark 0:fdea65150534 33 #define TYPE_FLOAT 2
tobyspark 0:fdea65150534 34
tobyspark 0:fdea65150534 35
tobyspark 0:fdea65150534 36 /** Container class for OSC messages (receiving or sending)
tobyspark 0:fdea65150534 37 @note mbedOSC version 0.1 Specification (similar to Recotana's OSCClass library)
tobyspark 0:fdea65150534 38 Example of an OSC message: "/mbed/test1, if 50 32.4"
tobyspark 0:fdea65150534 39 ie. "Address TypeTag Args"
tobyspark 0:fdea65150534 40 Address : max 2
tobyspark 0:fdea65150534 41 "/ard"
tobyspark 0:fdea65150534 42 "/ard/output"
tobyspark 0:fdea65150534 43 --address[0]="/ard" :max 15character
tobyspark 0:fdea65150534 44 --address[1]="/output" :max 15character
tobyspark 0:fdea65150534 45 TypeTag : max 2
tobyspark 0:fdea65150534 46 "i" - long or unsigned long
tobyspark 0:fdea65150534 47 "f" - double
tobyspark 0:fdea65150534 48 arg : max 2
tobyspark 0:fdea65150534 49 (Note: The byte string as seen here is not sent as UDP packet directly - there are no spaces, and arguments are in binary, BIG ENDIAN)
tobyspark 0:fdea65150534 50 */
tobyspark 0:fdea65150534 51 class OSCMessage{
tobyspark 0:fdea65150534 52
tobyspark 0:fdea65150534 53 private:
tobyspark 0:fdea65150534 54
tobyspark 0:fdea65150534 55 char *address[MAX_ADDRESS]; // these are strings (as char*)
tobyspark 0:fdea65150534 56 uint8_t addressNum; // current number of addresses in the message (ex: "/ard/test" --> the number of the addresses is 2)
tobyspark 0:fdea65150534 57
tobyspark 0:fdea65150534 58 char typeTag[MAX_ARG];
tobyspark 0:fdea65150534 59
tobyspark 0:fdea65150534 60 void *arg[MAX_ARG];
tobyspark 0:fdea65150534 61 uint8_t argNum;
tobyspark 0:fdea65150534 62
tobyspark 0:fdea65150534 63 // Information about the connection:
tobyspark 0:fdea65150534 64 //uint8_t ip[4];
tobyspark 0:fdea65150534 65 //uint16_t port;
tobyspark 0:fdea65150534 66 Host host;
tobyspark 0:fdea65150534 67
tobyspark 0:fdea65150534 68 public:
tobyspark 0:fdea65150534 69 /** Create a container for an OSC message to be received or sent */
tobyspark 0:fdea65150534 70 OSCMessage();
tobyspark 0:fdea65150534 71
tobyspark 0:fdea65150534 72 /** Return the IpAddr object */
tobyspark 0:fdea65150534 73 const IpAddr& getIp();
tobyspark 0:fdea65150534 74 /** Return the port */
tobyspark 0:fdea65150534 75 const int& getPort();
tobyspark 0:fdea65150534 76
tobyspark 0:fdea65150534 77 /** Gets the address string of the OSC message
tobyspark 0:fdea65150534 78 *
tobyspark 0:fdea65150534 79 * @param[in] _index The index of the address string (byte)
tobyspark 0:fdea65150534 80 * @return pointer of the address string (char *)
tobyspark 0:fdea65150534 81 * @note ex. "/ard/test"<br>
tobyspark 0:fdea65150534 82 * getAddress(0) = "/ard"<br>
tobyspark 0:fdea65150534 83 * getAddress(1) = "/test"
tobyspark 0:fdea65150534 84 * @attention It is maximum number of the addresses is 2<br>
tobyspark 0:fdea65150534 85 * In this case "/ard/test1/test2"<br>
tobyspark 0:fdea65150534 86 * ignore it after "/test2"
tobyspark 0:fdea65150534 87 */
tobyspark 0:fdea65150534 88 char *getAddress(uint8_t _index); //retturn address
tobyspark 0:fdea65150534 89
tobyspark 0:fdea65150534 90 /** Gets the TopAddress string of the OSC message (this is just the address with index 0)
tobyspark 0:fdea65150534 91 @return pointer of the TopAddress string (char *), i.e. address[0]
tobyspark 0:fdea65150534 92 Example: In the case "/ard/test", getTopAddress() = "/ard" (WITH the slash "/")
tobyspark 0:fdea65150534 93 */
tobyspark 0:fdea65150534 94 char *getTopAddress(); //return address[0] :"/ard"
tobyspark 0:fdea65150534 95
tobyspark 0:fdea65150534 96 /**
tobyspark 0:fdea65150534 97 Gets the "SubAddress" string of the OSC message (this is just the address with index 1)
tobyspark 0:fdea65150534 98 @return pointer of the SubAddress string (char *), i.e. address[1]
tobyspark 0:fdea65150534 99 Example: in the case "/ard/test", getSubAddress() = "/test" (WITH the slash "/")
tobyspark 0:fdea65150534 100 */
tobyspark 0:fdea65150534 101 char *getSubAddress(); //return address[1] :"/test"
tobyspark 0:fdea65150534 102
tobyspark 0:fdea65150534 103 /**
tobyspark 0:fdea65150534 104 Gets the number of the OSC message address
tobyspark 0:fdea65150534 105 @return number of the OSC message address (byte)
tobyspark 0:fdea65150534 106 Examples: "/ard" --> the number of the addresses is 1
tobyspark 0:fdea65150534 107 "/ard/test" --> the number of the addresses is 2
tobyspark 0:fdea65150534 108 Attention: the maximum number of addresses is 2 (MAX_ADDRESS)
tobyspark 0:fdea65150534 109 */
tobyspark 0:fdea65150534 110 uint8_t getAddressNum(); //return 2
tobyspark 0:fdea65150534 111
tobyspark 0:fdea65150534 112 /**
tobyspark 0:fdea65150534 113 Gets the TypeTag string (with index) of the OSC message
tobyspark 0:fdea65150534 114 @param[in] _index The index of the TypeTag string (byte)
tobyspark 0:fdea65150534 115 @return: TypeTag char (char)
tobyspark 0:fdea65150534 116 Example: in the case of a total typetag string equal to "if", getTypeTag(0) = 'i' and getTypeTag(1) = 'f'
tobyspark 0:fdea65150534 117 Attention: MAX_ARG is maximum number of the args, if the index argument is larger, it will be constrained to this max.
tobyspark 0:fdea65150534 118 */
tobyspark 0:fdea65150534 119 char getTypeTag(uint8_t _index); //_index=0 ->'i'
tobyspark 0:fdea65150534 120 //_index=1 ->'f'
tobyspark 0:fdea65150534 121
tobyspark 0:fdea65150534 122 /**
tobyspark 0:fdea65150534 123 Gets the number of the OSC message args
tobyspark 0:fdea65150534 124 @return number of the args (byte)
tobyspark 0:fdea65150534 125 Example: "i" 123 --> number of the OSC message args is 1
tobyspark 0:fdea65150534 126 "if" 123 54.24 --> number of the OSC message args is 2
tobyspark 0:fdea65150534 127 Attention: the maximum number of args is 2 (MAX_ARG)
tobyspark 0:fdea65150534 128 */
tobyspark 0:fdea65150534 129 uint8_t getArgNum(); //return 2
tobyspark 0:fdea65150534 130
tobyspark 0:fdea65150534 131 /**
tobyspark 0:fdea65150534 132 Get the args of the OSC message with an integer value
tobyspark 0:fdea65150534 133 @param[in] _index An int or uint8_t corresponding to the index of the args (byte)
tobyspark 0:fdea65150534 134 @return: integer value (long, or int32_t)
tobyspark 0:fdea65150534 135 Example: in the case "if" 123 54.24, getArgInt(0) = 123
tobyspark 0:fdea65150534 136 Noe: "i" is integer, but the return type is "long"
tobyspark 0:fdea65150534 137 Note: When a index is bigger than the number of the args, it is set to the number of the args
tobyspark 0:fdea65150534 138 */
tobyspark 0:fdea65150534 139 int32_t getArgInt(uint8_t _index); //_index=0 -> 123
tobyspark 0:fdea65150534 140
tobyspark 0:fdea65150534 141 /**
tobyspark 0:fdea65150534 142 Get the args of the OSC message with a float value
tobyspark 0:fdea65150534 143 @param[in] _index The index of the args
tobyspark 0:fdea65150534 144 @return: float value (double)
tobyspark 0:fdea65150534 145 note: In this case "if" 123 54.24, getArgFloat(1) = 54.24
tobyspark 0:fdea65150534 146 attention: arg declared as float, but return value cast as "double"
tobyspark 0:fdea65150534 147 attention: When index is bigger than the number of the args, it is set to the number of the args
tobyspark 0:fdea65150534 148 */
tobyspark 0:fdea65150534 149 double getArgFloat(uint8_t _index); //_index=1 -> 54.21
tobyspark 0:fdea65150534 150
tobyspark 0:fdea65150534 151
tobyspark 0:fdea65150534 152 /**
tobyspark 0:fdea65150534 153 Set TopAddress string of OSC Message
tobyspark 0:fdea65150534 154 @param[in] _address 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:fdea65150534 155 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:fdea65150534 156 */
tobyspark 0:fdea65150534 157 void setTopAddress(char *_address); //set address[0]
tobyspark 0:fdea65150534 158
tobyspark 0:fdea65150534 159 /**
tobyspark 0:fdea65150534 160 Set SubAddress string of the OSC Message
tobyspark 0:fdea65150534 161 @param[in] _address A string pointer for the SubAddress String (char *)
tobyspark 0:fdea65150534 162 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:fdea65150534 163 Attention: we should call first setTopAddress, and then setSubAddress. The order is important. This does not seems like a good idea...
tobyspark 0:fdea65150534 164 */
tobyspark 0:fdea65150534 165 void setSubAddress(char *_address); //set address[1]
tobyspark 0:fdea65150534 166
tobyspark 0:fdea65150534 167 /**
tobyspark 0:fdea65150534 168 Set the complete Address string of the OSC Message (top and sub addresses)
tobyspark 0:fdea65150534 169 @param[in] _topAddress, _subAddress The string pointers to top and sub addresses (char *)
tobyspark 0:fdea65150534 170 Example: in the case "/ard/test", we need to do: char top[]="/ard", char sub[]="/test", and then setAddress(top,sub)
tobyspark 0:fdea65150534 171 Reminder: in this implementation, the maximum number of addresses is MAX_ADDRESS=2
tobyspark 0:fdea65150534 172 */
tobyspark 0:fdea65150534 173 void setAddress(char *_topAddress,
tobyspark 0:fdea65150534 174 char *_subAddress);
tobyspark 0:fdea65150534 175
tobyspark 0:fdea65150534 176 /**
tobyspark 0:fdea65150534 177 Set address string using index (here 0 or 1)
tobyspark 0:fdea65150534 178 Example: "/ard/test", char adr[]="/ard", setAddress(0,adr), char adr2[]="/test", setAddress(1,adr)
tobyspark 0:fdea65150534 179 */
tobyspark 0:fdea65150534 180 void setAddress(uint8_t _index, //set 0,address[0]
tobyspark 0:fdea65150534 181 char *_address);
tobyspark 0:fdea65150534 182 //set 1,address[1]
tobyspark 0:fdea65150534 183
tobyspark 0:fdea65150534 184 /**
tobyspark 0:fdea65150534 185 Set IP Address of the OSC Message (for SENDING messages - for receiving this will be done when receiving something )
tobyspark 0:fdea65150534 186 @param[in] _ip Pointer of IP Address array (byte *)
tobyspark 0:fdea65150534 187 Example: IP=192.168.0.99, then we have to do: ip[]={192,168,0,1}, then setIp(ip)
tobyspark 0:fdea65150534 188 */
tobyspark 0:fdea65150534 189 void setIp( uint8_t *_ip ); //set ip
tobyspark 0:fdea65150534 190
tobyspark 0:fdea65150534 191 /**
tobyspark 0:fdea65150534 192 Set IP Address to the OSC Message container (not through pointer)
tobyspark 0:fdea65150534 193 Example: IP=192.168.0.99 => setIp(192,168,0,99)
tobyspark 0:fdea65150534 194 */
tobyspark 0:fdea65150534 195 void setIp(uint8_t _ip1, //set(192,
tobyspark 0:fdea65150534 196 uint8_t _ip2, // 168,
tobyspark 0:fdea65150534 197 uint8_t _ip3, // 0,
tobyspark 0:fdea65150534 198 uint8_t _ip4); // 100)
tobyspark 0:fdea65150534 199
tobyspark 0:fdea65150534 200 /*
tobyspark 0:fdea65150534 201 Set PortNo for the OSC Message
tobyspark 0:fdea65150534 202 @param[in] _port PortNo (unsigned int)
tobyspark 0:fdea65150534 203 @return None
tobyspark 0:fdea65150534 204 */
tobyspark 0:fdea65150534 205 void setPort( uint16_t _port );
tobyspark 0:fdea65150534 206
tobyspark 0:fdea65150534 207 /**
tobyspark 0:fdea65150534 208 Set TypeTag and args to the OSC Message container
tobyspark 0:fdea65150534 209 @param[in] types TypeTag string "i"(integer) or"f"(float) (char *)
tobyspark 0:fdea65150534 210 @param[in] ... Pointer of the Args(variable argument) ..
tobyspark 0:fdea65150534 211 @Example:
tobyspark 0:fdea65150534 212 (1) integer 123: (NOTE: integers are LONG)
tobyspark 0:fdea65150534 213 long v1=123; sendMes.setArgs("i",&v1)
tobyspark 0:fdea65150534 214 (2)integer:123 and float:52.14
tobyspark 0:fdea65150534 215 long v1=123; double v2=52.14; sendMes.setArgs("if",&v1,&v2)
tobyspark 0:fdea65150534 216 Attention: in this implementation, the maximum number of the args is 2
tobyspark 0:fdea65150534 217 (if setArgs("iff",&v1,&v2,&v3), data is ignored after &v3)
tobyspark 0:fdea65150534 218 */
tobyspark 0:fdea65150534 219 void setArgs( char *types , ... ); //set ("if",&v1,&v2)
tobyspark 0:fdea65150534 220
tobyspark 0:fdea65150534 221 friend class OSCClass;
tobyspark 0:fdea65150534 222
tobyspark 0:fdea65150534 223 };
tobyspark 0:fdea65150534 224
tobyspark 0:fdea65150534 225
tobyspark 0:fdea65150534 226
tobyspark 0:fdea65150534 227 /* ==================================== OSCClass for sending and receiving OSC messages using UDP protocol ===================================== */
tobyspark 0:fdea65150534 228
tobyspark 0:fdea65150534 229 #include "UDPSocket.h"
tobyspark 0:fdea65150534 230
tobyspark 0:fdea65150534 231 /** Wraps the UDP functions to send and receive OSC messages */
tobyspark 0:fdea65150534 232 class OSCClass {
tobyspark 0:fdea65150534 233
tobyspark 0:fdea65150534 234 private:
tobyspark 0:fdea65150534 235
tobyspark 0:fdea65150534 236 UDPSocket udpRec,udpSend;
tobyspark 0:fdea65150534 237 char rcvBuff[256]; // raw buffer for UDP packets (udpRec.recvfrom( buf, 256, &host ) ))
tobyspark 0:fdea65150534 238 int buflength;
tobyspark 0:fdea65150534 239
tobyspark 0:fdea65150534 240 OSCMessage *receiverMessage;
tobyspark 0:fdea65150534 241 OSCMessage *sendContainer;
tobyspark 0:fdea65150534 242
tobyspark 0:fdea65150534 243 char tempAddress[MAX_ADDRESS][16];
tobyspark 0:fdea65150534 244 uint8_t tempArg[MAX_ARG][4];
tobyspark 0:fdea65150534 245
tobyspark 0:fdea65150534 246 void onUDPSocketEvent(UDPSocketEvent e);
tobyspark 0:fdea65150534 247
tobyspark 0:fdea65150534 248 void decodePacket( OSCMessage *_mes); // makes OSC message from packet
tobyspark 0:fdea65150534 249
tobyspark 0:fdea65150534 250 public:
tobyspark 0:fdea65150534 251
tobyspark 0:fdea65150534 252 friend class UDPSocket;
tobyspark 0:fdea65150534 253
tobyspark 0:fdea65150534 254 /** Create an object to send and receive OSC messages */
tobyspark 0:fdea65150534 255 OSCClass();
tobyspark 1:63b72e393989 256 ~OSCClass();
tobyspark 0:fdea65150534 257 /**
tobyspark 0:fdea65150534 258 This sets "binds" the received message to the receiver container of the communication object
tobyspark 0:fdea65150534 259 @param[in] _mes A pointer to the "receiveing" OSC message (OSCMessage *)
tobyspark 0:fdea65150534 260 */
tobyspark 0:fdea65150534 261 OSCClass(OSCMessage *_mes); // set the receiver message container
tobyspark 0:fdea65150534 262
tobyspark 0:fdea65150534 263 /**
tobyspark 0:fdea65150534 264 This initializes the OSC communication object with default receiving port (DEFAULT_REC_PORT)
tobyspark 0:fdea65150534 265 */
tobyspark 0:fdea65150534 266 void begin();
tobyspark 0:fdea65150534 267
tobyspark 0:fdea65150534 268 /**
tobyspark 0:fdea65150534 269 Initialize an OSC object with arbitrary listening port
tobyspark 0:fdea65150534 270 @param[in] _recievePort The listening ("receiving") Port No (unsigned int)
tobyspark 0:fdea65150534 271 */
tobyspark 0:fdea65150534 272 void begin(uint16_t _recievePort);
tobyspark 0:fdea65150534 273
tobyspark 0:fdea65150534 274 /**
tobyspark 0:fdea65150534 275 Stop OSC communication (in fact, only the receiver - the server side)
tobyspark 0:fdea65150534 276 */
tobyspark 0:fdea65150534 277 void stop();
tobyspark 0:fdea65150534 278
tobyspark 0:fdea65150534 279 /**
tobyspark 0:fdea65150534 280 Returns whether there is new OSC data in the receiver message container.
tobyspark 0:fdea65150534 281 */
tobyspark 0:fdea65150534 282 bool newMessage;
tobyspark 0:fdea65150534 283
tobyspark 0:fdea65150534 284 /**
tobyspark 0:fdea65150534 285 Set a OSC receive message container
tobyspark 0:fdea65150534 286 @param[in] _mes Pointer to the OSC receive message container (OSCMessage *)
tobyspark 0:fdea65150534 287 */
tobyspark 0:fdea65150534 288 void setReceiveMessage( OSCMessage *_mes ); //set receive OSCmessage container (note: the message has a "host" object from which we get the upd packets)
tobyspark 0:fdea65150534 289
tobyspark 0:fdea65150534 290 /**
tobyspark 0:fdea65150534 291 Get the received OSC message (note: this is another way to access the message directly from the OSCClass object).
tobyspark 0:fdea65150534 292 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:fdea65150534 293 (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:fdea65150534 294 */
tobyspark 0:fdea65150534 295 OSCMessage *getMessage(); //return received OSCmessage
tobyspark 0:fdea65150534 296
tobyspark 0:fdea65150534 297 /**
tobyspark 0:fdea65150534 298 Send an OSC Message (message contain the host ip and port where the message data has to be sent)
tobyspark 0:fdea65150534 299 @param[in] _mes Pointer to the OSC message container (OSCMessage *)
tobyspark 0:fdea65150534 300 */
tobyspark 0:fdea65150534 301 void sendOsc( OSCMessage *_mes ); //set&send OSCmessage (note: it will be sent to the host defined in the message container)
tobyspark 0:fdea65150534 302
tobyspark 0:fdea65150534 303 /**
tobyspark 0:fdea65150534 304 A function pointer to be set by host program that will be called on receipt of an OSC message
tobyspark 0:fdea65150534 305 @code
tobyspark 0:fdea65150534 306 osc.messageReceivedCallback.attach(&processOSC);
tobyspark 0:fdea65150534 307 @endcode
tobyspark 0:fdea65150534 308 */
tobyspark 0:fdea65150534 309 FunctionPointer messageReceivedCallback;
tobyspark 0:fdea65150534 310 };
tobyspark 0:fdea65150534 311
tobyspark 0:fdea65150534 312 #endif