1 /*
2   Copyright 2007-2017 David Robillard <d@drobilla.net>
3 
4   Permission to use, copy, modify, and/or distribute this software for any
5   purpose with or without fee is hereby granted, provided that the above
6   copyright notice and this permission notice appear in all copies.
7 
8   THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9   WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10   MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11   ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16 
17 #ifndef LILV_LILVMM_HPP
18 #define LILV_LILVMM_HPP
19 
20 #include "lilv/lilv.h"
21 #include "lv2/core/lv2.h"
22 
23 #include <cstdarg>
24 #include <cstdint>
25 
26 namespace Lilv {
27 
28 #if defined(__clang__)
29 #  pragma clang diagnostic push
30 #  pragma clang diagnostic ignored "-Wdeprecated-declarations"
31 #elif defined(__GNUC__) && __GNUC__ > 4
32 #  pragma GCC diagnostic push
33 #  pragma GCC diagnostic ignored "-Wdeprecated-declarations"
34 #endif
35 
36 struct Instance;
37 struct Node;
38 struct Nodes;
39 struct Plugin;
40 struct PluginClass;
41 struct PluginClasses;
42 struct Plugins;
43 struct Port;
44 struct ScalePoint;
45 struct ScalePoints;
46 struct UI;
47 struct UIs;
48 struct World;
49 
50 LILV_DEPRECATED
51 static inline const char*
uri_to_path(const char * uri)52 uri_to_path(const char* uri)
53 {
54   return lilv_uri_to_path(uri);
55 }
56 
57 #if defined(__clang__)
58 #  pragma clang diagnostic pop
59 #elif defined(__GNUC__) && __GNUC__ > 4
60 #  pragma GCC diagnostic pop
61 #endif
62 
63 #define LILV_WRAP0(RT, prefix, name) \
64   inline RT name() { return lilv_##prefix##_##name(me); }
65 
66 #define LILV_WRAP0_VOID(prefix, name) \
67   inline void name() { lilv_##prefix##_##name(me); }
68 
69 #define LILV_WRAP1(RT, prefix, name, T1, a1) \
70   inline RT name(T1 a1) { return lilv_##prefix##_##name(me, a1); }
71 
72 #define LILV_WRAP1_VOID(prefix, name, T1, a1) \
73   inline void name(T1 a1) { lilv_##prefix##_##name(me, a1); }
74 
75 #define LILV_WRAP2(RT, prefix, name, T1, a1, T2, a2) \
76   inline RT name(T1 a1, T2 a2) { return lilv_##prefix##_##name(me, a1, a2); }
77 
78 #define LILV_WRAP3(RT, prefix, name, T1, a1, T2, a2, T3, a3) \
79   inline RT name(T1 a1, T2 a2, T3 a3)                        \
80   {                                                          \
81     return lilv_##prefix##_##name(me, a1, a2, a3);           \
82   }
83 
84 #define LILV_WRAP2_VOID(prefix, name, T1, a1, T2, a2) \
85   inline void name(T1 a1, T2 a2) { lilv_##prefix##_##name(me, a1, a2); }
86 
87 #ifndef SWIG
88 #  define LILV_WRAP_CONVERSION(CT) \
89     inline operator CT*() const { return me; }
90 #else
91 #  define LILV_WRAP_CONVERSION(CT)
92 #endif
93 
94 struct Node {
NodeLilv::Node95   inline Node(const LilvNode* node)
96     : me(lilv_node_duplicate(node))
97   {}
98 
NodeLilv::Node99   inline Node(const Node& copy)
100     : me(lilv_node_duplicate(copy.me))
101   {}
102 
operator =Lilv::Node103   inline Node& operator=(const Node& rhs)
104   {
105     if (&rhs != this) {
106       lilv_node_free(me);
107       me = lilv_node_duplicate(rhs.me);
108     }
109     return *this;
110   }
111 
NodeLilv::Node112   inline Node(Node&& other) noexcept
113     : me(other.me)
114   {
115     other.me = nullptr;
116   }
117 
operator =Lilv::Node118   inline Node& operator=(Node&& rhs) noexcept
119   {
120     if (&rhs != this) {
121       me     = rhs.me;
122       rhs.me = nullptr;
123     }
124     return *this;
125   }
126 
~NodeLilv::Node127   inline ~Node() { lilv_node_free(me); }
128 
equalsLilv::Node129   inline bool equals(const Node& other) const
130   {
131     return lilv_node_equals(me, other.me);
132   }
133 
operator ==Lilv::Node134   inline bool operator==(const Node& other) const { return equals(other); }
135 
136   LILV_WRAP_CONVERSION(LilvNode);
137 
138   LILV_WRAP0(char*, node, get_turtle_token);
139   LILV_WRAP0(bool, node, is_uri);
140   LILV_WRAP0(const char*, node, as_uri);
141   LILV_WRAP0(bool, node, is_blank);
142   LILV_WRAP0(const char*, node, as_blank);
143   LILV_WRAP0(bool, node, is_literal);
144   LILV_WRAP0(bool, node, is_string);
145   LILV_WRAP0(const char*, node, as_string);
146   LILV_WRAP0(bool, node, is_float);
147   LILV_WRAP0(float, node, as_float);
148   LILV_WRAP0(bool, node, is_int);
149   LILV_WRAP0(int, node, as_int);
150   LILV_WRAP0(bool, node, is_bool);
151   LILV_WRAP0(bool, node, as_bool);
152 
153   LilvNode* me;
154 };
155 
156 struct ScalePoint {
ScalePointLilv::ScalePoint157   inline ScalePoint(const LilvScalePoint* c_obj)
158     : me(c_obj)
159   {}
160 
161   LILV_WRAP_CONVERSION(const LilvScalePoint);
162 
163   LILV_WRAP0(const LilvNode*, scale_point, get_label);
164   LILV_WRAP0(const LilvNode*, scale_point, get_value);
165 
166   const LilvScalePoint* me;
167 };
168 
169 struct PluginClass {
PluginClassLilv::PluginClass170   inline PluginClass(const LilvPluginClass* c_obj)
171     : me(c_obj)
172   {}
173 
174   LILV_WRAP_CONVERSION(const LilvPluginClass);
175 
176   LILV_WRAP0(Node, plugin_class, get_parent_uri);
177   LILV_WRAP0(Node, plugin_class, get_uri);
178   LILV_WRAP0(Node, plugin_class, get_label);
179   LILV_WRAP0(LilvPluginClasses*, plugin_class, get_children);
180 
181   const LilvPluginClass* me;
182 };
183 
184 #define LILV_WRAP_COLL(CT, ET, prefix)               \
185   inline CT(const Lilv##CT* c_obj)                   \
186     : me(c_obj)                                      \
187   {}                                                 \
188   LILV_WRAP_CONVERSION(const Lilv##CT);              \
189   LILV_WRAP0(unsigned, prefix, size);                \
190   LILV_WRAP1(ET, prefix, get, LilvIter*, i);         \
191   LILV_WRAP0(LilvIter*, prefix, begin);              \
192   LILV_WRAP1(LilvIter*, prefix, next, LilvIter*, i); \
193   LILV_WRAP1(bool, prefix, is_end, LilvIter*, i);    \
194   const Lilv##CT* me;
195 
196 struct PluginClasses {
197   LILV_WRAP_COLL(PluginClasses, PluginClass, plugin_classes);
198   LILV_WRAP1(PluginClass, plugin_classes, get_by_uri, const LilvNode*, uri);
199 };
200 
201 struct ScalePoints {
202   LILV_WRAP_COLL(ScalePoints, ScalePoint, scale_points);
203 };
204 
205 struct Nodes {
206   LILV_WRAP_COLL(Nodes, Node, nodes);
207   LILV_WRAP1(bool, nodes, contains, const Node&, node);
208   LILV_WRAP0(Node, nodes, get_first);
209 };
210 
211 struct UI {
UILilv::UI212   inline UI(const LilvUI* c_obj)
213     : me(c_obj)
214   {}
215 
216   LILV_WRAP_CONVERSION(const LilvUI);
217 
218   LILV_WRAP0(const LilvNode*, ui, get_uri);
219   LILV_WRAP0(const LilvNode*, ui, get_bundle_uri);
220   LILV_WRAP0(const LilvNode*, ui, get_binary_uri);
221   LILV_WRAP0(const LilvNodes*, ui, get_classes);
222   /*LILV_WRAP3(bool, ui, is_supported,
223              LilvUISupportedFunc, supported_func,
224              const LilvNode*,     container_type,
225              const LilvNode**,    ui_type);*/
226   LILV_WRAP1(bool, ui, is_a, const LilvNode*, class_uri);
227 
228   const LilvUI* me;
229 };
230 
231 struct UIs {
232   LILV_WRAP_COLL(UIs, UI, uis);
233 };
234 
235 struct Port {
PortLilv::Port236   inline Port(const LilvPlugin* p, const LilvPort* c_obj)
237     : parent(p)
238     , me(c_obj)
239   {}
240 
241   LILV_WRAP_CONVERSION(const LilvPort);
242 
243 #define LILV_PORT_WRAP0(RT, name) \
244   inline RT name() { return lilv_port_##name(parent, me); }
245 
246 #define LILV_PORT_WRAP1(RT, name, T1, a1) \
247   inline RT name(T1 a1) { return lilv_port_##name(parent, me, a1); }
248 
249   LILV_PORT_WRAP1(LilvNodes*, get_value, LilvNode*, predicate);
250   LILV_PORT_WRAP0(LilvNodes*, get_properties)
251   LILV_PORT_WRAP1(bool, has_property, LilvNode*, property_uri);
252   LILV_PORT_WRAP1(bool, supports_event, LilvNode*, event_uri);
253   LILV_PORT_WRAP0(const LilvNode*, get_symbol);
254   LILV_PORT_WRAP0(LilvNode*, get_name);
255   LILV_PORT_WRAP0(const LilvNodes*, get_classes);
256   LILV_PORT_WRAP1(bool, is_a, LilvNode*, port_class);
257   LILV_PORT_WRAP0(LilvScalePoints*, get_scale_points);
258 
259   // TODO: get_range (output parameters)
260 
261   const LilvPlugin* parent;
262   const LilvPort*   me;
263 };
264 
265 struct Plugin {
PluginLilv::Plugin266   inline Plugin(const LilvPlugin* c_obj)
267     : me(c_obj)
268   {}
269 
270   LILV_WRAP_CONVERSION(const LilvPlugin);
271 
272   LILV_WRAP0(bool, plugin, verify);
273   LILV_WRAP0(Node, plugin, get_uri);
274   LILV_WRAP0(Node, plugin, get_bundle_uri);
275   LILV_WRAP0(Nodes, plugin, get_data_uris);
276   LILV_WRAP0(Node, plugin, get_library_uri);
277   LILV_WRAP0(Node, plugin, get_name);
278   LILV_WRAP0(PluginClass, plugin, get_class);
279   LILV_WRAP1(Nodes, plugin, get_value, const Node&, pred);
280   LILV_WRAP1(bool, plugin, has_feature, const Node&, feature_uri);
281   LILV_WRAP0(Nodes, plugin, get_supported_features);
282   LILV_WRAP0(Nodes, plugin, get_required_features);
283   LILV_WRAP0(Nodes, plugin, get_optional_features);
284   LILV_WRAP0(unsigned, plugin, get_num_ports);
285   LILV_WRAP0(bool, plugin, has_latency);
286   LILV_WRAP0(unsigned, plugin, get_latency_port_index);
287   LILV_WRAP0(Node, plugin, get_author_name);
288   LILV_WRAP0(Node, plugin, get_author_email);
289   LILV_WRAP0(Node, plugin, get_author_homepage);
290   LILV_WRAP0(bool, plugin, is_replaced);
291   LILV_WRAP0(Nodes, plugin, get_extension_data);
292   LILV_WRAP0(UIs, plugin, get_uis);
293   LILV_WRAP1(Nodes, plugin, get_related, const Node&, type);
294 
get_port_by_indexLilv::Plugin295   inline Port get_port_by_index(unsigned index) const
296   {
297     return Port(me, lilv_plugin_get_port_by_index(me, index));
298   }
299 
get_port_by_symbolLilv::Plugin300   inline Port get_port_by_symbol(LilvNode* symbol) const
301   {
302     return Port(me, lilv_plugin_get_port_by_symbol(me, symbol));
303   }
304 
get_port_ranges_floatLilv::Plugin305   inline void get_port_ranges_float(float* min_values,
306                                     float* max_values,
307                                     float* def_values) const
308   {
309     return lilv_plugin_get_port_ranges_float(
310       me, min_values, max_values, def_values);
311   }
312 
get_num_ports_of_classLilv::Plugin313   inline unsigned get_num_ports_of_class(LilvNode* class_1, ...) const
314   {
315     va_list args;
316     va_start(args, class_1);
317 
318     const uint32_t count =
319       lilv_plugin_get_num_ports_of_class_va(me, class_1, args);
320 
321     va_end(args);
322     return count;
323   }
324 
325   const LilvPlugin* me;
326 };
327 
328 struct Plugins {
329   LILV_WRAP_COLL(Plugins, Plugin, plugins);
330   LILV_WRAP1(Plugin, plugins, get_by_uri, const LilvNode*, uri);
331 };
332 
333 struct Instance {
InstanceLilv::Instance334   inline Instance(LilvInstance* instance)
335     : me(instance)
336   {}
337 
338   LILV_DEPRECATED
InstanceLilv::Instance339   inline Instance(Plugin plugin, double sample_rate)
340   {
341     me = lilv_plugin_instantiate(plugin, sample_rate, nullptr);
342   }
343 
InstanceLilv::Instance344   LILV_DEPRECATED inline Instance(Plugin              plugin,
345                                   double              sample_rate,
346                                   LV2_Feature* const* features)
347   {
348     me = lilv_plugin_instantiate(plugin, sample_rate, features);
349   }
350 
createLilv::Instance351   static inline Instance* create(Plugin              plugin,
352                                  double              sample_rate,
353                                  LV2_Feature* const* features)
354   {
355     LilvInstance* me = lilv_plugin_instantiate(plugin, sample_rate, features);
356 
357     return me ? new Instance(me) : nullptr;
358   }
359 
360   LILV_WRAP_CONVERSION(LilvInstance);
361 
362   LILV_WRAP2_VOID(instance,
363                   connect_port,
364                   unsigned,
365                   port_index,
366                   void*,
367                   data_location);
368 
369   LILV_WRAP0_VOID(instance, activate);
370   LILV_WRAP1_VOID(instance, run, unsigned, sample_count);
371   LILV_WRAP0_VOID(instance, deactivate);
372 
get_extension_dataLilv::Instance373   inline const void* get_extension_data(const char* uri) const
374   {
375     return lilv_instance_get_extension_data(me, uri);
376   }
377 
get_descriptorLilv::Instance378   inline const LV2_Descriptor* get_descriptor() const
379   {
380     return lilv_instance_get_descriptor(me);
381   }
382 
get_handleLilv::Instance383   inline LV2_Handle get_handle() const { return lilv_instance_get_handle(me); }
384 
385   LilvInstance* me;
386 };
387 
388 struct World {
WorldLilv::World389   inline World()
390     : me(lilv_world_new())
391   {}
392 
~WorldLilv::World393   inline ~World() { lilv_world_free(me); }
394 
395   World(const World&) = delete;
396   World& operator=(const World&) = delete;
397 
398   World(World&&) = delete;
399   World& operator=(World&&) = delete;
400 
new_uriLilv::World401   inline LilvNode* new_uri(const char* uri) const
402   {
403     return lilv_new_uri(me, uri);
404   }
405 
new_stringLilv::World406   inline LilvNode* new_string(const char* str) const
407   {
408     return lilv_new_string(me, str);
409   }
410 
new_intLilv::World411   inline LilvNode* new_int(int val) const { return lilv_new_int(me, val); }
412 
new_floatLilv::World413   inline LilvNode* new_float(float val) const
414   {
415     return lilv_new_float(me, val);
416   }
417 
new_boolLilv::World418   inline LilvNode* new_bool(bool val) const { return lilv_new_bool(me, val); }
419 
find_nodesLilv::World420   inline Nodes find_nodes(const LilvNode* subject,
421                           const LilvNode* predicate,
422                           const LilvNode* object) const
423   {
424     return lilv_world_find_nodes(me, subject, predicate, object);
425   }
426 
427   LILV_WRAP2_VOID(world, set_option, const char*, uri, LilvNode*, value);
428   LILV_WRAP0_VOID(world, load_all);
429   LILV_WRAP1_VOID(world, load_bundle, LilvNode*, bundle_uri);
430   LILV_WRAP0(const LilvPluginClass*, world, get_plugin_class);
431   LILV_WRAP0(const LilvPluginClasses*, world, get_plugin_classes);
432   LILV_WRAP0(Plugins, world, get_all_plugins);
433   LILV_WRAP1(int, world, load_resource, const LilvNode*, resource);
434 
435   LilvWorld* me;
436 };
437 
438 } /* namespace Lilv */
439 
440 #endif /* LILV_LILVMM_HPP */
441