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.

413 lines
12KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCETICE project - Copyright 2009 by Lucio Asnaghi.
  4. JUCETICE is based around the JUCE library - "Jules' Utility Class Extensions"
  5. Copyright 2007 by Julian Storer.
  6. ------------------------------------------------------------------------------
  7. JUCE and JUCETICE can be redistributed and/or modified under the terms of
  8. the GNU General Public License, as published by the Free Software Foundation;
  9. either version 2 of the License, or (at your option) any later version.
  10. JUCE and JUCETICE are distributed in the hope that they will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with JUCE and JUCETICE; if not, visit www.gnu.org/licenses or write to
  16. Free Software Foundation, Inc., 59 Temple Place, Suite 330,
  17. Boston, MA 02111-1307 USA
  18. ==============================================================================
  19. This file is based around Niall Moody's OSC/UDP library, but was modified to
  20. be more independent and modularized, using the best practices from JUCE.
  21. ==============================================================================
  22. */
  23. #ifdef WIN32
  24. #include <winsock.h>
  25. #else
  26. #include <netinet/in.h>
  27. #endif
  28. BEGIN_JUCE_NAMESPACE
  29. //------------------------------------------------------------------------------
  30. OpenSoundMessage::OpenSoundMessage()
  31. : OpenSoundBase(),
  32. bufferSize(0),
  33. outgoingSize(0),
  34. buffer(0)
  35. {
  36. typeTag = ",";
  37. }
  38. //------------------------------------------------------------------------------
  39. OpenSoundMessage::OpenSoundMessage(char *data, const int size)
  40. : OpenSoundBase(),
  41. bufferSize(0),
  42. outgoingSize(0),
  43. buffer(0)
  44. {
  45. int i;
  46. GetTheBytes tempBytes;
  47. int32 tempint;
  48. float *tempf;
  49. String tempstr;
  50. //This represents which part of the Message we're currently reading from.
  51. int currentSection = 0;
  52. int currentTag = 1; //Because Type Tags start with ','.
  53. for(i=0;i<size;++i)
  54. {
  55. //Address.
  56. if(currentSection == 0)
  57. {
  58. if((data[i] != 0) && (data[i] != ','))
  59. address += data[i];
  60. else if(data[i] == ',')
  61. {
  62. typeTag = ",";
  63. ++currentSection;
  64. }
  65. }
  66. //Type Tag.
  67. else if(currentSection == 1)
  68. {
  69. if(data[i] != 0)
  70. typeTag += data[i];
  71. else if((i%4) == 3) //i.e. we're on the last byte of a 4 byte boundary.
  72. ++currentSection;
  73. }
  74. //The actual data.
  75. else
  76. {
  77. if(currentTag >= static_cast<int>(typeTag.length()))
  78. break;
  79. else if(typeTag[currentTag] == 'f')
  80. {
  81. tempBytes.a = data[i];
  82. ++i;
  83. tempBytes.b = data[i];
  84. ++i;
  85. tempBytes.c = data[i];
  86. ++i;
  87. tempBytes.d = data[i];
  88. tempint = ntohl(*(reinterpret_cast<int32 *>(&tempBytes)));
  89. tempf = reinterpret_cast<float *>(&tempint);
  90. floatArray.add (*tempf);
  91. ++currentTag;
  92. }
  93. else if(typeTag[currentTag] == 'i')
  94. {
  95. tempBytes.a = data[i];
  96. ++i;
  97. tempBytes.b = data[i];
  98. ++i;
  99. tempBytes.c = data[i];
  100. ++i;
  101. tempBytes.d = data[i];
  102. tempint = ntohl(*(reinterpret_cast<int32 *>(&tempBytes)));
  103. intArray.add (tempint);
  104. ++currentTag;
  105. }
  106. else if(typeTag[currentTag] == 's')
  107. {
  108. tempstr = "";
  109. while(data[i] != 0)
  110. {
  111. tempstr += data[i];
  112. ++i;
  113. }
  114. //@TODO
  115. //Not sure with this, it was
  116. //tempstr[tempstr.length()] = static_cast<char>(NULL); //Terminator.
  117. tempstr = tempstr.replaceCharacter (tempstr.getLastCharacter(),
  118. static_cast<char>(NULL)); //Terminator.
  119. stringArray.add (tempstr);
  120. //Handle any padding bytes.
  121. while((i%4) != 0)
  122. ++i;
  123. ++currentTag;
  124. }
  125. }
  126. }
  127. }
  128. //------------------------------------------------------------------------------
  129. OpenSoundMessage::~OpenSoundMessage()
  130. {
  131. if(buffer)
  132. {
  133. delete [] buffer;
  134. buffer = 0;
  135. }
  136. }
  137. //------------------------------------------------------------------------------
  138. int32 OpenSoundMessage::getSize()
  139. {
  140. int32 i;
  141. int32 tempint;
  142. outgoingSize = 0;
  143. if((address.length()+1)%4)
  144. {
  145. //Because we need space for the padding bytes.
  146. tempint = (4 - ((address.length()+1)%4));
  147. outgoingSize += address.length() + 1;
  148. outgoingSize += tempint;
  149. }
  150. else
  151. outgoingSize += address.length() + 1; //+1 = Null terminator.
  152. if((typeTag.length()+1)%4)
  153. {
  154. //Because we need space for the padding bytes.
  155. tempint = (4 - ((typeTag.length()+1)%4));
  156. outgoingSize += typeTag.length() + 1;
  157. outgoingSize += tempint;
  158. }
  159. else
  160. outgoingSize += typeTag.length() + 1; //+1 = Null terminator.
  161. outgoingSize += intArray.size() * sizeof(int32);
  162. outgoingSize += floatArray.size() * sizeof(float);
  163. for(i=0;i<static_cast<int32>(stringArray.size());++i)
  164. {
  165. if((stringArray[i].length()+1)%4)
  166. {
  167. //Because we need space for the padding bytes.
  168. tempint = (4 - ((stringArray[i].length()+1)%4));
  169. outgoingSize += stringArray[i].length() + 1;
  170. outgoingSize += tempint;
  171. }
  172. else
  173. outgoingSize += stringArray[i].length() + 1; //+1 = Null terminator.
  174. }
  175. if(outgoingSize > bufferSize)
  176. {
  177. bufferSize = outgoingSize;
  178. if(buffer)
  179. {
  180. delete [] buffer;
  181. buffer = 0;
  182. }
  183. buffer = new char[bufferSize];
  184. }
  185. return outgoingSize;
  186. }
  187. //------------------------------------------------------------------------------
  188. char *OpenSoundMessage::getData()
  189. {
  190. int32 addressCount = 0;
  191. int32 typeTagCount = 0;
  192. int32 intCount = 0;
  193. int32 floatCount = 0;
  194. int32 stringCount = 0;
  195. int32 currentTypeTag = 1;
  196. int32 i, j;
  197. GetTheBytes *tempBytes;
  198. int32 tempInt;
  199. float tempFloat;
  200. int32 addressLength = static_cast<int32>(address.length());
  201. int32 typeTagLength = static_cast<int32>(typeTag.length());
  202. int32 stringLength;
  203. if(!buffer)
  204. return 0;
  205. for(i=0;i<outgoingSize;++i)
  206. {
  207. //If we're currently writing the address to the buffer.
  208. if(addressCount < (addressLength + 1))
  209. {
  210. buffer[i] = address[addressCount];
  211. ++addressCount;
  212. if(addressCount == addressLength)
  213. {
  214. ++i;
  215. buffer[i] = static_cast<char>(NULL);
  216. ++addressCount;
  217. //Add any packing bytes.
  218. while(addressCount%4)
  219. {
  220. ++i;
  221. buffer[i] = static_cast<char>(NULL);
  222. ++addressCount;
  223. }
  224. }
  225. }
  226. //If we're currently writing the type tag to the buffer.
  227. else if(typeTagCount < (typeTagLength + 1))
  228. {
  229. buffer[i] = typeTag[typeTagCount];
  230. ++typeTagCount;
  231. if(typeTagCount == typeTagLength)
  232. {
  233. ++i;
  234. buffer[i] = static_cast<char>(NULL);
  235. ++typeTagCount;
  236. //Add any packing bytes.
  237. while(typeTagCount%4)
  238. {
  239. ++i;
  240. buffer[i] = static_cast<char>(NULL);
  241. ++typeTagCount;
  242. }
  243. }
  244. }
  245. //If we're currently writing part of the data to the buffer.
  246. else if(currentTypeTag < typeTagLength)
  247. {
  248. //Determine what kind of data we should be writing to the buffer.
  249. switch(typeTag[currentTypeTag])
  250. {
  251. //If we're writing an integer to the buffer.
  252. case 'i':
  253. tempInt = htonl(intArray[intCount]);
  254. tempBytes = reinterpret_cast<GetTheBytes *>(&tempInt);
  255. buffer[i] = tempBytes->a;
  256. ++i;
  257. buffer[i] = tempBytes->b;
  258. ++i;
  259. buffer[i] = tempBytes->c;
  260. ++i;
  261. buffer[i] = tempBytes->d;
  262. ++intCount;
  263. break;
  264. //If we're writing a float to the buffer.
  265. case 'f': {
  266. tempFloat = floatArray[floatCount];
  267. int32* const _i((int32*)&tempFloat);
  268. tempInt = htonl(*_i);
  269. tempBytes = reinterpret_cast<GetTheBytes *>(&tempInt);
  270. buffer[i] = tempBytes->a;
  271. ++i;
  272. buffer[i] = tempBytes->b;
  273. ++i;
  274. buffer[i] = tempBytes->c;
  275. ++i;
  276. buffer[i] = tempBytes->d;
  277. ++floatCount;
  278. break;
  279. }
  280. //If we're writing an OSC String to the buffer.
  281. case 's':
  282. stringLength = static_cast<int32>(stringArray[stringCount].length());
  283. for(j=1;j<stringLength;++j)
  284. {
  285. buffer[i] = stringArray[stringCount][j-1];
  286. ++i;
  287. }
  288. buffer[i] = static_cast<char>(NULL);
  289. //Add any packing bytes.
  290. while(j%4)
  291. {
  292. ++i;
  293. buffer[i] = static_cast<char>(NULL);
  294. ++j;
  295. }
  296. ++stringCount;
  297. break;
  298. }
  299. //Move on to the next tag in the message's type tag list.
  300. ++currentTypeTag;
  301. }
  302. }
  303. i = i;
  304. return buffer;
  305. }
  306. //------------------------------------------------------------------------------
  307. void OpenSoundMessage::clearMessage()
  308. {
  309. outgoingSize = 0;
  310. typeTag = ",";
  311. intArray.clear();
  312. floatArray.clear();
  313. stringArray.clear();
  314. }
  315. //------------------------------------------------------------------------------
  316. void OpenSoundMessage::setAddress(const String& val)
  317. {
  318. address = val;
  319. }
  320. //------------------------------------------------------------------------------
  321. void OpenSoundMessage::addInt32(const int32 val)
  322. {
  323. typeTag += 'i';
  324. intArray.add (val);
  325. }
  326. //------------------------------------------------------------------------------
  327. void OpenSoundMessage::addFloat32(const float val)
  328. {
  329. typeTag += 'f';
  330. floatArray.add (val);
  331. }
  332. //------------------------------------------------------------------------------
  333. void OpenSoundMessage::addOscString(const String& val)
  334. {
  335. typeTag += 's';
  336. stringArray.add (val);
  337. }
  338. //------------------------------------------------------------------------------
  339. bool OpenSoundMessage::isMessage(char *data, const int size)
  340. {
  341. int i;
  342. bool retval = false;
  343. //All OSC Messages start with the OSC address, which always starts with '/'.
  344. if(data[0] == '/')
  345. {
  346. for(i=1;i<size;++i)
  347. {
  348. //The comma marks the start of the Type Tag section of the message.
  349. //It'll always come at the start of a 4-byte boundary.
  350. if((data[i] == ',')&&((i%4) == 0))
  351. {
  352. retval = true;
  353. break;
  354. }
  355. }
  356. }
  357. return retval;
  358. }
  359. END_JUCE_NAMESPACE