support OSC-string
Fork of OSC by
mbedOSC.h@8:73bce95a6853, 2016-03-08 (annotated)
- Committer:
- casiotone401
- Date:
- Tue Mar 08 11:50:30 2016 +0000
- Revision:
- 8:73bce95a6853
- Parent:
- 7:498455cded21
minor change
Who changed what in which revision?
User | Revision | Line number | New 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 |
casiotone401 | 4:601f6a1141fb | 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 | */ |
casiotone401 | 4:601f6a1141fb | 12 | |
casiotone401 | 2:507dea4cc97a | 13 | #pragma O3 |
casiotone401 | 2:507dea4cc97a | 14 | #pragma Otime |
casiotone401 | 4:601f6a1141fb | 15 | |
tobyspark | 0:fdea65150534 | 16 | #ifndef mbedOSC_h |
tobyspark | 0:fdea65150534 | 17 | #define mbedOSC_h |
casiotone401 | 4:601f6a1141fb | 18 | |
tobyspark | 0:fdea65150534 | 19 | #include "mbed.h" |
tobyspark | 0:fdea65150534 | 20 | #include "EthernetNetIf.h" |
tobyspark | 0:fdea65150534 | 21 | #include "UDPSocket.h" |
casiotone401 | 4:601f6a1141fb | 22 | |
tobyspark | 0:fdea65150534 | 23 | // setup IP of destination (computer): |
tobyspark | 0:fdea65150534 | 24 | #define DEFAULT_SEND_PORT 12000 |
tobyspark | 0:fdea65150534 | 25 | //Host sendHost(IpAddr(10, 0, 0, 1), DEFAULT_SEND_PORT, NULL); // Send Port |
tobyspark | 0:fdea65150534 | 26 | // 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 | 27 | #define DEFAULT_RECEIVE_PORT 57130 |
tobyspark | 0:fdea65150534 | 28 | //Host recHost(IpAddr(10, 0, 0, 1), DEFAULT_RECEIVE_PORT, NULL); // Receive Port |
tobyspark | 0:fdea65150534 | 29 | //UDPSocket udpRec,udpSend; |
casiotone401 | 4:601f6a1141fb | 30 | |
casiotone401 | 4:601f6a1141fb | 31 | |
tobyspark | 0:fdea65150534 | 32 | #define MAX_ADDRESS 2 |
casiotone401 | 2:507dea4cc97a | 33 | #define MAX_ARG 4 |
casiotone401 | 6:a47004fb44f5 | 34 | |
casiotone401 | 6:a47004fb44f5 | 35 | #define MAX_SENDBUFF_SIZE 128 |
casiotone401 | 6:a47004fb44f5 | 36 | #define MAX_RECEIVEBUFF_SIZE 512 |
casiotone401 | 4:601f6a1141fb | 37 | |
casiotone401 | 4:601f6a1141fb | 38 | |
tobyspark | 0:fdea65150534 | 39 | /** Container class for OSC messages (receiving or sending) |
tobyspark | 0:fdea65150534 | 40 | @note mbedOSC version 0.1 Specification (similar to Recotana's OSCClass library) |
tobyspark | 0:fdea65150534 | 41 | Example of an OSC message: "/mbed/test1, if 50 32.4" |
tobyspark | 0:fdea65150534 | 42 | ie. "Address TypeTag Args" |
tobyspark | 0:fdea65150534 | 43 | Address : max 2 |
tobyspark | 0:fdea65150534 | 44 | "/ard" |
tobyspark | 0:fdea65150534 | 45 | "/ard/output" |
tobyspark | 0:fdea65150534 | 46 | --address[0]="/ard" :max 15character |
tobyspark | 0:fdea65150534 | 47 | --address[1]="/output" :max 15character |
tobyspark | 0:fdea65150534 | 48 | TypeTag : max 2 |
tobyspark | 0:fdea65150534 | 49 | "i" - long or unsigned long |
tobyspark | 0:fdea65150534 | 50 | "f" - double |
tobyspark | 0:fdea65150534 | 51 | arg : max 2 |
tobyspark | 0:fdea65150534 | 52 | (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 | 53 | */ |
tobyspark | 0:fdea65150534 | 54 | class OSCMessage{ |
tobyspark | 0:fdea65150534 | 55 | |
tobyspark | 0:fdea65150534 | 56 | private: |
tobyspark | 0:fdea65150534 | 57 | |
tobyspark | 0:fdea65150534 | 58 | char *address[MAX_ADDRESS]; // these are strings (as char*) |
casiotone401 | 2:507dea4cc97a | 59 | uint8_t addressNum; // current number of addresses in the message (ex: "/ard/test" --> the number of the addresses is 2) |
tobyspark | 0:fdea65150534 | 60 | |
casiotone401 | 2:507dea4cc97a | 61 | char typeTag[MAX_ARG]; |
casiotone401 | 5:5d585d5107da | 62 | |
casiotone401 | 5:5d585d5107da | 63 | typedef union |
casiotone401 | 5:5d585d5107da | 64 | { |
casiotone401 | 7:498455cded21 | 65 | char * s; |
casiotone401 | 7:498455cded21 | 66 | int i; |
casiotone401 | 7:498455cded21 | 67 | float f; |
casiotone401 | 7:498455cded21 | 68 | double d; |
casiotone401 | 8:73bce95a6853 | 69 | |
casiotone401 | 8:73bce95a6853 | 70 | char _b[8]; // endian conversion temp variable |
casiotone401 | 5:5d585d5107da | 71 | |
casiotone401 | 5:5d585d5107da | 72 | } OSCArg; |
casiotone401 | 5:5d585d5107da | 73 | |
casiotone401 | 8:73bce95a6853 | 74 | OSCArg oscArgs[MAX_ARG]; |
casiotone401 | 5:5d585d5107da | 75 | |
casiotone401 | 2:507dea4cc97a | 76 | uint8_t argNum; |
casiotone401 | 6:a47004fb44f5 | 77 | |
tobyspark | 0:fdea65150534 | 78 | Host host; |
tobyspark | 0:fdea65150534 | 79 | |
tobyspark | 0:fdea65150534 | 80 | public: |
tobyspark | 0:fdea65150534 | 81 | /** Create a container for an OSC message to be received or sent */ |
tobyspark | 0:fdea65150534 | 82 | OSCMessage(); |
casiotone401 | 4:601f6a1141fb | 83 | |
tobyspark | 0:fdea65150534 | 84 | /** Return the IpAddr object */ |
casiotone401 | 2:507dea4cc97a | 85 | const IpAddr& getIp(); |
tobyspark | 0:fdea65150534 | 86 | /** Return the port */ |
tobyspark | 0:fdea65150534 | 87 | const int& getPort(); |
tobyspark | 0:fdea65150534 | 88 | |
tobyspark | 0:fdea65150534 | 89 | /** Gets the address string of the OSC message |
tobyspark | 0:fdea65150534 | 90 | * |
casiotone401 | 6:a47004fb44f5 | 91 | * @param[in] index The index of the address string (byte) |
tobyspark | 0:fdea65150534 | 92 | * @return pointer of the address string (char *) |
tobyspark | 0:fdea65150534 | 93 | * @note ex. "/ard/test"<br> |
tobyspark | 0:fdea65150534 | 94 | * getAddress(0) = "/ard"<br> |
tobyspark | 0:fdea65150534 | 95 | * getAddress(1) = "/test" |
tobyspark | 0:fdea65150534 | 96 | * @attention It is maximum number of the addresses is 2<br> |
tobyspark | 0:fdea65150534 | 97 | * In this case "/ard/test1/test2"<br> |
tobyspark | 0:fdea65150534 | 98 | * ignore it after "/test2" |
tobyspark | 0:fdea65150534 | 99 | */ |
casiotone401 | 6:a47004fb44f5 | 100 | char *getAddress(uint8_t index); //retturn address |
tobyspark | 0:fdea65150534 | 101 | |
tobyspark | 0:fdea65150534 | 102 | /** Gets the TopAddress string of the OSC message (this is just the address with index 0) |
tobyspark | 0:fdea65150534 | 103 | @return pointer of the TopAddress string (char *), i.e. address[0] |
tobyspark | 0:fdea65150534 | 104 | Example: In the case "/ard/test", getTopAddress() = "/ard" (WITH the slash "/") |
tobyspark | 0:fdea65150534 | 105 | */ |
tobyspark | 0:fdea65150534 | 106 | char *getTopAddress(); //return address[0] :"/ard" |
casiotone401 | 4:601f6a1141fb | 107 | |
tobyspark | 0:fdea65150534 | 108 | /** |
tobyspark | 0:fdea65150534 | 109 | Gets the "SubAddress" string of the OSC message (this is just the address with index 1) |
tobyspark | 0:fdea65150534 | 110 | @return pointer of the SubAddress string (char *), i.e. address[1] |
tobyspark | 0:fdea65150534 | 111 | Example: in the case "/ard/test", getSubAddress() = "/test" (WITH the slash "/") |
tobyspark | 0:fdea65150534 | 112 | */ |
tobyspark | 0:fdea65150534 | 113 | char *getSubAddress(); //return address[1] :"/test" |
casiotone401 | 4:601f6a1141fb | 114 | |
tobyspark | 0:fdea65150534 | 115 | /** |
tobyspark | 0:fdea65150534 | 116 | Gets the number of the OSC message address |
tobyspark | 0:fdea65150534 | 117 | @return number of the OSC message address (byte) |
tobyspark | 0:fdea65150534 | 118 | Examples: "/ard" --> the number of the addresses is 1 |
tobyspark | 0:fdea65150534 | 119 | "/ard/test" --> the number of the addresses is 2 |
tobyspark | 0:fdea65150534 | 120 | Attention: the maximum number of addresses is 2 (MAX_ADDRESS) |
tobyspark | 0:fdea65150534 | 121 | */ |
casiotone401 | 2:507dea4cc97a | 122 | uint8_t getAddressNum(); //return 2 |
tobyspark | 0:fdea65150534 | 123 | |
tobyspark | 0:fdea65150534 | 124 | /** |
tobyspark | 0:fdea65150534 | 125 | Gets the TypeTag string (with index) of the OSC message |
casiotone401 | 6:a47004fb44f5 | 126 | @param[in] index The index of the TypeTag string (byte) |
tobyspark | 0:fdea65150534 | 127 | @return: TypeTag char (char) |
tobyspark | 0:fdea65150534 | 128 | Example: in the case of a total typetag string equal to "if", getTypeTag(0) = 'i' and getTypeTag(1) = 'f' |
tobyspark | 0:fdea65150534 | 129 | 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 | 130 | */ |
casiotone401 | 6:a47004fb44f5 | 131 | char getTypeTag(uint8_t index); //index=0 ->'i' |
casiotone401 | 6:a47004fb44f5 | 132 | //index=1 ->'f' |
casiotone401 | 4:601f6a1141fb | 133 | |
tobyspark | 0:fdea65150534 | 134 | /** |
tobyspark | 0:fdea65150534 | 135 | Gets the number of the OSC message args |
tobyspark | 0:fdea65150534 | 136 | @return number of the args (byte) |
tobyspark | 0:fdea65150534 | 137 | Example: "i" 123 --> number of the OSC message args is 1 |
tobyspark | 0:fdea65150534 | 138 | "if" 123 54.24 --> number of the OSC message args is 2 |
tobyspark | 0:fdea65150534 | 139 | Attention: the maximum number of args is 2 (MAX_ARG) |
tobyspark | 0:fdea65150534 | 140 | */ |
casiotone401 | 3:f4118f0bc1ab | 141 | uint8_t getArgNum(); //return 2 |
tobyspark | 0:fdea65150534 | 142 | |
tobyspark | 0:fdea65150534 | 143 | /** |
tobyspark | 0:fdea65150534 | 144 | Get the args of the OSC message with an integer value |
casiotone401 | 6:a47004fb44f5 | 145 | @param[in] index An int or uint8_t corresponding to the index of the args (byte) |
casiotone401 | 2:507dea4cc97a | 146 | @return: integer value (long, or int16_t) |
tobyspark | 0:fdea65150534 | 147 | Example: in the case "if" 123 54.24, getArgInt(0) = 123 |
tobyspark | 0:fdea65150534 | 148 | Noe: "i" is integer, but the return type is "long" |
tobyspark | 0:fdea65150534 | 149 | Note: When a index is bigger than the number of the args, it is set to the number of the args |
tobyspark | 0:fdea65150534 | 150 | */ |
casiotone401 | 6:a47004fb44f5 | 151 | int getArgInt(uint8_t index); //index=0 -> 123 |
casiotone401 | 4:601f6a1141fb | 152 | |
tobyspark | 0:fdea65150534 | 153 | /** |
tobyspark | 0:fdea65150534 | 154 | Get the args of the OSC message with a float value |
casiotone401 | 6:a47004fb44f5 | 155 | @param[in] index The index of the args |
tobyspark | 0:fdea65150534 | 156 | @return: float value (double) |
tobyspark | 0:fdea65150534 | 157 | note: In this case "if" 123 54.24, getArgFloat(1) = 54.24 |
tobyspark | 0:fdea65150534 | 158 | attention: arg declared as float, but return value cast as "double" |
tobyspark | 0:fdea65150534 | 159 | attention: When index is bigger than the number of the args, it is set to the number of the args |
tobyspark | 0:fdea65150534 | 160 | */ |
casiotone401 | 6:a47004fb44f5 | 161 | float getArgFloat(uint8_t index); //index=1 -> 54.21 |
casiotone401 | 6:a47004fb44f5 | 162 | |
tobyspark | 0:fdea65150534 | 163 | /** |
casiotone401 | 6:a47004fb44f5 | 164 | Get the args of the OSC message with a Strings value |
casiotone401 | 6:a47004fb44f5 | 165 | */ |
casiotone401 | 6:a47004fb44f5 | 166 | double getArgDouble(uint8_t index); |
casiotone401 | 6:a47004fb44f5 | 167 | |
tobyspark | 0:fdea65150534 | 168 | /** |
casiotone401 | 6:a47004fb44f5 | 169 | Get the args of the OSC message with a Strings value |
casiotone401 | 6:a47004fb44f5 | 170 | */ |
casiotone401 | 6:a47004fb44f5 | 171 | char * getArgString(uint8_t index); |
casiotone401 | 6:a47004fb44f5 | 172 | |
casiotone401 | 6:a47004fb44f5 | 173 | |
casiotone401 | 6:a47004fb44f5 | 174 | //-------------------------------------------------------------------------------- |
tobyspark | 0:fdea65150534 | 175 | /** |
tobyspark | 0:fdea65150534 | 176 | Set IP Address of the OSC Message (for SENDING messages - for receiving this will be done when receiving something ) |
tobyspark | 0:fdea65150534 | 177 | @param[in] _ip Pointer of IP Address array (byte *) |
tobyspark | 0:fdea65150534 | 178 | Example: IP=192.168.0.99, then we have to do: ip[]={192,168,0,1}, then setIp(ip) |
tobyspark | 0:fdea65150534 | 179 | */ |
casiotone401 | 6:a47004fb44f5 | 180 | void setIp(uint8_t * ip); //set ip |
casiotone401 | 4:601f6a1141fb | 181 | |
tobyspark | 0:fdea65150534 | 182 | /** |
tobyspark | 0:fdea65150534 | 183 | Set IP Address to the OSC Message container (not through pointer) |
tobyspark | 0:fdea65150534 | 184 | Example: IP=192.168.0.99 => setIp(192,168,0,99) |
tobyspark | 0:fdea65150534 | 185 | */ |
casiotone401 | 6:a47004fb44f5 | 186 | void setIp(uint8_t ip1, //set(192, |
casiotone401 | 6:a47004fb44f5 | 187 | uint8_t ip2, // 168, |
casiotone401 | 6:a47004fb44f5 | 188 | uint8_t ip3, // 0, |
casiotone401 | 6:a47004fb44f5 | 189 | uint8_t ip4); // 100) |
casiotone401 | 4:601f6a1141fb | 190 | |
tobyspark | 0:fdea65150534 | 191 | /* |
tobyspark | 0:fdea65150534 | 192 | Set PortNo for the OSC Message |
tobyspark | 0:fdea65150534 | 193 | @param[in] _port PortNo (unsigned int) |
tobyspark | 0:fdea65150534 | 194 | @return None |
tobyspark | 0:fdea65150534 | 195 | */ |
casiotone401 | 6:a47004fb44f5 | 196 | void setPort(uint16_t port); |
casiotone401 | 6:a47004fb44f5 | 197 | |
casiotone401 | 6:a47004fb44f5 | 198 | /** |
casiotone401 | 6:a47004fb44f5 | 199 | Set TopAddress string of OSC Message |
casiotone401 | 6:a47004fb44f5 | 200 | @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? |
casiotone401 | 6:a47004fb44f5 | 201 | Example: if the complete address string is "/ard/test", we set the topaddress as follows: char top[]="/ard" (allocation done here!), then setTopAddress(top) |
casiotone401 | 6:a47004fb44f5 | 202 | */ |
casiotone401 | 7:498455cded21 | 203 | void setTopAddress(char * topAddress); //set address[0] |
casiotone401 | 6:a47004fb44f5 | 204 | |
casiotone401 | 6:a47004fb44f5 | 205 | /** |
casiotone401 | 6:a47004fb44f5 | 206 | Set SubAddress string of the OSC Message |
casiotone401 | 6:a47004fb44f5 | 207 | @param[in] address A string pointer for the SubAddress String (char *) |
casiotone401 | 6:a47004fb44f5 | 208 | Example: if the complete address string is "/ard/test", we set the subaddress as follows: char sub[]="/test" (allocation done here!), then setSubAddress(sub) |
casiotone401 | 6:a47004fb44f5 | 209 | Attention: we should call first setTopAddress, and then setSubAddress. The order is important. This does not seems like a good idea... |
casiotone401 | 6:a47004fb44f5 | 210 | */ |
casiotone401 | 7:498455cded21 | 211 | void setSubAddress(char * subAddress); //set address[1] |
casiotone401 | 6:a47004fb44f5 | 212 | |
casiotone401 | 6:a47004fb44f5 | 213 | /** |
casiotone401 | 6:a47004fb44f5 | 214 | Set the complete Address string of the OSC Message (top and sub addresses) |
casiotone401 | 6:a47004fb44f5 | 215 | @param[in] topAddress, subAddress The string pointers to top and sub addresses (char *) |
casiotone401 | 6:a47004fb44f5 | 216 | Example: in the case "/ard/test", we need to do: char top[]="/ard", char sub[]="/test", and then setAddress(top,sub) |
casiotone401 | 6:a47004fb44f5 | 217 | Reminder: in this implementation, the maximum number of addresses is MAXaddress=2 |
casiotone401 | 6:a47004fb44f5 | 218 | */ |
casiotone401 | 7:498455cded21 | 219 | void setAddress(char * topAddress, |
casiotone401 | 7:498455cded21 | 220 | char * subAddress); |
casiotone401 | 6:a47004fb44f5 | 221 | |
casiotone401 | 6:a47004fb44f5 | 222 | /** |
casiotone401 | 6:a47004fb44f5 | 223 | Set address string using index (here 0 or 1) |
casiotone401 | 6:a47004fb44f5 | 224 | Example: "/ard/test", char adr[]="/ard", setAddress(0,adr), char adr2[]="/test", setAddress(1,adr) |
casiotone401 | 6:a47004fb44f5 | 225 | */ |
casiotone401 | 6:a47004fb44f5 | 226 | void setAddress(uint8_t index, //set 0,address[0] |
casiotone401 | 7:498455cded21 | 227 | char * oscAddress); //set 1,address[1] |
tobyspark | 0:fdea65150534 | 228 | |
tobyspark | 0:fdea65150534 | 229 | /** |
tobyspark | 0:fdea65150534 | 230 | Set TypeTag and args to the OSC Message container |
casiotone401 | 6:a47004fb44f5 | 231 | @param[in] types TypeTag string "i"(integer) "f"(float) "d"(double) "s" (char *) |
tobyspark | 0:fdea65150534 | 232 | @param[in] ... Pointer of the Args(variable argument) .. |
tobyspark | 0:fdea65150534 | 233 | @Example: |
casiotone401 | 6:a47004fb44f5 | 234 | (1) integer 123 |
casiotone401 | 6:a47004fb44f5 | 235 | int v1=123; sendMes.setArgs("i",&v1) |
tobyspark | 0:fdea65150534 | 236 | (2)integer:123 and float:52.14 |
casiotone401 | 6:a47004fb44f5 | 237 | int v1=123; double v2=52.14; sendMes.setArgs("if", v1, v2) |
tobyspark | 0:fdea65150534 | 238 | Attention: in this implementation, the maximum number of the args is 2 |
casiotone401 | 6:a47004fb44f5 | 239 | (if setArgs("iff", v1, v2, v3), data is ignored after v3) |
casiotone401 | 6:a47004fb44f5 | 240 | */ |
casiotone401 | 7:498455cded21 | 241 | void setArgs(char * types, ...); //set ("if", v1, v2) |
casiotone401 | 6:a47004fb44f5 | 242 | |
casiotone401 | 6:a47004fb44f5 | 243 | |
casiotone401 | 6:a47004fb44f5 | 244 | friend class OSCClass; |
casiotone401 | 6:a47004fb44f5 | 245 | |
casiotone401 | 6:a47004fb44f5 | 246 | }; |
casiotone401 | 6:a47004fb44f5 | 247 | |
casiotone401 | 6:a47004fb44f5 | 248 | |
casiotone401 | 6:a47004fb44f5 | 249 | |
casiotone401 | 6:a47004fb44f5 | 250 | /* ==================================== OSCClass for sending and receiving OSC messages using UDP protocol ===================================== */ |
casiotone401 | 6:a47004fb44f5 | 251 | |
casiotone401 | 6:a47004fb44f5 | 252 | #include "UDPSocket.h" |
casiotone401 | 6:a47004fb44f5 | 253 | |
casiotone401 | 6:a47004fb44f5 | 254 | /** Wraps the UDP functions to send and receive OSC messages */ |
casiotone401 | 6:a47004fb44f5 | 255 | class OSCClass { |
casiotone401 | 6:a47004fb44f5 | 256 | |
casiotone401 | 6:a47004fb44f5 | 257 | private: |
casiotone401 | 6:a47004fb44f5 | 258 | |
casiotone401 | 6:a47004fb44f5 | 259 | UDPSocket udpRec, udpSend; |
casiotone401 | 7:498455cded21 | 260 | Host auxhost; |
casiotone401 | 6:a47004fb44f5 | 261 | char rcvBuff[MAX_RECEIVEBUFF_SIZE]; // raw buffer for UDP packets (udpRec.recvfrom( buf, 256, &host ) )) |
casiotone401 | 6:a47004fb44f5 | 262 | int buflength; |
casiotone401 | 6:a47004fb44f5 | 263 | |
casiotone401 | 6:a47004fb44f5 | 264 | OSCMessage *receiverMessage; |
casiotone401 | 6:a47004fb44f5 | 265 | OSCMessage *sendContainer; |
casiotone401 | 6:a47004fb44f5 | 266 | |
casiotone401 | 6:a47004fb44f5 | 267 | char tempAddress[MAX_ADDRESS][16]; |
casiotone401 | 6:a47004fb44f5 | 268 | uint8_t tempArg[MAX_ARG][4]; |
casiotone401 | 6:a47004fb44f5 | 269 | |
casiotone401 | 6:a47004fb44f5 | 270 | void onUDPSocketEvent(UDPSocketEvent e); |
casiotone401 | 6:a47004fb44f5 | 271 | |
casiotone401 | 6:a47004fb44f5 | 272 | void decodePacket(OSCMessage *mes); // makes OSC message from packet |
casiotone401 | 6:a47004fb44f5 | 273 | |
casiotone401 | 6:a47004fb44f5 | 274 | public: |
casiotone401 | 6:a47004fb44f5 | 275 | |
casiotone401 | 6:a47004fb44f5 | 276 | friend class UDPSocket; |
casiotone401 | 6:a47004fb44f5 | 277 | |
casiotone401 | 6:a47004fb44f5 | 278 | /** Create an object to send and receive OSC messages */ |
casiotone401 | 6:a47004fb44f5 | 279 | OSCClass(); |
casiotone401 | 6:a47004fb44f5 | 280 | ~OSCClass(); |
casiotone401 | 6:a47004fb44f5 | 281 | /** |
casiotone401 | 6:a47004fb44f5 | 282 | This sets "binds" the received message to the receiver container of the communication object |
casiotone401 | 6:a47004fb44f5 | 283 | @param[in] mes A pointer to the "receiveing" OSC message (OSCMessage *) |
tobyspark | 0:fdea65150534 | 284 | */ |
casiotone401 | 6:a47004fb44f5 | 285 | OSCClass(OSCMessage *mes); // set the receiver message container |
casiotone401 | 2:507dea4cc97a | 286 | |
casiotone401 | 6:a47004fb44f5 | 287 | /** |
casiotone401 | 6:a47004fb44f5 | 288 | This initializes the OSC communication object with default receiving port (DEFAULT_REC_PORT) |
casiotone401 | 6:a47004fb44f5 | 289 | */ |
casiotone401 | 6:a47004fb44f5 | 290 | void begin(); |
casiotone401 | 6:a47004fb44f5 | 291 | |
casiotone401 | 6:a47004fb44f5 | 292 | /** |
casiotone401 | 6:a47004fb44f5 | 293 | Initialize an OSC object with arbitrary listening port |
casiotone401 | 6:a47004fb44f5 | 294 | @param[in] recievePort The listening ("receiving") Port No (unsigned int) |
casiotone401 | 6:a47004fb44f5 | 295 | */ |
casiotone401 | 6:a47004fb44f5 | 296 | void begin(uint16_t recievePort); |
casiotone401 | 6:a47004fb44f5 | 297 | |
casiotone401 | 6:a47004fb44f5 | 298 | /** |
casiotone401 | 6:a47004fb44f5 | 299 | Stop OSC communication (in fact, only the receiver - the server side) |
casiotone401 | 6:a47004fb44f5 | 300 | */ |
casiotone401 | 6:a47004fb44f5 | 301 | void stop(); |
casiotone401 | 6:a47004fb44f5 | 302 | |
casiotone401 | 6:a47004fb44f5 | 303 | /** |
casiotone401 | 6:a47004fb44f5 | 304 | Returns whether there is new OSC data in the receiver message container. |
casiotone401 | 6:a47004fb44f5 | 305 | */ |
casiotone401 | 6:a47004fb44f5 | 306 | bool newMessage; |
casiotone401 | 6:a47004fb44f5 | 307 | |
casiotone401 | 6:a47004fb44f5 | 308 | /** |
casiotone401 | 6:a47004fb44f5 | 309 | Set a OSC receive message container |
casiotone401 | 6:a47004fb44f5 | 310 | @param[in] mes Pointer to the OSC receive message container (OSCMessage *) |
casiotone401 | 6:a47004fb44f5 | 311 | */ |
casiotone401 | 6:a47004fb44f5 | 312 | void setReceiveMessage(OSCMessage *mes); //set receive OSCmessage container (note: the message has a "host" object from which we get the upd packets) |
casiotone401 | 6:a47004fb44f5 | 313 | |
casiotone401 | 6:a47004fb44f5 | 314 | /** |
casiotone401 | 6:a47004fb44f5 | 315 | Get the received OSC message (note: this is another way to access the message directly from the OSCClass object). |
casiotone401 | 6:a47004fb44f5 | 316 | The advantage is that we will signal that we read the message, and will be able to query if a NEW message arrived |
casiotone401 | 6:a47004fb44f5 | 317 | (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) |
casiotone401 | 6:a47004fb44f5 | 318 | */ |
casiotone401 | 6:a47004fb44f5 | 319 | OSCMessage *getMessage(); //return received OSCmessage |
casiotone401 | 6:a47004fb44f5 | 320 | |
casiotone401 | 6:a47004fb44f5 | 321 | /** |
casiotone401 | 6:a47004fb44f5 | 322 | Send an OSC Message (message contain the host ip and port where the message data has to be sent) |
casiotone401 | 6:a47004fb44f5 | 323 | @param[in] mes Pointer to the OSC message container (OSCMessage *) |
casiotone401 | 6:a47004fb44f5 | 324 | */ |
casiotone401 | 6:a47004fb44f5 | 325 | void sendOsc(OSCMessage *mes); //set&send OSCmessage (note: it will be sent to the host defined in the message container) |
casiotone401 | 6:a47004fb44f5 | 326 | |
casiotone401 | 6:a47004fb44f5 | 327 | /** |
casiotone401 | 6:a47004fb44f5 | 328 | A function pointer to be set by host program that will be called on receipt of an OSC message |
casiotone401 | 6:a47004fb44f5 | 329 | @code |
casiotone401 | 6:a47004fb44f5 | 330 | osc.messageReceivedCallback.attach(&processOSC); |
casiotone401 | 6:a47004fb44f5 | 331 | @endcode |
casiotone401 | 6:a47004fb44f5 | 332 | */ |
casiotone401 | 2:507dea4cc97a | 333 | //## Cortex-M is little Endian |
casiotone401 | 2:507dea4cc97a | 334 | /* |
casiotone401 | 2:507dea4cc97a | 335 | based on http://stackoverflow.com/questions/809902/64-bit-ntohl-in-c |
casiotone401 | 2:507dea4cc97a | 336 | |
casiotone401 | 2:507dea4cc97a | 337 | if the system is little endian, it will flip the bits |
casiotone401 | 2:507dea4cc97a | 338 | if the system is big endian, it'll do nothing |
casiotone401 | 2:507dea4cc97a | 339 | */ |
casiotone401 | 2:507dea4cc97a | 340 | template<typename T> |
casiotone401 | 2:507dea4cc97a | 341 | static inline T BigEndian(const T& x) |
casiotone401 | 2:507dea4cc97a | 342 | { |
casiotone401 | 2:507dea4cc97a | 343 | const int one = 1; |
casiotone401 | 2:507dea4cc97a | 344 | const char sig = *(char*)&one; |
casiotone401 | 2:507dea4cc97a | 345 | if (sig == 0) return x; // for big endian machine just return the input |
casiotone401 | 2:507dea4cc97a | 346 | T ret; |
casiotone401 | 2:507dea4cc97a | 347 | int size = sizeof(T); |
casiotone401 | 6:a47004fb44f5 | 348 | char* src = (char *)&x + sizeof(T) - 1; |
casiotone401 | 6:a47004fb44f5 | 349 | char* dst = (char *)&ret; |
casiotone401 | 2:507dea4cc97a | 350 | while (size-- > 0){ |
casiotone401 | 2:507dea4cc97a | 351 | *dst++ = *src--; |
casiotone401 | 2:507dea4cc97a | 352 | } |
casiotone401 | 2:507dea4cc97a | 353 | return ret; |
casiotone401 | 2:507dea4cc97a | 354 | } |
casiotone401 | 6:a47004fb44f5 | 355 | |
casiotone401 | 6:a47004fb44f5 | 356 | |
casiotone401 | 6:a47004fb44f5 | 357 | FunctionPointer messageReceivedCallback; |
tobyspark | 0:fdea65150534 | 358 | |
tobyspark | 0:fdea65150534 | 359 | }; |
casiotone401 | 4:601f6a1141fb | 360 | |
casiotone401 | 6:a47004fb44f5 | 361 | #endif |