1 /*
2   Copyright 2007-2019 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_INTERNAL_H
18 #define LILV_INTERNAL_H
19 
20 #ifdef __cplusplus
21 extern "C" {
22 #endif
23 
24 #include "lilv_config.h" // IWYU pragma: keep
25 
26 #include "lilv/lilv.h"
27 #include "lv2/core/lv2.h"
28 #include "serd/serd.h"
29 #include "sord/sord.h"
30 #include "zix/tree.h"
31 
32 #include <stdbool.h>
33 #include <stdint.h>
34 #include <stdio.h>
35 
36 #ifdef _WIN32
37 #  include <direct.h>
38 #  include <stdio.h>
39 #  include <windows.h>
40 #  define dlopen(path, flags) LoadLibrary(path)
41 #  define dlclose(lib) FreeLibrary((HMODULE)lib)
42 #  ifdef _MSC_VER
43 #    define __func__ __FUNCTION__
44 #    ifndef snprintf
45 #      define snprintf _snprintf
46 #    endif
47 #  endif
48 #  ifndef INFINITY
49 #    define INFINITY DBL_MAX + DBL_MAX
50 #  endif
51 #  ifndef NAN
52 #    define NAN INFINITY - INFINITY
53 #  endif
54 static inline const char*
dlerror(void)55 dlerror(void)
56 {
57   return "Unknown error";
58 }
59 #else
60 #  include <dlfcn.h>
61 #endif
62 
63 #ifdef LILV_DYN_MANIFEST
64 #  include "lv2/dynmanifest/dynmanifest.h"
65 #endif
66 
67 /*
68  *
69  * Types
70  *
71  */
72 
73 typedef void LilvCollection;
74 
75 struct LilvPortImpl {
76   LilvNode*  node;    ///< RDF node
77   uint32_t   index;   ///< lv2:index
78   LilvNode*  symbol;  ///< lv2:symbol
79   LilvNodes* classes; ///< rdf:type
80 };
81 
82 typedef struct LilvSpecImpl {
83   SordNode*            spec;
84   SordNode*            bundle;
85   LilvNodes*           data_uris;
86   struct LilvSpecImpl* next;
87 } LilvSpec;
88 
89 /**
90    Header of an LilvPlugin, LilvPluginClass, or LilvUI.
91    Any of these structs may be safely casted to LilvHeader, which is used to
92    implement collections using the same comparator.
93 */
94 struct LilvHeader {
95   LilvWorld* world;
96   LilvNode*  uri;
97 };
98 
99 #ifdef LILV_DYN_MANIFEST
100 typedef struct {
101   LilvNode*               bundle;
102   void*                   lib;
103   LV2_Dyn_Manifest_Handle handle;
104   uint32_t                refs;
105 } LilvDynManifest;
106 #endif
107 
108 typedef struct {
109   LilvWorld*                world;
110   LilvNode*                 uri;
111   char*                     bundle_path;
112   void*                     lib;
113   LV2_Descriptor_Function   lv2_descriptor;
114   const LV2_Lib_Descriptor* desc;
115   uint32_t                  refs;
116 } LilvLib;
117 
118 struct LilvPluginImpl {
119   LilvWorld* world;
120   LilvNode*  plugin_uri;
121   LilvNode*  bundle_uri; ///< Bundle plugin was loaded from
122   LilvNode*  binary_uri; ///< lv2:binary
123 #ifdef LILV_DYN_MANIFEST
124   LilvDynManifest* dynmanifest;
125 #endif
126   const LilvPluginClass* plugin_class;
127   LilvNodes*             data_uris; ///< rdfs::seeAlso
128   LilvPort**             ports;
129   uint32_t               num_ports;
130   bool                   loaded;
131   bool                   parse_errors;
132   bool                   replaced;
133 };
134 
135 struct LilvPluginClassImpl {
136   LilvWorld* world;
137   LilvNode*  uri;
138   LilvNode*  parent_uri;
139   LilvNode*  label;
140 };
141 
142 struct LilvInstancePimpl {
143   LilvWorld* world;
144   LilvLib*   lib;
145 };
146 
147 typedef struct {
148   bool  dyn_manifest;
149   bool  filter_language;
150   char* lv2_path;
151 } LilvOptions;
152 
153 struct LilvWorldImpl {
154   SordWorld*         world;
155   SordModel*         model;
156   SerdReader*        reader;
157   unsigned           n_read_files;
158   LilvPluginClass*   lv2_plugin_class;
159   LilvPluginClasses* plugin_classes;
160   LilvSpec*          specs;
161   LilvPlugins*       plugins;
162   LilvPlugins*       zombies;
163   LilvNodes*         loaded_files;
164   ZixTree*           libs;
165   struct {
166     SordNode* dc_replaces;
167     SordNode* dman_DynManifest;
168     SordNode* doap_name;
169     SordNode* lv2_Plugin;
170     SordNode* lv2_Specification;
171     SordNode* lv2_appliesTo;
172     SordNode* lv2_binary;
173     SordNode* lv2_default;
174     SordNode* lv2_designation;
175     SordNode* lv2_extensionData;
176     SordNode* lv2_index;
177     SordNode* lv2_latency;
178     SordNode* lv2_maximum;
179     SordNode* lv2_microVersion;
180     SordNode* lv2_minimum;
181     SordNode* lv2_minorVersion;
182     SordNode* lv2_name;
183     SordNode* lv2_optionalFeature;
184     SordNode* lv2_port;
185     SordNode* lv2_portProperty;
186     SordNode* lv2_reportsLatency;
187     SordNode* lv2_requiredFeature;
188     SordNode* lv2_symbol;
189     SordNode* lv2_prototype;
190     SordNode* owl_Ontology;
191     SordNode* pset_value;
192     SordNode* rdf_a;
193     SordNode* rdf_value;
194     SordNode* rdfs_Class;
195     SordNode* rdfs_label;
196     SordNode* rdfs_seeAlso;
197     SordNode* rdfs_subClassOf;
198     SordNode* xsd_base64Binary;
199     SordNode* xsd_boolean;
200     SordNode* xsd_decimal;
201     SordNode* xsd_double;
202     SordNode* xsd_integer;
203     SordNode* null_uri;
204   } uris;
205   LilvOptions opt;
206 };
207 
208 typedef enum {
209   LILV_VALUE_URI,
210   LILV_VALUE_STRING,
211   LILV_VALUE_INT,
212   LILV_VALUE_FLOAT,
213   LILV_VALUE_BOOL,
214   LILV_VALUE_BLANK,
215   LILV_VALUE_BLOB
216 } LilvNodeType;
217 
218 struct LilvNodeImpl {
219   LilvWorld*   world;
220   SordNode*    node;
221   LilvNodeType type;
222   union {
223     int   int_val;
224     float float_val;
225     bool  bool_val;
226   } val;
227 };
228 
229 struct LilvScalePointImpl {
230   LilvNode* value;
231   LilvNode* label;
232 };
233 
234 struct LilvUIImpl {
235   LilvWorld* world;
236   LilvNode*  uri;
237   LilvNode*  bundle_uri;
238   LilvNode*  binary_uri;
239   LilvNodes* classes;
240 };
241 
242 typedef struct LilvVersion {
243   int minor;
244   int micro;
245 } LilvVersion;
246 
247 /*
248  *
249  * Functions
250  *
251  */
252 
253 LilvPort*
254 lilv_port_new(LilvWorld*      world,
255               const SordNode* node,
256               uint32_t        index,
257               const char*     symbol);
258 void
259 lilv_port_free(const LilvPlugin* plugin, LilvPort* port);
260 
261 LilvPlugin*
262 lilv_plugin_new(LilvWorld* world, LilvNode* uri, LilvNode* bundle_uri);
263 
264 void
265 lilv_plugin_clear(LilvPlugin* plugin, LilvNode* bundle_uri);
266 
267 void
268 lilv_plugin_load_if_necessary(const LilvPlugin* plugin);
269 
270 void
271 lilv_plugin_free(LilvPlugin* plugin);
272 
273 LilvNode*
274 lilv_plugin_get_unique(const LilvPlugin* plugin,
275                        const SordNode*   subject,
276                        const SordNode*   predicate);
277 
278 void
279 lilv_collection_free(LilvCollection* collection);
280 
281 unsigned
282 lilv_collection_size(const LilvCollection* collection);
283 
284 LilvIter*
285 lilv_collection_begin(const LilvCollection* collection);
286 
287 void*
288 lilv_collection_get(const LilvCollection* collection, const LilvIter* i);
289 
290 LilvPluginClass*
291 lilv_plugin_class_new(LilvWorld*      world,
292                       const SordNode* parent_node,
293                       const SordNode* uri,
294                       const char*     label);
295 
296 void
297 lilv_plugin_class_free(LilvPluginClass* plugin_class);
298 
299 LilvLib*
300 lilv_lib_open(LilvWorld*                world,
301               const LilvNode*           uri,
302               const char*               bundle_path,
303               const LV2_Feature* const* features);
304 
305 const LV2_Descriptor*
306 lilv_lib_get_plugin(LilvLib* lib, uint32_t index);
307 
308 void
309 lilv_lib_close(LilvLib* lib);
310 
311 LilvNodes*
312 lilv_nodes_new(void);
313 
314 LilvPlugins*
315 lilv_plugins_new(void);
316 
317 LilvScalePoints*
318 lilv_scale_points_new(void);
319 
320 LilvPluginClasses*
321 lilv_plugin_classes_new(void);
322 
323 LilvUIs*
324 lilv_uis_new(void);
325 
326 LilvNode*
327 lilv_world_get_manifest_uri(LilvWorld* world, const LilvNode* bundle_uri);
328 
329 const uint8_t*
330 lilv_world_blank_node_prefix(LilvWorld* world);
331 
332 SerdStatus
333 lilv_world_load_file(LilvWorld* world, SerdReader* reader, const LilvNode* uri);
334 
335 SerdStatus
336 lilv_world_load_graph(LilvWorld* world, SordNode* graph, const LilvNode* uri);
337 
338 LilvUI*
339 lilv_ui_new(LilvWorld* world,
340             LilvNode*  uri,
341             LilvNode*  type_uri,
342             LilvNode*  binary_uri);
343 
344 void
345 lilv_ui_free(LilvUI* ui);
346 
347 LilvNode*
348 lilv_node_new(LilvWorld* world, LilvNodeType type, const char* str);
349 
350 LilvNode*
351 lilv_node_new_from_node(LilvWorld* world, const SordNode* node);
352 
353 int
354 lilv_header_compare_by_uri(const void* a, const void* b, void* user_data);
355 
356 int
357 lilv_lib_compare(const void* a, const void* b, void* user_data);
358 
359 int
360 lilv_ptr_cmp(const void* a, const void* b, void* user_data);
361 
362 int
363 lilv_resource_node_cmp(const void* a, const void* b, void* user_data);
364 
365 static inline int
lilv_version_cmp(const LilvVersion * a,const LilvVersion * b)366 lilv_version_cmp(const LilvVersion* a, const LilvVersion* b)
367 {
368   if (a->minor == b->minor && a->micro == b->micro) {
369     return 0;
370   }
371 
372   if ((a->minor < b->minor) || (a->minor == b->minor && a->micro < b->micro)) {
373     return -1;
374   }
375 
376   return 1;
377 }
378 
379 struct LilvHeader*
380 lilv_collection_get_by_uri(const ZixTree* seq, const LilvNode* uri);
381 
382 LilvScalePoint*
383 lilv_scale_point_new(LilvNode* value, LilvNode* label);
384 
385 void
386 lilv_scale_point_free(LilvScalePoint* point);
387 
388 SordIter*
389 lilv_world_query_internal(LilvWorld*      world,
390                           const SordNode* subject,
391                           const SordNode* predicate,
392                           const SordNode* object);
393 
394 bool
395 lilv_world_ask_internal(LilvWorld*      world,
396                         const SordNode* subject,
397                         const SordNode* predicate,
398                         const SordNode* object);
399 
400 LilvNodes*
401 lilv_world_find_nodes_internal(LilvWorld*      world,
402                                const SordNode* subject,
403                                const SordNode* predicate,
404                                const SordNode* object);
405 
406 SordModel*
407 lilv_world_filter_model(LilvWorld*      world,
408                         SordModel*      model,
409                         const SordNode* subject,
410                         const SordNode* predicate,
411                         const SordNode* object,
412                         const SordNode* graph);
413 
414 #define FOREACH_MATCH(iter) for (; !sord_iter_end(iter); sord_iter_next(iter))
415 
416 LilvNodes*
417 lilv_nodes_from_stream_objects(LilvWorld*    world,
418                                SordIter*     stream,
419                                SordQuadIndex field);
420 
421 char*
422 lilv_strjoin(const char* first, ...);
423 
424 char*
425 lilv_strdup(const char* str);
426 
427 char*
428 lilv_get_lang(void);
429 
430 char*
431 lilv_expand(const char* path);
432 
433 char*
434 lilv_get_latest_copy(const char* path, const char* copy_path);
435 
436 char*
437 lilv_find_free_path(const char* in_path,
438                     bool (*exists)(const char*, const void*),
439                     const void* user_data);
440 
441 typedef void (*LilvVoidFunc)(void);
442 
443 /** dlsym wrapper to return a function pointer (without annoying warning) */
444 static inline LilvVoidFunc
lilv_dlfunc(void * handle,const char * symbol)445 lilv_dlfunc(void* handle, const char* symbol)
446 {
447 #ifdef _WIN32
448   return (LilvVoidFunc)GetProcAddress((HMODULE)handle, symbol);
449 #else
450   typedef LilvVoidFunc (*VoidFuncGetter)(void*, const char*);
451   VoidFuncGetter dlfunc = (VoidFuncGetter)dlsym;
452   return dlfunc(handle, symbol);
453 #endif
454 }
455 
456 #ifdef LILV_DYN_MANIFEST
457 static const LV2_Feature* const dman_features = {NULL};
458 
459 void
460 lilv_dynmanifest_free(LilvDynManifest* dynmanifest);
461 #endif
462 
463 #define LILV_ERROR(str) fprintf(stderr, "%s(): error: " str, __func__)
464 #define LILV_ERRORF(fmt, ...) \
465   fprintf(stderr, "%s(): error: " fmt, __func__, __VA_ARGS__)
466 #define LILV_WARN(str) fprintf(stderr, "%s(): warning: " str, __func__)
467 #define LILV_WARNF(fmt, ...) \
468   fprintf(stderr, "%s(): warning: " fmt, __func__, __VA_ARGS__)
469 #define LILV_NOTE(str) fprintf(stderr, "%s(): note: " str, __func__)
470 #define LILV_NOTEF(fmt, ...) \
471   fprintf(stderr, "%s(): note: " fmt, __func__, __VA_ARGS__)
472 
473 #ifdef __cplusplus
474 }
475 #endif
476 
477 #endif /* LILV_INTERNAL_H */
478