Audio plugin host https://kx.studio/carla
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.

257 lines
7.1KB

  1. /*
  2. * Copyright (c) 2012 Mark McCurry
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining a
  5. * copy of this software and associated documentation files (the "Software"),
  6. * to deal in the Software without restriction, including without limitation
  7. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  8. * and/or sell copies of the Software, and to permit persons to whom the
  9. * Software is furnished to do so, subject to the following conditions:
  10. *
  11. * The above copyright notice and this permission notice (including the next
  12. * paragraph) shall be included in all copies or substantial portions of the
  13. * Software.
  14. *
  15. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  16. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  17. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  18. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  19. * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  20. * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  22. * DEALINGS IN THE SOFTWARE.
  23. */
  24. #ifndef RTOSC_PORTS
  25. #define RTOSC_PORTS
  26. #include <vector>
  27. #include <functional>
  28. #include <initializer_list>
  29. #include <rtosc/rtosc.h>
  30. #include <cstring>
  31. #include <cctype>
  32. #include <cstdlib>
  33. #include <cstdio>
  34. #include <string>
  35. namespace rtosc {
  36. //First define all types
  37. typedef const char *msg_t;
  38. struct Port;
  39. struct Ports;
  40. struct RtData
  41. {
  42. RtData(void);
  43. char *loc;
  44. size_t loc_size;
  45. void *obj;
  46. int matches;
  47. const Port *port;
  48. const char *message;
  49. virtual void replyArray(const char *path, const char *args,
  50. rtosc_arg_t *vals);
  51. virtual void reply(const char *path, const char *args, ...);
  52. virtual void reply(const char *msg);
  53. virtual void chain(const char *path, const char *args, ...);
  54. virtual void chain(const char *msg);
  55. virtual void chainArray(const char *path, const char *args,
  56. rtosc_arg_t *vals);
  57. virtual void broadcast(const char *path, const char *args, ...);
  58. virtual void broadcast(const char *msg);
  59. virtual void broadcastArray(const char *path, const char *args,
  60. rtosc_arg_t *vals);
  61. virtual void forward(const char *rational=NULL);
  62. };
  63. /**
  64. * Port in rtosc dispatching hierarchy
  65. */
  66. struct Port {
  67. const char *name; //< Pattern for messages to match
  68. const char *metadata;//< Statically accessable data about port
  69. const Ports *ports; //< Pointer to further ports
  70. std::function<void(msg_t, RtData&)> cb;//< Callback for matching functions
  71. class MetaIterator
  72. {
  73. public:
  74. MetaIterator(const char *str);
  75. //A bit odd to return yourself, but it seems to work for this
  76. //context
  77. const MetaIterator& operator*(void) const {return *this;}
  78. const MetaIterator* operator->(void) const {return this;}
  79. bool operator==(MetaIterator a) {return title == a.title;}
  80. bool operator!=(MetaIterator a) {return title != a.title;}
  81. MetaIterator& operator++(void);
  82. const char *title;
  83. const char *value;
  84. };
  85. class MetaContainer
  86. {
  87. public:
  88. MetaContainer(const char *str_);
  89. MetaIterator begin(void) const;
  90. MetaIterator end(void) const;
  91. MetaIterator find(const char *str) const;
  92. size_t length(void) const;
  93. const char *operator[](const char *str) const;
  94. const char *str_ptr;
  95. };
  96. MetaContainer meta(void) const
  97. {
  98. if(metadata && *metadata == ':')
  99. return MetaContainer(metadata+1);
  100. else
  101. return MetaContainer(metadata);
  102. }
  103. };
  104. /**
  105. * Ports - a dispatchable collection of Port entries
  106. *
  107. * This structure makes it somewhat easier to perform actions on collections of
  108. * port entries and it is responsible for the dispatching of OSC messages to
  109. * their respective ports.
  110. * That said, it is a very simple structure, which uses a stl container to store
  111. * all data in a simple dispatch table.
  112. * All methods post-initialization are RT safe (assuming callbacks are RT safe)
  113. */
  114. struct Ports
  115. {
  116. std::vector<Port> ports;
  117. std::function<void(msg_t, RtData&)> default_handler;
  118. typedef std::vector<Port>::const_iterator itr_t;
  119. /**Forwards to builtin container*/
  120. itr_t begin() const {return ports.begin();}
  121. /**Forwards to builtin container*/
  122. itr_t end() const {return ports.end();}
  123. /**Forwards to builtin container*/
  124. size_t size() const {return ports.size();}
  125. /**Forwards to builtin container*/
  126. const Port &operator[](unsigned i) const {return ports[i];}
  127. Ports(std::initializer_list<Port> l);
  128. ~Ports(void);
  129. Ports(const Ports&) = delete;
  130. /**
  131. * Dispatches message to all matching ports.
  132. * This uses simple pattern matching available in rtosc::match.
  133. *
  134. * @param m a valid OSC message
  135. * @param d The RtData object shall contain a path buffer (or null), the length of
  136. * the buffer, a pointer to data.
  137. */
  138. void dispatch(const char *m, RtData &d, bool base_dispatch=false) const;
  139. /**
  140. * Retrieve local port by name
  141. * TODO implement full matching
  142. */
  143. const Port *operator[](const char *name) const;
  144. /**
  145. * Find the best match for a given path
  146. *
  147. * @parameter path partial OSC path
  148. * @returns first path prefixed by the argument
  149. *
  150. * Example usage:
  151. * @code
  152. * Ports p = {{"foo",0,0,dummy_method},
  153. * {"flam",0,0,dummy_method},
  154. * {"bar",0,0,dummy_method}};
  155. * p.apropos("/b")->name;//bar
  156. * p.apropos("/f")->name;//foo
  157. * p.apropos("/fl")->name;//flam
  158. * p.apropos("/gg");//NULL
  159. * @endcode
  160. */
  161. const Port *apropos(const char *path) const;
  162. /**
  163. * Collapse path with parent path identifiers "/.."
  164. *
  165. * e.g. /foo/bar/../baz => /foo/baz
  166. */
  167. static char *collapsePath(char *p);
  168. protected:
  169. void refreshMagic(void);
  170. private:
  171. //Performance hacks
  172. class Port_Matcher *impl;
  173. unsigned elms;
  174. };
  175. struct ClonePort
  176. {
  177. const char *name;
  178. std::function<void(msg_t, RtData&)> cb;
  179. };
  180. struct ClonePorts:public Ports
  181. {
  182. ClonePorts(const Ports &p,
  183. std::initializer_list<ClonePort> c);
  184. };
  185. struct MergePorts:public Ports
  186. {
  187. MergePorts(std::initializer_list<const Ports*> c);
  188. };
  189. /*********************
  190. * Port walking code *
  191. *********************/
  192. //typedef std::function<void(const Port*,const char*)> port_walker_t;
  193. typedef void(*port_walker_t)(const Port*,const char*,void*);
  194. void walk_ports(const Ports *base,
  195. char *name_buffer,
  196. size_t buffer_size,
  197. void *data,
  198. port_walker_t walker);
  199. /*********************
  200. * Port Dumping code *
  201. *********************/
  202. struct OscDocFormatter
  203. {
  204. const Ports *p;
  205. std::string prog_name;
  206. std::string uri;
  207. std::string doc_origin;
  208. std::string author_first;
  209. std::string author_last;
  210. //TODO extend this some more
  211. };
  212. std::ostream &operator<<(std::ostream &o, OscDocFormatter &formatter);
  213. };
  214. #endif