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.

1140 lines
29KB

  1. /*
  2. Copyright 2007-2011 David Robillard <http://drobilla.net>
  3. Permission to use, copy, modify, and/or distribute this software for any
  4. purpose with or without fee is hereby granted, provided that the above
  5. copyright notice and this permission notice appear in all copies.
  6. THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  7. WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  8. MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  9. ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  10. WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  11. ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  12. OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  13. */
  14. #define __STDC_LIMIT_MACROS
  15. #include <assert.h>
  16. #include <math.h>
  17. #include <stdarg.h>
  18. #include <stdint.h>
  19. #include <stdio.h>
  20. #include <stdlib.h>
  21. #include <string.h>
  22. #include "lilv_config.h"
  23. #include "lilv_internal.h"
  24. #include "lv2/ui.h"
  25. #define NS_DOAP (const uint8_t*)"http://usefulinc.com/ns/doap#"
  26. #define NS_FOAF (const uint8_t*)"http://xmlns.com/foaf/0.1/"
  27. /** Ownership of @a uri is taken */
  28. LilvPlugin*
  29. lilv_plugin_new(LilvWorld* world, LilvNode* uri, LilvNode* bundle_uri)
  30. {
  31. assert(bundle_uri);
  32. LilvPlugin* plugin = (LilvPlugin*)malloc(sizeof(LilvPlugin));
  33. plugin->world = world;
  34. plugin->plugin_uri = uri;
  35. plugin->bundle_uri = bundle_uri;
  36. plugin->binary_uri = NULL;
  37. #ifdef LILV_DYN_MANIFEST
  38. plugin->dynmanifest = NULL;
  39. #endif
  40. plugin->plugin_class = NULL;
  41. plugin->data_uris = lilv_nodes_new();
  42. plugin->ports = NULL;
  43. plugin->num_ports = 0;
  44. plugin->loaded = false;
  45. plugin->replaced = false;
  46. return plugin;
  47. }
  48. static void
  49. lilv_plugin_free_ports(LilvPlugin* p)
  50. {
  51. if (p->ports) {
  52. for (uint32_t i = 0; i < p->num_ports; ++i) {
  53. lilv_port_free(p, p->ports[i]);
  54. }
  55. free(p->ports);
  56. p->num_ports = 0;
  57. p->ports = NULL;
  58. }
  59. }
  60. void
  61. lilv_plugin_free(LilvPlugin* p)
  62. {
  63. #ifdef LILV_DYN_MANIFEST
  64. if (p->dynmanifest && --p->dynmanifest->refs == 0) {
  65. typedef int (*CloseFunc)(LV2_Dyn_Manifest_Handle);
  66. CloseFunc close_func = (CloseFunc)lilv_dlfunc(p->dynmanifest->lib,
  67. "lv2_dyn_manifest_close");
  68. if (close_func) {
  69. close_func(p->dynmanifest->handle);
  70. }
  71. dlclose(p->dynmanifest->lib);
  72. lilv_node_free(p->dynmanifest->bundle);
  73. free(p->dynmanifest);
  74. }
  75. #endif
  76. lilv_node_free(p->plugin_uri);
  77. p->plugin_uri = NULL;
  78. lilv_node_free(p->bundle_uri);
  79. p->bundle_uri = NULL;
  80. lilv_node_free(p->binary_uri);
  81. p->binary_uri = NULL;
  82. lilv_plugin_free_ports(p);
  83. lilv_nodes_free(p->data_uris);
  84. p->data_uris = NULL;
  85. free(p);
  86. }
  87. static LilvNode*
  88. lilv_plugin_get_one(const LilvPlugin* p,
  89. const SordNode* subject,
  90. const SordNode* predicate)
  91. {
  92. LilvNode* ret = NULL;
  93. SordIter* stream = lilv_world_query_internal(
  94. p->world, subject, predicate, NULL);
  95. if (!sord_iter_end(stream)) {
  96. ret = lilv_node_new_from_node(p->world, sord_iter_get_node(stream, SORD_OBJECT));
  97. }
  98. sord_iter_free(stream);
  99. return ret;
  100. }
  101. LilvNode*
  102. lilv_plugin_get_unique(const LilvPlugin* p,
  103. const SordNode* subject,
  104. const SordNode* predicate)
  105. {
  106. LilvNode* ret = lilv_plugin_get_one(p, subject, predicate);
  107. if (!ret) {
  108. LILV_ERRORF("Multiple values found for (%s %s ...) property\n",
  109. sord_node_get_string(subject),
  110. sord_node_get_string(predicate));
  111. }
  112. return ret;
  113. }
  114. static void
  115. lilv_plugin_load(LilvPlugin* p)
  116. {
  117. SordNode* bundle_uri_node = p->bundle_uri->node;
  118. const SerdNode* bundle_uri_snode = sord_node_to_serd_node(bundle_uri_node);
  119. SerdEnv* env = serd_env_new(bundle_uri_snode);
  120. SerdReader* reader = sord_new_reader(p->world->model, env, SERD_TURTLE,
  121. bundle_uri_node);
  122. SordIter* prototypes = sord_search(p->world->model,
  123. p->plugin_uri->node,
  124. p->world->uris.lv2_prototype,
  125. NULL, NULL);
  126. FOREACH_MATCH(prototypes) {
  127. const SordNode* t = sord_iter_get_node(prototypes, SORD_OBJECT);
  128. LilvNode* prototype = lilv_node_new_from_node(p->world, t);
  129. lilv_world_load_resource(p->world, prototype);
  130. SordIter* statements = sord_search(
  131. p->world->model, prototype->node, NULL, NULL, NULL);
  132. FOREACH_MATCH(statements) {
  133. SordQuad quad;
  134. sord_iter_get(statements, quad);
  135. quad[0] = p->plugin_uri->node;
  136. sord_add(p->world->model, quad);
  137. }
  138. lilv_node_free(prototype);
  139. }
  140. // Parse all the plugin's data files into RDF model
  141. LILV_FOREACH(nodes, i, p->data_uris) {
  142. const LilvNode* data_uri_val = lilv_nodes_get(p->data_uris, i);
  143. const SordNode* data_uri_node = data_uri_val->node;
  144. const char* data_uri_str = lilv_node_as_uri(data_uri_val);
  145. serd_env_set_base_uri(env, sord_node_to_serd_node(data_uri_node));
  146. serd_reader_add_blank_prefix(reader,
  147. lilv_world_blank_node_prefix(p->world));
  148. serd_reader_read_file(reader, (const uint8_t*)data_uri_str);
  149. }
  150. #ifdef LILV_DYN_MANIFEST
  151. typedef void* LV2_Dyn_Manifest_Handle;
  152. // Load and parse dynamic manifest data, if this is a library
  153. if (p->dynmanifest) {
  154. typedef int (*GetDataFunc)(LV2_Dyn_Manifest_Handle handle,
  155. FILE* fp,
  156. const char* uri);
  157. GetDataFunc get_data_func = (GetDataFunc)lilv_dlfunc(
  158. p->dynmanifest->lib, "lv2_dyn_manifest_get_data");
  159. if (get_data_func) {
  160. const SordNode* bundle = p->dynmanifest->bundle->node;
  161. serd_env_set_base_uri(env, sord_node_to_serd_node(bundle));
  162. FILE* fd = tmpfile();
  163. get_data_func(p->dynmanifest->handle, fd,
  164. lilv_node_as_string(p->plugin_uri));
  165. rewind(fd);
  166. serd_reader_add_blank_prefix(
  167. reader, lilv_world_blank_node_prefix(p->world));
  168. serd_reader_read_file_handle(
  169. reader, fd, (const uint8_t*)"(dyn-manifest)");
  170. fclose(fd);
  171. }
  172. }
  173. #endif
  174. serd_reader_free(reader);
  175. serd_env_free(env);
  176. p->loaded = true;
  177. }
  178. static bool
  179. is_symbol(const char* str)
  180. {
  181. const size_t len = strlen(str);
  182. for (size_t i = 0; i < len; ++i) {
  183. if (!((str[i] >= 'a' && str[i] <= 'z')
  184. || (str[i] >= 'A' && str[i] <= 'Z')
  185. || (i > 0 && str[i] >= '0' && str[i] <= '9')
  186. || str[i] == '_')) {
  187. return false;
  188. }
  189. }
  190. return true;
  191. }
  192. static void
  193. lilv_plugin_load_ports_if_necessary(const LilvPlugin* const_p)
  194. {
  195. LilvPlugin* p = (LilvPlugin*)const_p;
  196. if (!p->loaded)
  197. lilv_plugin_load(p);
  198. if (!p->ports) {
  199. p->ports = (LilvPort**)malloc(sizeof(LilvPort*));
  200. p->ports[0] = NULL;
  201. SordIter* ports = lilv_world_query_internal(
  202. p->world,
  203. p->plugin_uri->node,
  204. p->world->uris.lv2_port,
  205. NULL);
  206. FOREACH_MATCH(ports) {
  207. const SordNode* port = sord_iter_get_node(ports, SORD_OBJECT);
  208. LilvNode* index = lilv_plugin_get_unique(
  209. p, port, p->world->uris.lv2_index);
  210. LilvNode* symbol = lilv_plugin_get_unique(
  211. p, port, p->world->uris.lv2_symbol);
  212. bool error = false;
  213. if (!lilv_node_is_string(symbol) ||
  214. !is_symbol((const char*)sord_node_get_string(symbol->node))) {
  215. LILV_ERRORF("Plugin <%s> port symbol `%s' is invalid\n",
  216. lilv_node_as_uri(p->plugin_uri),
  217. lilv_node_as_string(symbol));
  218. error = true;
  219. goto done;
  220. }
  221. if (!lilv_node_is_int(index)) {
  222. LILV_ERRORF("Plugin <%s> port index is not an integer\n",
  223. lilv_node_as_uri(p->plugin_uri));
  224. error = true;
  225. goto done;
  226. }
  227. uint32_t this_index = lilv_node_as_int(index);
  228. LilvPort* this_port = NULL;
  229. if (p->num_ports > this_index) {
  230. this_port = p->ports[this_index];
  231. } else {
  232. p->ports = (LilvPort**)realloc(
  233. p->ports, (this_index + 1) * sizeof(LilvPort*));
  234. memset(p->ports + p->num_ports, '\0',
  235. (this_index - p->num_ports) * sizeof(LilvPort*));
  236. p->num_ports = this_index + 1;
  237. }
  238. // Havn't seen this port yet, add it to array
  239. if (!this_port) {
  240. this_port = lilv_port_new(p->world,
  241. port,
  242. this_index,
  243. lilv_node_as_string(symbol));
  244. p->ports[this_index] = this_port;
  245. }
  246. SordIter* types = lilv_world_query_internal(
  247. p->world, port, p->world->uris.rdf_a, NULL);
  248. FOREACH_MATCH(types) {
  249. const SordNode* type = sord_iter_get_node(types, SORD_OBJECT);
  250. if (sord_node_get_type(type) == SORD_URI) {
  251. zix_tree_insert(
  252. (ZixTree*)this_port->classes,
  253. lilv_node_new_from_node(p->world, type), NULL);
  254. } else {
  255. LILV_WARNF("Plugin <%s> port type is not a URI\n",
  256. lilv_node_as_uri(p->plugin_uri));
  257. }
  258. }
  259. sord_iter_free(types);
  260. done:
  261. lilv_node_free(symbol);
  262. lilv_node_free(index);
  263. if (error) { // Invalid plugin
  264. lilv_plugin_free_ports(p);
  265. break;
  266. }
  267. }
  268. sord_iter_free(ports);
  269. // Check sanity
  270. for (uint32_t i = 0; i < p->num_ports; ++i) {
  271. if (!p->ports[i]) {
  272. LILV_ERRORF("Plugin <%s> is missing port %d/%d\n",
  273. lilv_node_as_uri(p->plugin_uri), i, p->num_ports);
  274. lilv_plugin_free_ports(p);
  275. break;
  276. }
  277. }
  278. }
  279. }
  280. void
  281. lilv_plugin_load_if_necessary(const LilvPlugin* p)
  282. {
  283. if (!p->loaded)
  284. lilv_plugin_load((LilvPlugin*)p);
  285. }
  286. LILV_API
  287. const LilvNode*
  288. lilv_plugin_get_uri(const LilvPlugin* p)
  289. {
  290. assert(p);
  291. assert(p->plugin_uri);
  292. return p->plugin_uri;
  293. }
  294. LILV_API
  295. const LilvNode*
  296. lilv_plugin_get_bundle_uri(const LilvPlugin* p)
  297. {
  298. assert(p);
  299. assert(p->bundle_uri);
  300. return p->bundle_uri;
  301. }
  302. LILV_API
  303. const LilvNode*
  304. lilv_plugin_get_library_uri(const LilvPlugin* const_p)
  305. {
  306. LilvPlugin* p = (LilvPlugin*)const_p;
  307. lilv_plugin_load_if_necessary(p);
  308. if (!p->binary_uri) {
  309. // <plugin> lv2:binary ?binary
  310. SordIter* results = lilv_world_query_internal(
  311. p->world,
  312. p->plugin_uri->node,
  313. p->world->uris.lv2_binary,
  314. NULL);
  315. FOREACH_MATCH(results) {
  316. const SordNode* binary_node = sord_iter_get_node(results, SORD_OBJECT);
  317. if (sord_node_get_type(binary_node) == SORD_URI) {
  318. p->binary_uri = lilv_node_new_from_node(p->world, binary_node);
  319. break;
  320. }
  321. }
  322. sord_iter_free(results);
  323. }
  324. if (!p->binary_uri) {
  325. LILV_WARNF("Plugin <%s> has no lv2:binary\n",
  326. lilv_node_as_uri(lilv_plugin_get_uri(p)));
  327. }
  328. return p->binary_uri;
  329. }
  330. LILV_API
  331. const LilvNodes*
  332. lilv_plugin_get_data_uris(const LilvPlugin* p)
  333. {
  334. return p->data_uris;
  335. }
  336. LILV_API
  337. const LilvPluginClass*
  338. lilv_plugin_get_class(const LilvPlugin* const_p)
  339. {
  340. LilvPlugin* p = (LilvPlugin*)const_p;
  341. lilv_plugin_load_if_necessary(p);
  342. if (!p->plugin_class) {
  343. // <plugin> a ?class
  344. SordIter* results = lilv_world_query_internal(
  345. p->world,
  346. p->plugin_uri->node,
  347. p->world->uris.rdf_a,
  348. NULL);
  349. FOREACH_MATCH(results) {
  350. const SordNode* class_node = sord_iter_get_node(results, SORD_OBJECT);
  351. if (sord_node_get_type(class_node) != SORD_URI) {
  352. continue;
  353. }
  354. LilvNode* klass = lilv_node_new_from_node(p->world, class_node);
  355. if (!lilv_node_equals(klass, p->world->lv2_plugin_class->uri)) {
  356. const LilvPluginClass* pclass = lilv_plugin_classes_get_by_uri(
  357. p->world->plugin_classes, klass);
  358. if (pclass) {
  359. ((LilvPlugin*)p)->plugin_class = pclass;
  360. lilv_node_free(klass);
  361. break;
  362. }
  363. }
  364. lilv_node_free(klass);
  365. }
  366. sord_iter_free(results);
  367. if (p->plugin_class == NULL)
  368. p->plugin_class = p->world->lv2_plugin_class;
  369. }
  370. return p->plugin_class;
  371. }
  372. static LilvNodes*
  373. lilv_plugin_get_value_internal(const LilvPlugin* p,
  374. const SordNode* predicate)
  375. {
  376. lilv_plugin_load_if_necessary(p);
  377. return lilv_world_find_nodes_internal(
  378. p->world, p->plugin_uri->node, predicate, NULL);
  379. }
  380. LILV_API
  381. bool
  382. lilv_plugin_verify(const LilvPlugin* plugin)
  383. {
  384. LilvNode* rdf_type = lilv_new_uri(plugin->world, LILV_NS_RDF "type");
  385. LilvNodes* results = lilv_plugin_get_value(plugin, rdf_type);
  386. lilv_node_free(rdf_type);
  387. if (!results) {
  388. return false;
  389. }
  390. lilv_nodes_free(results);
  391. results = lilv_plugin_get_value_internal(plugin,
  392. plugin->world->uris.doap_name);
  393. if (!results) {
  394. return false;
  395. }
  396. lilv_nodes_free(results);
  397. LilvNode* lv2_port = lilv_new_uri(plugin->world, LV2_CORE__port);
  398. results = lilv_plugin_get_value(plugin, lv2_port);
  399. lilv_node_free(lv2_port);
  400. if (!results) {
  401. return false;
  402. }
  403. lilv_nodes_free(results);
  404. return true;
  405. }
  406. LILV_API
  407. LilvNode*
  408. lilv_plugin_get_name(const LilvPlugin* plugin)
  409. {
  410. LilvNodes* results = lilv_plugin_get_value_internal(
  411. plugin, plugin->world->uris.doap_name);
  412. LilvNode* ret = NULL;
  413. if (results) {
  414. LilvNode* val = lilv_nodes_get_first(results);
  415. if (lilv_node_is_string(val))
  416. ret = lilv_node_duplicate(val);
  417. lilv_nodes_free(results);
  418. }
  419. if (!ret)
  420. LILV_WARNF("Plugin <%s> has no (mandatory) doap:name\n",
  421. lilv_node_as_string(lilv_plugin_get_uri(plugin)));
  422. return ret;
  423. }
  424. LILV_API
  425. LilvNodes*
  426. lilv_plugin_get_value(const LilvPlugin* p,
  427. const LilvNode* predicate)
  428. {
  429. lilv_plugin_load_if_necessary(p);
  430. return lilv_world_find_nodes(p->world, p->plugin_uri, predicate, NULL);
  431. }
  432. LILV_API
  433. uint32_t
  434. lilv_plugin_get_num_ports(const LilvPlugin* p)
  435. {
  436. lilv_plugin_load_ports_if_necessary(p);
  437. return p->num_ports;
  438. }
  439. LILV_API
  440. void
  441. lilv_plugin_get_port_ranges_float(const LilvPlugin* p,
  442. float* min_values,
  443. float* max_values,
  444. float* def_values)
  445. {
  446. lilv_plugin_load_ports_if_necessary(p);
  447. LilvNode* min = NULL;
  448. LilvNode* max = NULL;
  449. LilvNode* def = NULL;
  450. LilvNode** minptr = min_values ? &min : NULL;
  451. LilvNode** maxptr = max_values ? &max : NULL;
  452. LilvNode** defptr = def_values ? &def : NULL;
  453. for (uint32_t i = 0; i < p->num_ports; ++i) {
  454. lilv_port_get_range(p, p->ports[i], defptr, minptr, maxptr);
  455. if (min_values) {
  456. if (lilv_node_is_float(min) || lilv_node_is_int(min)) {
  457. min_values[i] = lilv_node_as_float(min);
  458. } else {
  459. min_values[i] = NAN;
  460. }
  461. }
  462. if (max_values) {
  463. if (lilv_node_is_float(max) || lilv_node_is_int(max)) {
  464. max_values[i] = lilv_node_as_float(max);
  465. } else {
  466. max_values[i] = NAN;
  467. }
  468. }
  469. if (def_values) {
  470. if (lilv_node_is_float(def) || lilv_node_is_int(def)) {
  471. def_values[i] = lilv_node_as_float(def);
  472. } else {
  473. def_values[i] = NAN;
  474. }
  475. }
  476. lilv_node_free(def);
  477. lilv_node_free(min);
  478. lilv_node_free(max);
  479. }
  480. }
  481. LILV_API
  482. uint32_t
  483. lilv_plugin_get_num_ports_of_class_va(const LilvPlugin* p,
  484. const LilvNode* class_1,
  485. va_list args)
  486. {
  487. lilv_plugin_load_ports_if_necessary(p);
  488. uint32_t count = 0;
  489. // Build array of classes from args so we can walk it several times
  490. size_t n_classes = 0;
  491. const LilvNode** classes = NULL;
  492. for (LilvNode* class_i = NULL; (class_i = va_arg(args, LilvNode*)); ) {
  493. classes = (const LilvNode**)realloc(
  494. classes, ++n_classes * sizeof(LilvNode*));
  495. classes[n_classes - 1] = class_i;
  496. }
  497. // Check each port against every type
  498. for (unsigned i = 0; i < p->num_ports; ++i) {
  499. LilvPort* port = p->ports[i];
  500. if (port && lilv_port_is_a(p, port, class_1)) {
  501. bool matches = true;
  502. for (size_t j = 0; j < n_classes; ++j) {
  503. if (!lilv_port_is_a(p, port, classes[j])) {
  504. matches = false;
  505. break;
  506. }
  507. }
  508. if (matches) {
  509. ++count;
  510. }
  511. }
  512. }
  513. free(classes);
  514. return count;
  515. }
  516. LILV_API
  517. uint32_t
  518. lilv_plugin_get_num_ports_of_class(const LilvPlugin* p,
  519. const LilvNode* class_1, ...)
  520. {
  521. va_list args;
  522. va_start(args, class_1);
  523. uint32_t count = lilv_plugin_get_num_ports_of_class_va(p, class_1, args);
  524. va_end(args);
  525. return count;
  526. }
  527. LILV_API
  528. bool
  529. lilv_plugin_has_latency(const LilvPlugin* p)
  530. {
  531. lilv_plugin_load_if_necessary(p);
  532. SordIter* ports = lilv_world_query_internal(
  533. p->world,
  534. p->plugin_uri->node,
  535. p->world->uris.lv2_port,
  536. NULL);
  537. bool ret = false;
  538. FOREACH_MATCH(ports) {
  539. const SordNode* port = sord_iter_get_node(ports, SORD_OBJECT);
  540. SordIter* prop = lilv_world_query_internal(
  541. p->world,
  542. port,
  543. p->world->uris.lv2_portProperty,
  544. p->world->uris.lv2_reportsLatency);
  545. SordIter* des = lilv_world_query_internal(
  546. p->world,
  547. port,
  548. p->world->uris.lv2_designation,
  549. p->world->uris.lv2_latency);
  550. const bool latent = !sord_iter_end(prop) || !sord_iter_end(des);
  551. sord_iter_free(prop);
  552. sord_iter_free(des);
  553. if (latent) {
  554. ret = true;
  555. break;
  556. }
  557. }
  558. sord_iter_free(ports);
  559. return ret;
  560. }
  561. static const LilvPort*
  562. lilv_plugin_get_port_by_property(const LilvPlugin* plugin,
  563. const LilvNode* port_property)
  564. {
  565. lilv_plugin_load_ports_if_necessary(plugin);
  566. for (uint32_t i = 0; i < plugin->num_ports; ++i) {
  567. LilvPort* port = plugin->ports[i];
  568. SordIter* iter = lilv_world_query_internal(
  569. plugin->world,
  570. port->node->node,
  571. plugin->world->uris.lv2_portProperty,
  572. port_property->node);
  573. const bool found = !sord_iter_end(iter);
  574. sord_iter_free(iter);
  575. if (found) {
  576. return port;
  577. }
  578. }
  579. return NULL;
  580. }
  581. LILV_API
  582. const LilvPort*
  583. lilv_plugin_get_port_by_designation(const LilvPlugin* plugin,
  584. const LilvNode* port_class,
  585. const LilvNode* designation)
  586. {
  587. LilvWorld* world = plugin->world;
  588. lilv_plugin_load_ports_if_necessary(plugin);
  589. for (uint32_t i = 0; i < plugin->num_ports; ++i) {
  590. LilvPort* port = plugin->ports[i];
  591. SordIter* iter = lilv_world_query_internal(
  592. world,
  593. port->node->node,
  594. world->uris.lv2_designation,
  595. designation->node);
  596. const bool found = !sord_iter_end(iter) &&
  597. (!port_class || lilv_port_is_a(plugin, port, port_class));
  598. sord_iter_free(iter);
  599. if (found) {
  600. return port;
  601. }
  602. }
  603. return NULL;
  604. }
  605. LILV_API
  606. uint32_t
  607. lilv_plugin_get_latency_port_index(const LilvPlugin* p)
  608. {
  609. LilvNode* prop = lilv_node_new_from_node(
  610. p->world, p->world->uris.lv2_reportsLatency);
  611. LilvNode* des = lilv_node_new_from_node(
  612. p->world, p->world->uris.lv2_latency);
  613. const LilvPort* prop_port = lilv_plugin_get_port_by_property(p, prop);
  614. const LilvPort* des_port = lilv_plugin_get_port_by_property(p, des);
  615. lilv_node_free(prop);
  616. lilv_node_free(des);
  617. if (prop_port) {
  618. return prop_port->index;
  619. } else if (des_port) {
  620. return des_port->index;
  621. } else {
  622. return UINT32_MAX;
  623. }
  624. }
  625. LILV_API
  626. bool
  627. lilv_plugin_has_feature(const LilvPlugin* p,
  628. const LilvNode* feature)
  629. {
  630. lilv_plugin_load_if_necessary(p);
  631. const SordNode* predicates[] = { p->world->uris.lv2_requiredFeature,
  632. p->world->uris.lv2_optionalFeature,
  633. NULL };
  634. for (const SordNode** pred = predicates; *pred; ++pred) {
  635. if (lilv_world_ask_internal(
  636. p->world, p->plugin_uri->node, *pred, feature->node)) {
  637. return true;
  638. }
  639. }
  640. return false;
  641. }
  642. LILV_API
  643. LilvNodes*
  644. lilv_plugin_get_supported_features(const LilvPlugin* p)
  645. {
  646. LilvNodes* optional = lilv_plugin_get_optional_features(p);
  647. LilvNodes* required = lilv_plugin_get_required_features(p);
  648. LilvNodes* result = lilv_nodes_merge(optional, required);
  649. lilv_nodes_free(optional);
  650. lilv_nodes_free(required);
  651. return result;
  652. }
  653. LILV_API
  654. LilvNodes*
  655. lilv_plugin_get_optional_features(const LilvPlugin* p)
  656. {
  657. lilv_plugin_load_if_necessary(p);
  658. return lilv_world_find_nodes_internal(p->world,
  659. p->plugin_uri->node,
  660. p->world->uris.lv2_optionalFeature,
  661. NULL);
  662. }
  663. LILV_API
  664. LilvNodes*
  665. lilv_plugin_get_required_features(const LilvPlugin* p)
  666. {
  667. lilv_plugin_load_if_necessary(p);
  668. return lilv_world_find_nodes_internal(p->world,
  669. p->plugin_uri->node,
  670. p->world->uris.lv2_requiredFeature,
  671. NULL);
  672. }
  673. LILV_API
  674. bool
  675. lilv_plugin_has_extension_data(const LilvPlugin* p,
  676. const LilvNode* uri)
  677. {
  678. if (!lilv_node_is_uri(uri)) {
  679. LILV_ERRORF("Extension data `%s' is not a URI\n",
  680. sord_node_get_string(uri->node));
  681. return false;
  682. }
  683. lilv_plugin_load_if_necessary(p);
  684. return lilv_world_ask_internal(
  685. p->world,
  686. p->plugin_uri->node,
  687. p->world->uris.lv2_extensionData,
  688. uri->node);
  689. }
  690. LILV_API
  691. LilvNodes*
  692. lilv_plugin_get_extension_data(const LilvPlugin* p)
  693. {
  694. return lilv_plugin_get_value_internal(p, p->world->uris.lv2_extensionData);
  695. }
  696. LILV_API
  697. const LilvPort*
  698. lilv_plugin_get_port_by_index(const LilvPlugin* p,
  699. uint32_t index)
  700. {
  701. lilv_plugin_load_ports_if_necessary(p);
  702. if (index < p->num_ports)
  703. return p->ports[index];
  704. else
  705. return NULL;
  706. }
  707. LILV_API
  708. const LilvPort*
  709. lilv_plugin_get_port_by_symbol(const LilvPlugin* p,
  710. const LilvNode* symbol)
  711. {
  712. lilv_plugin_load_ports_if_necessary(p);
  713. for (uint32_t i = 0; i < p->num_ports; ++i) {
  714. LilvPort* port = p->ports[i];
  715. if (lilv_node_equals(port->symbol, symbol))
  716. return port;
  717. }
  718. return NULL;
  719. }
  720. LILV_API
  721. LilvNode*
  722. lilv_plugin_get_project(const LilvPlugin* p)
  723. {
  724. lilv_plugin_load_if_necessary(p);
  725. SordNode* lv2_project = sord_new_uri(p->world->world,
  726. (const uint8_t*)LV2_CORE__project);
  727. SordIter* projects = lilv_world_query_internal(
  728. p->world,
  729. p->plugin_uri->node,
  730. lv2_project,
  731. NULL);
  732. sord_node_free(p->world->world, lv2_project);
  733. if (sord_iter_end(projects)) {
  734. sord_iter_free(projects);
  735. return NULL;
  736. }
  737. const SordNode* project = sord_iter_get_node(projects, SORD_OBJECT);
  738. sord_iter_free(projects);
  739. return lilv_node_new_from_node(p->world, project);
  740. }
  741. static const SordNode*
  742. lilv_plugin_get_author(const LilvPlugin* p)
  743. {
  744. lilv_plugin_load_if_necessary(p);
  745. SordNode* doap_maintainer = sord_new_uri(
  746. p->world->world, NS_DOAP "maintainer");
  747. SordIter* maintainers = lilv_world_query_internal(
  748. p->world,
  749. p->plugin_uri->node,
  750. doap_maintainer,
  751. NULL);
  752. if (sord_iter_end(maintainers)) {
  753. sord_iter_free(maintainers);
  754. LilvNode* project = lilv_plugin_get_project(p);
  755. if (!project) {
  756. sord_node_free(p->world->world, doap_maintainer);
  757. return NULL;
  758. }
  759. maintainers = lilv_world_query_internal(
  760. p->world,
  761. project->node,
  762. doap_maintainer,
  763. NULL);
  764. lilv_node_free(project);
  765. }
  766. sord_node_free(p->world->world, doap_maintainer);
  767. if (sord_iter_end(maintainers)) {
  768. sord_iter_free(maintainers);
  769. return NULL;
  770. }
  771. const SordNode* author = sord_iter_get_node(maintainers, SORD_OBJECT);
  772. sord_iter_free(maintainers);
  773. return author;
  774. }
  775. LILV_API
  776. LilvNode*
  777. lilv_plugin_get_author_name(const LilvPlugin* plugin)
  778. {
  779. const SordNode* author = lilv_plugin_get_author(plugin);
  780. if (author) {
  781. SordNode* foaf_name = sord_new_uri(plugin->world->world, NS_FOAF "name");
  782. LilvNode* ret = lilv_plugin_get_one(plugin, author, foaf_name);
  783. sord_node_free(plugin->world->world, foaf_name);
  784. return ret;
  785. }
  786. return NULL;
  787. }
  788. LILV_API
  789. LilvNode*
  790. lilv_plugin_get_author_email(const LilvPlugin* plugin)
  791. {
  792. const SordNode* author = lilv_plugin_get_author(plugin);
  793. if (author) {
  794. SordNode* foaf_mbox = sord_new_uri(plugin->world->world, NS_FOAF "mbox");
  795. LilvNode* ret = lilv_plugin_get_one(plugin, author, foaf_mbox);
  796. sord_node_free(plugin->world->world, foaf_mbox);
  797. return ret;
  798. }
  799. return NULL;
  800. }
  801. LILV_API
  802. LilvNode*
  803. lilv_plugin_get_author_homepage(const LilvPlugin* plugin)
  804. {
  805. const SordNode* author = lilv_plugin_get_author(plugin);
  806. if (author) {
  807. SordNode* foaf_homepage = sord_new_uri(plugin->world->world, NS_FOAF "homepage");
  808. LilvNode* ret = lilv_plugin_get_one(plugin, author, foaf_homepage);
  809. sord_node_free(plugin->world->world, foaf_homepage);
  810. return ret;
  811. }
  812. return NULL;
  813. }
  814. LILV_API
  815. bool
  816. lilv_plugin_is_replaced(const LilvPlugin* plugin)
  817. {
  818. return plugin->replaced;
  819. }
  820. LILV_API
  821. LilvUIs*
  822. lilv_plugin_get_uis(const LilvPlugin* p)
  823. {
  824. lilv_plugin_load_if_necessary(p);
  825. SordNode* ui_ui_node = sord_new_uri(p->world->world,
  826. (const uint8_t*)LV2_UI__ui);
  827. SordNode* ui_binary_node = sord_new_uri(p->world->world,
  828. (const uint8_t*)LV2_UI__binary);
  829. LilvUIs* result = lilv_uis_new();
  830. SordIter* uis = lilv_world_query_internal(
  831. p->world,
  832. p->plugin_uri->node,
  833. ui_ui_node,
  834. NULL);
  835. FOREACH_MATCH(uis) {
  836. const SordNode* ui = sord_iter_get_node(uis, SORD_OBJECT);
  837. LilvNode* type = lilv_plugin_get_unique(p, ui, p->world->uris.rdf_a);
  838. LilvNode* binary = lilv_plugin_get_unique(p, ui, ui_binary_node);
  839. if (sord_node_get_type(ui) != SORD_URI
  840. || !lilv_node_is_uri(type)
  841. || !lilv_node_is_uri(binary)) {
  842. lilv_node_free(binary);
  843. lilv_node_free(type);
  844. LILV_ERRORF("Corrupt UI <%s>\n", sord_node_get_string(ui));
  845. continue;
  846. }
  847. LilvUI* lilv_ui = lilv_ui_new(
  848. p->world,
  849. lilv_node_new_from_node(p->world, ui),
  850. type,
  851. binary);
  852. zix_tree_insert((ZixTree*)result, lilv_ui, NULL);
  853. }
  854. sord_iter_free(uis);
  855. sord_node_free(p->world->world, ui_binary_node);
  856. sord_node_free(p->world->world, ui_ui_node);
  857. if (lilv_uis_size(result) > 0) {
  858. return result;
  859. } else {
  860. lilv_uis_free(result);
  861. return NULL;
  862. }
  863. }
  864. LILV_API
  865. LilvNodes*
  866. lilv_plugin_get_related(const LilvPlugin* plugin, const LilvNode* type)
  867. {
  868. lilv_plugin_load_if_necessary(plugin);
  869. LilvWorld* const world = plugin->world;
  870. LilvNodes* const related = lilv_world_find_nodes_internal(
  871. world,
  872. NULL,
  873. world->uris.lv2_appliesTo,
  874. lilv_plugin_get_uri(plugin)->node);
  875. if (!type) {
  876. return related;
  877. }
  878. LilvNodes* matches = lilv_nodes_new();
  879. LILV_FOREACH(nodes, i, related) {
  880. LilvNode* node = (LilvNode*)lilv_collection_get((ZixTree*)related, i);
  881. if (lilv_world_ask_internal(
  882. world, node->node, world->uris.rdf_a, type->node)) {
  883. zix_tree_insert((ZixTree*)matches,
  884. lilv_node_new_from_node(world, node->node),
  885. NULL);
  886. }
  887. }
  888. lilv_nodes_free(related);
  889. return matches;
  890. }
  891. static SerdEnv*
  892. new_lv2_env(const SerdNode* base)
  893. {
  894. SerdEnv* env = serd_env_new(base);
  895. #define USTR(s) ((const uint8_t*)s)
  896. serd_env_set_prefix_from_strings(env, USTR("doap"), USTR(LILV_NS_DOAP));
  897. serd_env_set_prefix_from_strings(env, USTR("foaf"), USTR(LILV_NS_FOAF));
  898. serd_env_set_prefix_from_strings(env, USTR("lv2"), USTR(LILV_NS_LV2));
  899. serd_env_set_prefix_from_strings(env, USTR("owl"), USTR(LILV_NS_OWL));
  900. serd_env_set_prefix_from_strings(env, USTR("rdf"), USTR(LILV_NS_RDF));
  901. serd_env_set_prefix_from_strings(env, USTR("rdfs"), USTR(LILV_NS_RDFS));
  902. serd_env_set_prefix_from_strings(env, USTR("xsd"), USTR(LILV_NS_XSD));
  903. return env;
  904. }
  905. static void
  906. maybe_write_prefixes(SerdWriter* writer, SerdEnv* env, FILE* file)
  907. {
  908. fseek(file, 0, SEEK_END);
  909. if (ftell(file) == 0) {
  910. serd_env_foreach(
  911. env, (SerdPrefixSink)serd_writer_set_prefix, writer);
  912. } else {
  913. fprintf(file, "\n");
  914. }
  915. }
  916. LILV_API
  917. void
  918. lilv_plugin_write_description(LilvWorld* world,
  919. const LilvPlugin* plugin,
  920. const LilvNode* base_uri,
  921. FILE* plugin_file)
  922. {
  923. const LilvNode* subject = lilv_plugin_get_uri(plugin);
  924. const uint32_t num_ports = lilv_plugin_get_num_ports(plugin);
  925. const SerdNode* base = sord_node_to_serd_node(base_uri->node);
  926. SerdEnv* env = new_lv2_env(base);
  927. SerdWriter* writer = serd_writer_new(
  928. SERD_TURTLE,
  929. (SerdStyle)(SERD_STYLE_ABBREVIATED|SERD_STYLE_CURIED),
  930. env,
  931. NULL,
  932. serd_file_sink,
  933. plugin_file);
  934. // Write prefixes if this is a new file
  935. maybe_write_prefixes(writer, env, plugin_file);
  936. // Write plugin description
  937. SordIter* plug_iter = lilv_world_query_internal(
  938. world, subject->node, NULL, NULL);
  939. sord_write_iter(plug_iter, writer);
  940. // Write port descriptions
  941. for (uint32_t i = 0; i < num_ports; ++i) {
  942. const LilvPort* port = plugin->ports[i];
  943. SordIter* port_iter = lilv_world_query_internal(
  944. world, port->node->node, NULL, NULL);
  945. sord_write_iter(port_iter, writer);
  946. }
  947. serd_writer_free(writer);
  948. serd_env_free(env);
  949. }
  950. LILV_API
  951. void
  952. lilv_plugin_write_manifest_entry(LilvWorld* world,
  953. const LilvPlugin* plugin,
  954. const LilvNode* base_uri,
  955. FILE* manifest_file,
  956. const char* plugin_file_path)
  957. {
  958. const LilvNode* subject = lilv_plugin_get_uri(plugin);
  959. const SerdNode* base = sord_node_to_serd_node(base_uri->node);
  960. SerdEnv* env = new_lv2_env(base);
  961. SerdWriter* writer = serd_writer_new(
  962. SERD_TURTLE,
  963. (SerdStyle)(SERD_STYLE_ABBREVIATED|SERD_STYLE_CURIED),
  964. env,
  965. NULL,
  966. serd_file_sink,
  967. manifest_file);
  968. // Write prefixes if this is a new file
  969. maybe_write_prefixes(writer, env, manifest_file);
  970. // Write manifest entry
  971. serd_writer_write_statement(
  972. writer, 0, NULL,
  973. sord_node_to_serd_node(subject->node),
  974. sord_node_to_serd_node(plugin->world->uris.rdf_a),
  975. sord_node_to_serd_node(plugin->world->uris.lv2_Plugin), 0, 0);
  976. const SerdNode file_node = serd_node_from_string(
  977. SERD_URI, (const uint8_t*)plugin_file_path);
  978. serd_writer_write_statement(
  979. writer, 0, NULL,
  980. sord_node_to_serd_node(subject->node),
  981. sord_node_to_serd_node(plugin->world->uris.rdfs_seeAlso),
  982. &file_node, 0, 0);
  983. serd_writer_free(writer);
  984. serd_env_free(env);
  985. }