Allolib  1.0
C++ Components For Interactive Multimedia
al_OSC.hpp
1 #ifndef INCLUDE_AL_OSC_HPP
2 #define INCLUDE_AL_OSC_HPP
3 
4 /* Allocore --
5  Multimedia / virtual environment application class library
6 
7  Copyright (C) 2009. AlloSphere Research Group, Media Arts & Technology,
8  UCSB. Copyright (C) 2012. The Regents of the University of California. All
9  rights reserved.
10 
11  Redistribution and use in source and binary forms, with or without
12  modification, are permitted provided that the following conditions are
13  met:
14 
15  Redistributions of source code must retain the above copyright
16  notice, this list of conditions and the following disclaimer.
17 
18  Redistributions in binary form must reproduce the above
19  copyright notice, this list of conditions and the following disclaimer in the
20  documentation and/or other materials provided with the
21  distribution.
22 
23  Neither the name of the University of California nor the names
24  of its contributors may be used to endorse or promote products derived from
25  this software without specific prior written permission.
26 
27  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
28  IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
31  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
32  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
33  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
34  OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
35  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
36  OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
37  ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 
39  File description:
40  Objects for reading, writing, sending, and receiving
41  OSC (Open Sound Control) packets.
42 
43  File author(s):
44  Lance Putnam, 2010, putnam.lance@gmail.com
45  Graham Wakefield, 2010, grrrwaaa@gmail.com
46  Keehong Youn, 2017, younkeehong@gmail.com
47 */
48 
49 #include <memory>
50 #include <string>
51 #include <vector>
52 
53 #include "al/system/al_Thread.hpp"
54 #include "al/system/al_Time.hpp"
55 
56 namespace al {
57 
59 namespace osc {
60 
64 struct Blob {
65  Blob() {}
66  explicit Blob(const void *data_, unsigned long size_)
67  : data(data_), size(size_) {}
68  const void *data;
69  unsigned long size;
70 };
71 
73 
80 typedef unsigned long long TimeTag;
81 
85 class Packet {
86 public:
88  Packet(int size = 1024);
89 
92  Packet(const char *contents, size_t size);
93 
94  ~Packet();
95 
96  const char *data() const;
97  bool isMessage() const;
98  bool isBundle() const;
99 
101  void printRaw() const;
102 
104  size_t size() const;
105 
107  Packet &beginBundle(TimeTag timeTag = 1);
108 
111 
113  Packet &beginMessage(const std::string &addressPattern);
114 
117 
119  Packet &addMessage(const std::string &addr) {
120  beginMessage(addr);
121  return endMessage();
122  }
123 
125  template <class A> Packet &addMessage(const std::string &addr, const A &a) {
126  beginMessage(addr);
127  (*this) << a;
128  return endMessage();
129  }
130 
132  template <class A, class B>
133  Packet &addMessage(const std::string &addr, const A &a, const B &b) {
134  beginMessage(addr);
135  (*this) << a << b;
136  return endMessage();
137  }
138 
140  template <class A, class B, class C>
141  Packet &addMessage(const std::string &addr, const A &a, const B &b,
142  const C &c) {
143  beginMessage(addr);
144  (*this) << a << b << c;
145  return endMessage();
146  }
147 
149  template <class A, class B, class C, class D>
150  Packet &addMessage(const std::string &addr, const A &a, const B &b,
151  const C &c, const D &d) {
152  beginMessage(addr);
153  (*this) << a << b << c << d;
154  return endMessage();
155  }
156 
158  template <class A, class B, class C, class D, class E>
159  Packet &addMessage(const std::string &addr, const A &a, const B &b,
160  const C &c, const D &d, const E &e) {
161  beginMessage(addr);
162  (*this) << a << b << c << d << e;
163  return endMessage();
164  }
165 
167  template <class A, class B, class C, class D, class E, class F>
168  Packet &addMessage(const std::string &addr, const A &a, const B &b,
169  const C &c, const D &d, const E &e, const F &f) {
170  beginMessage(addr);
171  (*this) << a << b << c << d << e << f;
172  return endMessage();
173  }
174 
176  template <class A, class B, class C, class D, class E, class F, class G>
177  Packet &addMessage(const std::string &addr, const A &a, const B &b,
178  const C &c, const D &d, const E &e, const F &f,
179  const G &g) {
180  beginMessage(addr);
181  (*this) << a << b << c << d << e << f << g;
182  return endMessage();
183  }
184 
186  template <class A, class B, class C, class D, class E, class F, class G,
187  class H>
188  Packet &addMessage(const std::string &addr, const A &a, const B &b,
189  const C &c, const D &d, const E &e, const F &f, const G &g,
190  const H &h) {
191  beginMessage(addr);
192  (*this) << a << b << c << d << e << f << g << h;
193  return endMessage();
194  }
195 
196  Packet &operator<<(int v);
197  Packet &operator<<(unsigned v);
198  Packet &operator<<(float v);
199  Packet &operator<<(double v);
200  Packet &operator<<(char v);
201  Packet &operator<<(const char *v);
202  Packet &operator<<(const std::string &v);
203  Packet &operator<<(const Blob &v);
204 
207 
208 protected:
209  class Impl;
210  Impl *mImpl;
211  std::vector<char> mData;
212 };
213 
217 class Message {
218 public:
224  Message(const char *message, int size, const TimeTag &timeTag = 1,
225  const char *senderAddr = nullptr);
226  ~Message();
227 
229  void print() const;
230 
232 
235  const TimeTag &timeTag() const { return mTimeTag; }
236 
238  const std::string &addressPattern() const { return mAddressPattern; }
239 
240  const std::string senderAddress() const { return std::string(mSenderAddr); }
241 
243  const std::string &typeTags() const { return mTypeTags; }
244 
247 
248  Message &operator>>(int &v);
249  Message &operator>>(float &v);
250  Message &operator>>(double &v);
251  Message &operator>>(char &v);
252  Message &
253  operator>>(const char *&v);
254  Message &
255  operator>>(std::string &v);
257 
258 protected:
259  class Impl;
260  Impl *mImpl;
261  std::string mAddressPattern;
262  std::string mTypeTags;
263  TimeTag mTimeTag;
264  char mSenderAddr[32];
265 };
266 
272 public:
273  virtual ~PacketHandler() {}
274 
276  virtual void onMessage(Message &m) = 0;
277 };
278 
287 public:
288  virtual ~MessageConsumer() {}
290  virtual bool consumeMessage(Message &m, std::string rootOSCPath) = 0;
291 };
292 
296 class Send : public Packet {
297  class SocketSender;
298  std::unique_ptr<SocketSender> socketSender;
299  std::string mAddress = "";
300  uint16_t mPort = 0;
301 
302 public:
303  Send();
304  Send(int size);
305 
311  Send(uint16_t port, const char *address = "localhost", al_sec timeout = 0,
312  int size = 1024);
313 
314  ~Send();
315 
316  bool open(uint16_t port, const char *address);
317 
318  const std::string &address() const { return mAddress; }
319  uint16_t port() const { return mPort; }
320 
322  size_t send();
323 
325  size_t send(const Packet &p);
326 
328  size_t send(const std::string &addr) {
329  addMessage(addr);
330  return send();
331  }
332 
334  template <class A> size_t send(const std::string &addr, const A &a) {
335  addMessage(addr, a);
336  return send();
337  }
338 
340  template <class A, class B>
341  size_t send(const std::string &addr, const A &a, const B &b) {
342  addMessage(addr, a, b);
343  return send();
344  }
345 
347  template <class A, class B, class C>
348  size_t send(const std::string &addr, const A &a, const B &b, const C &c) {
349  addMessage(addr, a, b, c);
350  return send();
351  }
352 
354  template <class A, class B, class C, class D>
355  size_t send(const std::string &addr, const A &a, const B &b, const C &c,
356  const D &d) {
357  addMessage(addr, a, b, c, d);
358  return send();
359  }
360 
362  template <class A, class B, class C, class D, class E>
363  size_t send(const std::string &addr, const A &a, const B &b, const C &c,
364  const D &d, const E &e) {
365  addMessage(addr, a, b, c, d, e);
366  return send();
367  }
368 
370  template <class A, class B, class C, class D, class E, class F>
371  size_t send(const std::string &addr, const A &a, const B &b, const C &c,
372  const D &d, const E &e, const F &f) {
373  addMessage(addr, a, b, c, d, e, f);
374  return send();
375  }
376 
378  template <class A, class B, class C, class D, class E, class F, class G>
379  size_t send(const std::string &addr, const A &a, const B &b, const C &c,
380  const D &d, const E &e, const F &f, const G &g) {
381  addMessage(addr, a, b, c, d, e, f, g);
382  return send();
383  }
385  template <class A, class B, class C, class D, class E, class F, class G,
386  class H>
387  size_t send(const std::string &addr, const A &a, const B &b, const C &c,
388  const D &d, const E &e, const F &f, const G &g, const H &h) {
389  addMessage(addr, a, b, c, d, e, f, g, h);
390  return send();
391  }
392 };
393 
395 
399 class Recv {
400  class SocketReceiver;
401  std::unique_ptr<SocketReceiver> socketReceiver;
402 
403 public:
404  Recv();
405 
411  Recv(uint16_t port, const char *address = "", al_sec timeout = 0);
412 
413  virtual ~Recv();
414 
415  bool open(uint16_t port, const char *address = "", al_sec timeout = 0);
416 
417  bool isOpen() { return mOpen; }
418 
419  const std::string &address() const { return mAddress; }
420  uint16_t port() const { return mPort; }
421 
423  bool background() const { return mBackground; }
424 
426  const char *data() const { return &mBuffer[0]; }
427 
429  void bufferSize(int n) { mBuffer.resize(n); }
430 
433  mHandlers.clear();
434  return appendHandler(v);
435  }
436 
439  mHandlers.push_back(&v);
440  return *this;
441  }
442 
446  int recv();
447 
449 
452  bool start();
453 
455  void stop();
456 
457  void parse(const char *packet, int size, const char *senderAddr);
458  void loop();
459 
460  static bool portAvailable(uint16_t port, const char *address = "");
461 
462  static std::vector<std::shared_ptr<Message>>
463  parse(const char *packet, int size, TimeTag timeTag = 1,
464  const char *senderAddr = nullptr);
465 
466 protected:
467  std::vector<PacketHandler *> mHandlers;
468  std::vector<char> mBuffer;
469  al::Thread mThread;
470  bool mBackground;
471  std::string mAddress = "";
472  uint16_t mPort = 0;
473  bool mOpen{false};
474 };
475 
476 } // namespace osc
477 } // namespace al
478 
479 #endif
virtual bool consumeMessage(Message &m, std::string rootOSCPath)=0
Returns true if message was consumed by this class.
const TimeTag & timeTag() const
Get time tag.
Definition: al_OSC.hpp:235
Message(const char *message, int size, const TimeTag &timeTag=1, const char *senderAddr=nullptr)
Message & operator>>(char &v)
Extract next stream element as char.
void print() const
Pretty-print message information.
Message & operator>>(int &v)
Extract next stream element as integer.
const std::string & typeTags() const
Get type tags.
Definition: al_OSC.hpp:243
Message & resetStream()
Reset stream for converting from raw message bytes to types.
Message & operator>>(const char *&v)
Extract next stream element as C-string.
Message & operator>>(Blob &v)
Extract next stream element as Blob.
const std::string & addressPattern() const
Get address pattern.
Definition: al_OSC.hpp:238
Message & operator>>(double &v)
Extract next stream element as double.
Message & operator>>(std::string &v)
Extract next stream element as string.
Message & operator>>(float &v)
Extract next stream element as float.
virtual void onMessage(Message &m)=0
Called for each message contained in packet.
bool isMessage() const
Whether packet is a message.
Packet & beginMessage(const std::string &addressPattern)
Start a new message.
Packet & operator<<(double v)
Add double to message.
Packet & endBundle()
End bundle.
Packet & operator<<(const std::string &v)
Add string to message.
Packet & addMessage(const std::string &addr)
Add zero argument message.
Definition: al_OSC.hpp:119
bool isBundle() const
Whether packet is a bundle.
void printRaw() const
Pretty-print raw packet bytes.
Packet(int size=1024)
Packet & operator<<(const char *v)
Add C-string to message.
Packet & addMessage(const std::string &addr, const A &a, const B &b, const C &c, const D &d, const E &e, const F &f, const G &g)
Add seven argument message.
Definition: al_OSC.hpp:177
Packet & operator<<(const Blob &v)
Add Blob to message.
Packet & operator<<(unsigned v)
Add integer to message.
Packet & operator<<(int v)
Add integer to message.
Packet & addMessage(const std::string &addr, const A &a, const B &b, const C &c)
Add three argument message.
Definition: al_OSC.hpp:141
Packet & addMessage(const std::string &addr, const A &a, const B &b, const C &c, const D &d, const E &e)
Add five argument message.
Definition: al_OSC.hpp:159
Packet(const char *contents, size_t size)
Packet & beginBundle(TimeTag timeTag=1)
Begin a new bundle.
Packet & operator<<(char v)
Add char to message.
Packet & clear()
Clear current packet contents.
Packet & addMessage(const std::string &addr, const A &a, const B &b, const C &c, const D &d, const E &e, const F &f, const G &g, const H &h)
Add eight argument message.
Definition: al_OSC.hpp:188
Packet & addMessage(const std::string &addr, const A &a, const B &b)
Add two argument message.
Definition: al_OSC.hpp:133
Packet & addMessage(const std::string &addr, const A &a, const B &b, const C &c, const D &d, const E &e, const F &f)
Add six argument message.
Definition: al_OSC.hpp:168
size_t size() const
Get number of bytes of current packet data.
Packet & addMessage(const std::string &addr, const A &a, const B &b, const C &c, const D &d)
Add four argument message.
Definition: al_OSC.hpp:150
const char * data() const
Get raw packet data.
Packet & operator<<(float v)
Add float to message.
Packet & addMessage(const std::string &addr, const A &a)
Add one argument message.
Definition: al_OSC.hpp:125
Packet & endMessage()
End message.
Socket for receiving OSC packets.
Definition: al_OSC.hpp:399
bool start()
Begin a background thread to poll the socket.
Recv & appendHandler(PacketHandler &v)
Add a packet handler to list. All handlers get all messages.
Definition: al_OSC.hpp:438
void stop()
Stop the background polling.
void bufferSize(int n)
Set size of internal buffer.
Definition: al_OSC.hpp:429
bool background() const
Whether background polling is activated.
Definition: al_OSC.hpp:423
Recv(uint16_t port, const char *address="", al_sec timeout=0)
const char * data() const
Get current received packet data.
Definition: al_OSC.hpp:426
Recv & handler(PacketHandler &v)
Set packet handling routine.
Definition: al_OSC.hpp:432
size_t send(const std::string &addr, const A &a, const B &b, const C &c)
Send three argument message immediately.
Definition: al_OSC.hpp:348
size_t send(const std::string &addr, const A &a, const B &b, const C &c, const D &d, const E &e)
Send five argument message immediately.
Definition: al_OSC.hpp:363
size_t send(const std::string &addr, const A &a, const B &b)
Send two argument message immediately.
Definition: al_OSC.hpp:341
size_t send(const std::string &addr, const A &a, const B &b, const C &c, const D &d, const E &e, const F &f, const G &g, const H &h)
Send eight argument message immediately.
Definition: al_OSC.hpp:387
size_t send()
Send and clear current packet contents.
Send(uint16_t port, const char *address="localhost", al_sec timeout=0, int size=1024)
size_t send(const std::string &addr)
Send zero argument message immediately.
Definition: al_OSC.hpp:328
size_t send(const std::string &addr, const A &a, const B &b, const C &c, const D &d)
Send four argument message immediately.
Definition: al_OSC.hpp:355
size_t send(const std::string &addr, const A &a)
Send one argument message immediately.
Definition: al_OSC.hpp:334
size_t send(const Packet &p)
Send a packet.
size_t send(const std::string &addr, const A &a, const B &b, const C &c, const D &d, const E &e, const F &f)
Send six argument message immediately.
Definition: al_OSC.hpp:371
size_t send(const std::string &addr, const A &a, const B &b, const C &c, const D &d, const E &e, const F &f, const G &g)
Send seven argument message immediately.
Definition: al_OSC.hpp:379
unsigned long long TimeTag
Time tag.
Definition: al_OSC.hpp:80
Definition: al_App.hpp:23