Mercurial > hg > aimc
comparison external/oscpack/osc/OscReceivedElements.h @ 509:0284d2152e17
Add support for outputting featutes using OSC (for use with the Wekinator, etc).
author | tomwalters@google.com |
---|---|
date | Fri, 22 Jun 2012 12:22:08 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
508:d609725e568a | 509:0284d2152e17 |
---|---|
1 /* | |
2 oscpack -- Open Sound Control packet manipulation library | |
3 http://www.audiomulch.com/~rossb/oscpack | |
4 | |
5 Copyright (c) 2004-2005 Ross Bencina <rossb@audiomulch.com> | |
6 | |
7 Permission is hereby granted, free of charge, to any person obtaining | |
8 a copy of this software and associated documentation files | |
9 (the "Software"), to deal in the Software without restriction, | |
10 including without limitation the rights to use, copy, modify, merge, | |
11 publish, distribute, sublicense, and/or sell copies of the Software, | |
12 and to permit persons to whom the Software is furnished to do so, | |
13 subject to the following conditions: | |
14 | |
15 The above copyright notice and this permission notice shall be | |
16 included in all copies or substantial portions of the Software. | |
17 | |
18 Any person wishing to distribute modifications to the Software is | |
19 requested to send the modifications to the original developer so that | |
20 they can be incorporated into the canonical version. | |
21 | |
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |
23 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
24 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | |
25 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR | |
26 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF | |
27 CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | |
28 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |
29 */ | |
30 #ifndef INCLUDED_OSCRECEIVEDELEMENTS_H | |
31 #define INCLUDED_OSCRECEIVEDELEMENTS_H | |
32 | |
33 #include "OscTypes.h" | |
34 #include "OscException.h" | |
35 | |
36 | |
37 namespace osc{ | |
38 | |
39 | |
40 class MalformedMessageException : public Exception{ | |
41 public: | |
42 MalformedMessageException( const char *w="malformed message" ) | |
43 : Exception( w ) {} | |
44 }; | |
45 | |
46 class MalformedBundleException : public Exception{ | |
47 public: | |
48 MalformedBundleException( const char *w="malformed bundle" ) | |
49 : Exception( w ) {} | |
50 }; | |
51 | |
52 class WrongArgumentTypeException : public Exception{ | |
53 public: | |
54 WrongArgumentTypeException( const char *w="wrong argument type" ) | |
55 : Exception( w ) {} | |
56 }; | |
57 | |
58 class MissingArgumentException : public Exception{ | |
59 public: | |
60 MissingArgumentException( const char *w="missing argument" ) | |
61 : Exception( w ) {} | |
62 }; | |
63 | |
64 class ExcessArgumentException : public Exception{ | |
65 public: | |
66 ExcessArgumentException( const char *w="too many arguments" ) | |
67 : Exception( w ) {} | |
68 }; | |
69 | |
70 | |
71 class ReceivedPacket{ | |
72 public: | |
73 ReceivedPacket( const char *contents, int32 size ) | |
74 : contents_( contents ) | |
75 , size_( size ) {} | |
76 | |
77 bool IsMessage() const { return !IsBundle(); } | |
78 bool IsBundle() const; | |
79 | |
80 int32 Size() const { return size_; } | |
81 const char *Contents() const { return contents_; } | |
82 | |
83 private: | |
84 const char *contents_; | |
85 int32 size_; | |
86 }; | |
87 | |
88 | |
89 class ReceivedBundleElement{ | |
90 public: | |
91 ReceivedBundleElement( const char *size ) | |
92 : size_( size ) {} | |
93 | |
94 friend class ReceivedBundleElementIterator; | |
95 | |
96 bool IsMessage() const { return !IsBundle(); } | |
97 bool IsBundle() const; | |
98 | |
99 int32 Size() const; | |
100 const char *Contents() const { return size_ + 4; } | |
101 | |
102 private: | |
103 const char *size_; | |
104 }; | |
105 | |
106 | |
107 class ReceivedBundleElementIterator{ | |
108 public: | |
109 ReceivedBundleElementIterator( const char *sizePtr ) | |
110 : value_( sizePtr ) {} | |
111 | |
112 ReceivedBundleElementIterator operator++() | |
113 { | |
114 Advance(); | |
115 return *this; | |
116 } | |
117 | |
118 ReceivedBundleElementIterator operator++(int) | |
119 { | |
120 ReceivedBundleElementIterator old( *this ); | |
121 Advance(); | |
122 return old; | |
123 } | |
124 | |
125 const ReceivedBundleElement& operator*() const { return value_; } | |
126 | |
127 const ReceivedBundleElement* operator->() const { return &value_; } | |
128 | |
129 friend bool operator==(const ReceivedBundleElementIterator& lhs, | |
130 const ReceivedBundleElementIterator& rhs ); | |
131 | |
132 private: | |
133 ReceivedBundleElement value_; | |
134 | |
135 void Advance() { value_.size_ = value_.Contents() + value_.Size(); } | |
136 | |
137 bool IsEqualTo( const ReceivedBundleElementIterator& rhs ) const | |
138 { | |
139 return value_.size_ == rhs.value_.size_; | |
140 } | |
141 }; | |
142 | |
143 inline bool operator==(const ReceivedBundleElementIterator& lhs, | |
144 const ReceivedBundleElementIterator& rhs ) | |
145 { | |
146 return lhs.IsEqualTo( rhs ); | |
147 } | |
148 | |
149 inline bool operator!=(const ReceivedBundleElementIterator& lhs, | |
150 const ReceivedBundleElementIterator& rhs ) | |
151 { | |
152 return !( lhs == rhs ); | |
153 } | |
154 | |
155 | |
156 class ReceivedMessageArgument{ | |
157 public: | |
158 ReceivedMessageArgument( const char *typeTag, const char *argument ) | |
159 : typeTag_( typeTag ) | |
160 , argument_( argument ) {} | |
161 | |
162 friend class ReceivedMessageArgumentIterator; | |
163 | |
164 const char TypeTag() const { return *typeTag_; } | |
165 | |
166 // the unchecked methods below don't check whether the argument actually | |
167 // is of the specified type. they should only be used if you've already | |
168 // checked the type tag or the associated IsType() method. | |
169 | |
170 bool IsBool() const | |
171 { return *typeTag_ == TRUE_TYPE_TAG || *typeTag_ == FALSE_TYPE_TAG; } | |
172 bool AsBool() const; | |
173 bool AsBoolUnchecked() const; | |
174 | |
175 bool IsNil() const { return *typeTag_ == NIL_TYPE_TAG; } | |
176 bool IsInfinitum() const { return *typeTag_ == INFINITUM_TYPE_TAG; } | |
177 | |
178 bool IsInt32() const { return *typeTag_ == INT32_TYPE_TAG; } | |
179 int32 AsInt32() const; | |
180 int32 AsInt32Unchecked() const; | |
181 | |
182 bool IsFloat() const { return *typeTag_ == FLOAT_TYPE_TAG; } | |
183 float AsFloat() const; | |
184 float AsFloatUnchecked() const; | |
185 | |
186 bool IsChar() const { return *typeTag_ == CHAR_TYPE_TAG; } | |
187 char AsChar() const; | |
188 char AsCharUnchecked() const; | |
189 | |
190 bool IsRgbaColor() const { return *typeTag_ == RGBA_COLOR_TYPE_TAG; } | |
191 uint32 AsRgbaColor() const; | |
192 uint32 AsRgbaColorUnchecked() const; | |
193 | |
194 bool IsMidiMessage() const { return *typeTag_ == MIDI_MESSAGE_TYPE_TAG; } | |
195 uint32 AsMidiMessage() const; | |
196 uint32 AsMidiMessageUnchecked() const; | |
197 | |
198 bool IsInt64() const { return *typeTag_ == INT64_TYPE_TAG; } | |
199 int64 AsInt64() const; | |
200 int64 AsInt64Unchecked() const; | |
201 | |
202 bool IsTimeTag() const { return *typeTag_ == TIME_TAG_TYPE_TAG; } | |
203 uint64 AsTimeTag() const; | |
204 uint64 AsTimeTagUnchecked() const; | |
205 | |
206 bool IsDouble() const { return *typeTag_ == DOUBLE_TYPE_TAG; } | |
207 double AsDouble() const; | |
208 double AsDoubleUnchecked() const; | |
209 | |
210 bool IsString() const { return *typeTag_ == STRING_TYPE_TAG; } | |
211 const char* AsString() const; | |
212 const char* AsStringUnchecked() const { return argument_; } | |
213 | |
214 bool IsSymbol() const { return *typeTag_ == SYMBOL_TYPE_TAG; } | |
215 const char* AsSymbol() const; | |
216 const char* AsSymbolUnchecked() const { return argument_; } | |
217 | |
218 bool IsBlob() const { return *typeTag_ == BLOB_TYPE_TAG; } | |
219 void AsBlob( const void*& data, unsigned long& size ) const; | |
220 void AsBlobUnchecked( const void*& data, unsigned long& size ) const; | |
221 | |
222 private: | |
223 const char *typeTag_; | |
224 const char *argument_; | |
225 }; | |
226 | |
227 | |
228 class ReceivedMessageArgumentIterator{ | |
229 public: | |
230 ReceivedMessageArgumentIterator( const char *typeTags, const char *arguments ) | |
231 : value_( typeTags, arguments ) {} | |
232 | |
233 ReceivedMessageArgumentIterator operator++() | |
234 { | |
235 Advance(); | |
236 return *this; | |
237 } | |
238 | |
239 ReceivedMessageArgumentIterator operator++(int) | |
240 { | |
241 ReceivedMessageArgumentIterator old( *this ); | |
242 Advance(); | |
243 return old; | |
244 } | |
245 | |
246 const ReceivedMessageArgument& operator*() const { return value_; } | |
247 | |
248 const ReceivedMessageArgument* operator->() const { return &value_; } | |
249 | |
250 friend bool operator==(const ReceivedMessageArgumentIterator& lhs, | |
251 const ReceivedMessageArgumentIterator& rhs ); | |
252 | |
253 private: | |
254 ReceivedMessageArgument value_; | |
255 | |
256 void Advance(); | |
257 | |
258 bool IsEqualTo( const ReceivedMessageArgumentIterator& rhs ) const | |
259 { | |
260 return value_.typeTag_ == rhs.value_.typeTag_; | |
261 } | |
262 }; | |
263 | |
264 inline bool operator==(const ReceivedMessageArgumentIterator& lhs, | |
265 const ReceivedMessageArgumentIterator& rhs ) | |
266 { | |
267 return lhs.IsEqualTo( rhs ); | |
268 } | |
269 | |
270 inline bool operator!=(const ReceivedMessageArgumentIterator& lhs, | |
271 const ReceivedMessageArgumentIterator& rhs ) | |
272 { | |
273 return !( lhs == rhs ); | |
274 } | |
275 | |
276 | |
277 class ReceivedMessageArgumentStream{ | |
278 friend class ReceivedMessage; | |
279 ReceivedMessageArgumentStream( const ReceivedMessageArgumentIterator& begin, | |
280 const ReceivedMessageArgumentIterator& end ) | |
281 : p_( begin ) | |
282 , end_( end ) {} | |
283 | |
284 ReceivedMessageArgumentIterator p_, end_; | |
285 | |
286 public: | |
287 | |
288 // end of stream | |
289 bool Eos() const { return p_ == end_; } | |
290 | |
291 ReceivedMessageArgumentStream& operator>>( bool& rhs ) | |
292 { | |
293 if( Eos() ) | |
294 throw MissingArgumentException(); | |
295 | |
296 rhs = (*p_++).AsBool(); | |
297 return *this; | |
298 } | |
299 | |
300 // not sure if it would be useful to stream Nil and Infinitum | |
301 // for now it's not possible | |
302 | |
303 ReceivedMessageArgumentStream& operator>>( int32& rhs ) | |
304 { | |
305 if( Eos() ) | |
306 throw MissingArgumentException(); | |
307 | |
308 rhs = (*p_++).AsInt32(); | |
309 return *this; | |
310 } | |
311 | |
312 ReceivedMessageArgumentStream& operator>>( float& rhs ) | |
313 { | |
314 if( Eos() ) | |
315 throw MissingArgumentException(); | |
316 | |
317 rhs = (*p_++).AsFloat(); | |
318 return *this; | |
319 } | |
320 | |
321 ReceivedMessageArgumentStream& operator>>( char& rhs ) | |
322 { | |
323 if( Eos() ) | |
324 throw MissingArgumentException(); | |
325 | |
326 rhs = (*p_++).AsChar(); | |
327 return *this; | |
328 } | |
329 | |
330 ReceivedMessageArgumentStream& operator>>( RgbaColor& rhs ) | |
331 { | |
332 if( Eos() ) | |
333 throw MissingArgumentException(); | |
334 | |
335 rhs.value = (*p_++).AsRgbaColor(); | |
336 return *this; | |
337 } | |
338 | |
339 ReceivedMessageArgumentStream& operator>>( MidiMessage& rhs ) | |
340 { | |
341 if( Eos() ) | |
342 throw MissingArgumentException(); | |
343 | |
344 rhs.value = (*p_++).AsMidiMessage(); | |
345 return *this; | |
346 } | |
347 | |
348 ReceivedMessageArgumentStream& operator>>( int64& rhs ) | |
349 { | |
350 if( Eos() ) | |
351 throw MissingArgumentException(); | |
352 | |
353 rhs = (*p_++).AsInt64(); | |
354 return *this; | |
355 } | |
356 | |
357 ReceivedMessageArgumentStream& operator>>( TimeTag& rhs ) | |
358 { | |
359 if( Eos() ) | |
360 throw MissingArgumentException(); | |
361 | |
362 rhs.value = (*p_++).AsTimeTag(); | |
363 return *this; | |
364 } | |
365 | |
366 ReceivedMessageArgumentStream& operator>>( double& rhs ) | |
367 { | |
368 if( Eos() ) | |
369 throw MissingArgumentException(); | |
370 | |
371 rhs = (*p_++).AsDouble(); | |
372 return *this; | |
373 } | |
374 | |
375 ReceivedMessageArgumentStream& operator>>( Blob& rhs ) | |
376 { | |
377 if( Eos() ) | |
378 throw MissingArgumentException(); | |
379 | |
380 (*p_++).AsBlob( rhs.data, rhs.size ); | |
381 return *this; | |
382 } | |
383 | |
384 ReceivedMessageArgumentStream& operator>>( const char*& rhs ) | |
385 { | |
386 if( Eos() ) | |
387 throw MissingArgumentException(); | |
388 | |
389 rhs = (*p_++).AsString(); | |
390 return *this; | |
391 } | |
392 | |
393 ReceivedMessageArgumentStream& operator>>( Symbol& rhs ) | |
394 { | |
395 if( Eos() ) | |
396 throw MissingArgumentException(); | |
397 | |
398 rhs.value = (*p_++).AsSymbol(); | |
399 return *this; | |
400 } | |
401 | |
402 ReceivedMessageArgumentStream& operator>>( MessageTerminator& rhs ) | |
403 { | |
404 if( !Eos() ) | |
405 throw ExcessArgumentException(); | |
406 | |
407 return *this; | |
408 } | |
409 }; | |
410 | |
411 | |
412 class ReceivedMessage{ | |
413 void Init( const char *bundle, unsigned long size ); | |
414 public: | |
415 explicit ReceivedMessage( const ReceivedPacket& packet ); | |
416 explicit ReceivedMessage( const ReceivedBundleElement& bundleElement ); | |
417 | |
418 const char *AddressPattern() const { return addressPattern_; } | |
419 | |
420 // Support for non-standad SuperCollider integer address patterns: | |
421 bool AddressPatternIsUInt32() const; | |
422 uint32 AddressPatternAsUInt32() const; | |
423 | |
424 unsigned long ArgumentCount() const { return static_cast<unsigned long>(typeTagsEnd_ - typeTagsBegin_); } | |
425 | |
426 const char *TypeTags() const { return typeTagsBegin_; } | |
427 | |
428 | |
429 typedef ReceivedMessageArgumentIterator const_iterator; | |
430 | |
431 ReceivedMessageArgumentIterator ArgumentsBegin() const | |
432 { | |
433 return ReceivedMessageArgumentIterator( typeTagsBegin_, arguments_ ); | |
434 } | |
435 | |
436 ReceivedMessageArgumentIterator ArgumentsEnd() const | |
437 { | |
438 return ReceivedMessageArgumentIterator( typeTagsEnd_, 0 ); | |
439 } | |
440 | |
441 ReceivedMessageArgumentStream ArgumentStream() const | |
442 { | |
443 return ReceivedMessageArgumentStream( ArgumentsBegin(), ArgumentsEnd() ); | |
444 } | |
445 | |
446 private: | |
447 const char *addressPattern_; | |
448 const char *typeTagsBegin_; | |
449 const char *typeTagsEnd_; | |
450 const char *arguments_; | |
451 }; | |
452 | |
453 | |
454 class ReceivedBundle{ | |
455 void Init( const char *message, unsigned long size ); | |
456 public: | |
457 explicit ReceivedBundle( const ReceivedPacket& packet ); | |
458 explicit ReceivedBundle( const ReceivedBundleElement& bundleElement ); | |
459 | |
460 uint64 TimeTag() const; | |
461 | |
462 unsigned long ElementCount() const { return elementCount_; } | |
463 | |
464 typedef ReceivedBundleElementIterator const_iterator; | |
465 | |
466 ReceivedBundleElementIterator ElementsBegin() const | |
467 { | |
468 return ReceivedBundleElementIterator( timeTag_ + 8 ); | |
469 } | |
470 | |
471 ReceivedBundleElementIterator ElementsEnd() const | |
472 { | |
473 return ReceivedBundleElementIterator( end_ ); | |
474 } | |
475 | |
476 private: | |
477 const char *timeTag_; | |
478 const char *end_; | |
479 unsigned long elementCount_; | |
480 }; | |
481 | |
482 | |
483 } // namespace osc | |
484 | |
485 | |
486 #endif /* INCLUDED_OSCRECEIVEDELEMENTS_H */ |