PlatformIO package of the Teensy core framework compatible with GCC 10 & C++20
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

OSCMessage.h 9.4KB

3 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332
  1. /*
  2. Written by Yotam Mann, The Center for New Music and Audio Technologies,
  3. University of California, Berkeley. Copyright (c) 2012, The Regents of
  4. the University of California (Regents).
  5. Permission to use, copy, modify, distribute, and distribute modified versions
  6. of this software and its documentation without fee and without a signed
  7. licensing agreement, is hereby granted, provided that the above copyright
  8. notice, this paragraph and the following two paragraphs appear in all copies,
  9. modifications, and distributions.
  10. IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
  11. SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
  12. OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
  13. BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  14. REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
  15. THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  16. PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
  17. HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE
  18. MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  19. For bug reports and feature requests please email me at yotam@cnmat.berkeley.edu
  20. */
  21. #ifndef OSCMESSAGE_h
  22. #define OSCMESSAGE_h
  23. #include "OSCData.h"
  24. #include <Print.h>
  25. class OSCMessage
  26. {
  27. private:
  28. //friends
  29. friend class OSCBundle;
  30. /*=============================================================================
  31. PRIVATE VARIABLES
  32. =============================================================================*/
  33. //the address
  34. char * address;
  35. //the data
  36. OSCData ** data;
  37. //the number of OSCData in the data array
  38. int dataCount;
  39. //error codes for potential runtime problems
  40. OSCErrorCode error;
  41. /*=============================================================================
  42. DECODING INCOMING BYTES
  43. =============================================================================*/
  44. //the decoding states for incoming bytes
  45. enum DecodeState {
  46. STANDBY,
  47. ADDRESS,
  48. ADDRESS_PADDING,
  49. TYPES,
  50. TYPES_PADDING,
  51. DATA,
  52. DATA_PADDING,
  53. DONE,
  54. } decodeState;
  55. //stores incoming bytes until they can be decoded
  56. uint8_t * incomingBuffer;
  57. int incomingBufferSize; // how many bytes are stored
  58. int incomingBufferFree; // how many bytes are allocated but unused
  59. //adds a byte to the buffer
  60. void addToIncomingBuffer(uint8_t);
  61. //clears the incoming buffer
  62. void clearIncomingBuffer();
  63. //decoding function
  64. void decode(uint8_t);
  65. void decodeAddress();
  66. void decodeType(uint8_t);
  67. void decodeData(uint8_t);
  68. /*=============================================================================
  69. HELPER FUNCTIONS
  70. =============================================================================*/
  71. void setupMessage();
  72. //compares the OSCData's type char to a test char
  73. bool testType(int position, char type);
  74. //returns the number of bytes to pad to make it 4-bit aligned
  75. // int padSize(int bytes);
  76. public:
  77. //returns the OSCData at that position
  78. OSCData * getOSCData(int);
  79. /*=============================================================================
  80. CONSTRUCTORS / DESTRUCTOR
  81. =============================================================================*/
  82. //new constructor needs an address
  83. OSCMessage (const char * _address);
  84. //no address
  85. //placeholder since it's invalide OSC
  86. OSCMessage();
  87. //can optionally accept all of the data after the address
  88. //OSCMessage(const char * _address, char * types, ... );
  89. //created from another OSCMessage
  90. OSCMessage (OSCMessage *);
  91. //DESTRUCTOR
  92. ~OSCMessage();
  93. //empties all of the data
  94. OSCMessage& empty();
  95. /*=============================================================================
  96. SETTING DATA
  97. =============================================================================*/
  98. //returns the OSCMessage so that multiple 'add's can be strung together
  99. template <typename T>
  100. OSCMessage& add(T datum){
  101. //make a piece of data
  102. OSCData * d = new OSCData(datum);
  103. //check if it has any errors
  104. if (d->error == ALLOCFAILED){
  105. error = ALLOCFAILED;
  106. } else {
  107. //resize the data array
  108. OSCData ** dataMem = (OSCData **) realloc(data, sizeof(OSCData *) * (dataCount + 1));
  109. if (dataMem == NULL){
  110. error = ALLOCFAILED;
  111. } else {
  112. data = dataMem;
  113. //add data to the end of the array
  114. data[dataCount] = d;
  115. //increment the data size
  116. dataCount++;
  117. }
  118. }
  119. return *this;
  120. }
  121. //blob specific add
  122. OSCMessage& add(uint8_t * blob, int length){
  123. //make a piece of data
  124. OSCData * d = new OSCData(blob, length);
  125. //check if it has any errors
  126. if (d->error == ALLOCFAILED){
  127. error = ALLOCFAILED;
  128. } else {
  129. //resize the data array
  130. OSCData ** dataMem = (OSCData **) realloc(data, sizeof(OSCData *) * (dataCount + 1));
  131. if (dataMem == NULL){
  132. error = ALLOCFAILED;
  133. } else {
  134. data = dataMem;
  135. //add data to the end of the array
  136. data[dataCount] = d;
  137. //increment the data size
  138. dataCount++;
  139. }
  140. }
  141. return *this;
  142. }
  143. //sets the data at a position
  144. template <typename T>
  145. OSCMessage& set(int position, T datum){
  146. if (position < dataCount){
  147. //replace the OSCData with a new one
  148. OSCData * oldDatum = getOSCData(position);
  149. //destroy the old one
  150. delete oldDatum;
  151. //make a new one
  152. OSCData * newDatum = new OSCData(datum);
  153. //test if there was an error
  154. if (newDatum->error == ALLOCFAILED){
  155. error = ALLOCFAILED;
  156. } else {
  157. //otherwise, put it in the data array
  158. data[position] = newDatum;
  159. }
  160. } else if (position == (dataCount)){
  161. //add the data to the end
  162. add(datum);
  163. } else {
  164. //else out of bounds error
  165. error = INDEX_OUT_OF_BOUNDS;
  166. }
  167. return *this;
  168. }
  169. //blob specific setter
  170. OSCMessage& set(int position, uint8_t * blob, int length){
  171. if (position < dataCount){
  172. //replace the OSCData with a new one
  173. OSCData * oldDatum = getOSCData(position);
  174. //destroy the old one
  175. delete oldDatum;
  176. //make a new one
  177. OSCData * newDatum = new OSCData(blob, length);
  178. //test if there was an error
  179. if (newDatum->error == ALLOCFAILED){
  180. error = ALLOCFAILED;
  181. } else {
  182. //otherwise, put it in the data array
  183. data[position] = newDatum;
  184. }
  185. } else if (position == (dataCount)){
  186. //add the data to the end
  187. add(blob, length);
  188. } else {
  189. //else out of bounds error
  190. error = INDEX_OUT_OF_BOUNDS;
  191. }
  192. return *this;
  193. }
  194. OSCMessage& setAddress(const char *);
  195. /*=============================================================================
  196. GETTING DATA
  197. getters take a position as an argument
  198. =============================================================================*/
  199. int32_t getInt(int);
  200. osctime_t getTime(int);
  201. float getFloat(int);
  202. double getDouble(int);
  203. bool getBoolean(int);
  204. //return the copied string's length
  205. int getString(int, char *, int);
  206. //returns the number of unsigned int8's copied into the buffer
  207. int getBlob(int, uint8_t *, int);
  208. //returns the number of bytes of the data at that position
  209. int getDataLength(int);
  210. //returns the type at the position
  211. char getType(int);
  212. //put the address in the buffer
  213. int getAddress(char * buffer, int offset = 0);
  214. int getAddress(char * buffer, int offset, int len);
  215. // TODO: int getAddressLength(int offset = 0);
  216. /*=============================================================================
  217. TESTING DATA
  218. testers take a position as an argument
  219. =============================================================================*/
  220. bool isInt(int);
  221. bool isFloat(int);
  222. bool isBlob(int);
  223. bool isChar(int);
  224. bool isString(int);
  225. bool isDouble(int);
  226. bool isBoolean(int);
  227. bool isTime(int);
  228. /*=============================================================================
  229. PATTERN MATCHING
  230. =============================================================================*/
  231. //match the pattern against the address
  232. //returns true only for a complete match
  233. bool fullMatch( const char * pattern, int = 0);
  234. //returns the number of characters matched in the address
  235. int match( const char * pattern, int = 0);
  236. //calls the function with the message as the arg if it was a full match
  237. bool dispatch(const char * pattern, void (*callback)(OSCMessage &), int = 0);
  238. //like dispatch, but allows for partial matches
  239. //the address match offset is sent as an argument to the callback
  240. //also room for an option address offset to allow for multiple nested routes
  241. bool route(const char * pattern, void (*callback)(OSCMessage &, int), int = 0);
  242. /*=============================================================================
  243. SIZE
  244. =============================================================================*/
  245. //the number of data that the message contains
  246. int size();
  247. //computes the number of bytes the OSCMessage occupies if everything is 32-bit aligned
  248. int bytes();
  249. /*=============================================================================
  250. TRANSMISSION
  251. =============================================================================*/
  252. //send the message
  253. OSCMessage& send(Print &p);
  254. //fill the message from a byte stream
  255. OSCMessage& fill(uint8_t);
  256. OSCMessage& fill(uint8_t *, int);
  257. /*=============================================================================
  258. ERROR
  259. =============================================================================*/
  260. bool hasError();
  261. OSCErrorCode getError();
  262. };
  263. #endif