1use crate::instance::Instance;
2use crate::node::{Node, Nodes};
3use crate::port::{FloatRanges, Port};
4use crate::ui::Uis;
5use crate::world::Life;
6use lilv_sys as lib;
7use lv2_raw::LV2Feature;
8use std::borrow::Borrow;
9use std::convert::TryFrom;
10use std::fmt::Debug;
11use std::ptr::NonNull;
12use std::sync::Arc;
13
14unsafe impl Send for Plugin {}
15unsafe impl Sync for Plugin {}
16
17#[derive(Clone)]
19pub struct Plugin {
20 pub(crate) inner: NonNull<lib::LilvPlugin>,
21 pub(crate) life: Arc<Life>,
22}
23
24impl Plugin {
25 #[must_use]
29 pub fn verify(&self) -> bool {
30 let _life = self.life.inner.lock();
31 let plugin = self.inner.as_ptr();
32 unsafe { lib::lilv_plugin_verify(plugin) }
33 }
34
35 #[must_use]
39 pub fn uri(&self) -> Node {
40 let _life = self.life.inner.lock();
41 let plugin = self.inner.as_ptr();
42 let ptr = NonNull::new(unsafe { lib::lilv_plugin_get_uri(plugin) as _ }).unwrap();
43 let world = self.life.clone();
44 Node {
45 inner: ptr,
46 borrowed: true,
47 life: world,
48 }
49 }
50
51 #[must_use]
55 pub fn bundle_uri(&self) -> Node {
56 let _life = self.life.inner.lock();
57 let plugin = self.inner.as_ptr();
58
59 {
60 let ptr =
61 NonNull::new(unsafe { lib::lilv_plugin_get_bundle_uri(plugin) as _ }).unwrap();
62 let world = self.life.clone();
63 Node {
64 inner: ptr,
65 borrowed: true,
66 life: world,
67 }
68 }
69 }
70
71 #[must_use]
73 pub fn data_uris(&self) -> Nodes {
74 let _life = self.life.inner.lock();
75 let plugin = self.inner.as_ptr();
76
77 Nodes {
78 inner: unsafe { lib::lilv_plugin_get_data_uris(plugin) },
79 life: self.life.clone(),
80 }
81 }
82
83 #[must_use]
85 pub fn library_uri(&self) -> Option<Node> {
86 let _life = self.life.inner.lock();
87 let plugin = self.inner.as_ptr();
88
89 Some({
90 let ptr = NonNull::new(unsafe { lib::lilv_plugin_get_library_uri(plugin) as _ })?;
91 let world = self.life.clone();
92 Node {
93 inner: ptr,
94 borrowed: true,
95 life: world,
96 }
97 })
98 }
99
100 #[must_use]
105 pub fn name(&self) -> Node {
106 let _life = self.life.inner.lock();
107 let plugin = self.inner.as_ptr();
108
109 {
110 let ptr = NonNull::new(unsafe { lib::lilv_plugin_get_name(plugin).cast() }).unwrap();
111 let world = self.life.clone();
112 Node {
113 inner: ptr,
114 borrowed: false,
115 life: world,
116 }
117 }
118 }
119
120 #[must_use]
125 pub fn class(&self) -> Class {
126 let _life = self.life.inner.lock();
127 let plugin = self.inner.as_ptr();
128
129 {
130 let ptr =
131 NonNull::new(unsafe { lib::lilv_plugin_get_class(plugin) as *mut _ }).unwrap();
132 let world = self.life.clone();
133 Class {
134 inner: ptr,
135 life: world,
136 }
137 }
138 }
139
140 #[must_use]
143 pub fn value(&self, predicate: &Node) -> Nodes {
144 let _life = self.life.inner.lock();
145 let plugin = self.inner.as_ptr();
146 let predicate = predicate.inner.as_ptr();
147
148 Nodes {
149 inner: unsafe { lib::lilv_plugin_get_value(plugin, predicate) },
150 life: self.life.clone(),
151 }
152 }
153
154 #[must_use]
156 pub fn has_feature(&self, feature_uri: &Node) -> bool {
157 let _life = self.life.inner.lock();
158 let plugin = self.inner.as_ptr();
159 let feature_uri = feature_uri.inner.as_ptr();
160
161 unsafe { lib::lilv_plugin_has_feature(plugin, feature_uri) }
162 }
163
164 #[must_use]
166 pub fn supported_features(&self) -> Nodes {
167 let _life = self.life.inner.lock();
168 let plugin = self.inner.as_ptr();
169 let inner = unsafe { lib::lilv_plugin_get_supported_features(plugin) };
170 let world = self.life.clone();
171 Nodes { inner, life: world }
172 }
173
174 #[must_use]
176 pub fn required_features(&self) -> Nodes {
177 let _life = self.life.inner.lock();
178 let plugin = self.inner.as_ptr();
179 let inner = unsafe { lib::lilv_plugin_get_required_features(plugin) };
180 let world = self.life.clone();
181 Nodes { inner, life: world }
182 }
183
184 #[must_use]
186 pub fn optional_features(&self) -> Nodes {
187 let _life = self.life.inner.lock();
188 let plugin = self.inner.as_ptr();
189 let inner = unsafe { lib::lilv_plugin_get_optional_features(plugin) };
190 let world = self.life.clone();
191 Nodes { inner, life: world }
192 }
193
194 #[must_use]
196 pub fn has_extension_data(&self, uri: &Node) -> bool {
197 let _life = self.life.inner.lock();
198 let plugin = self.inner.as_ptr();
199 let uri = uri.inner.as_ptr();
200
201 unsafe { lib::lilv_plugin_has_extension_data(plugin, uri) }
202 }
203
204 #[must_use]
206 pub fn extension_data(&self) -> Option<Nodes> {
207 let _life = self.life.inner.lock();
208 let plugin = self.inner.as_ptr();
209
210 Some({
211 let inner = unsafe { lib::lilv_plugin_get_extension_data(plugin) };
212 let world = self.life.clone();
213 Nodes { inner, life: world }
214 })
215 }
216
217 #[must_use]
219 pub fn ports_count(&self) -> usize {
220 let _life = self.life.inner.lock();
221 let plugin = self.inner.as_ptr();
222 unsafe { lib::lilv_plugin_get_num_ports(plugin) as _ }
223 }
224
225 #[must_use]
227 pub fn port_ranges_float(&self) -> Vec<FloatRanges> {
228 let ports_count = self.ports_count();
229 let mut min = vec![0_f32; ports_count];
230 let mut max = vec![0_f32; ports_count];
231 let mut default = vec![0_f32; ports_count];
232 let plugin = self.inner.as_ptr();
233
234 unsafe {
235 let _life = self.life.inner.lock();
236 lib::lilv_plugin_get_port_ranges_float(
237 plugin,
238 min.as_mut_ptr(),
239 max.as_mut_ptr(),
240 default.as_mut_ptr(),
241 );
242 }
243 (0..ports_count)
244 .map(|i| FloatRanges {
245 min: min[i],
246 max: max[i],
247 default: default[i],
248 })
249 .collect()
250 }
251
252 #[must_use]
254 pub fn num_ports_of_class<I, N>(&self, classes: I) -> usize
255 where
256 I: IntoIterator<Item = N>,
257 N: Borrow<Node>,
258 {
259 let mut classes = classes.into_iter();
260 let classes_ref = &mut classes;
261 (0..self.ports_count())
262 .filter_map(|index| self.port_by_index(index))
263 .filter(|port| classes_ref.all(|cls| port.is_a(cls.borrow())))
264 .count()
265 }
266
267 #[must_use]
269 pub fn has_latency(&self) -> bool {
270 let _life = self.life.inner.lock();
271 let plugin = self.inner.as_ptr();
272 unsafe { lib::lilv_plugin_has_latency(plugin) }
273 }
274
275 #[must_use]
277 pub fn latency_port_index(&self) -> Option<usize> {
278 if self.has_latency() {
279 let _life = self.life.inner.lock();
280 let plugin = self.inner.as_ptr();
281 Some(unsafe { lib::lilv_plugin_get_latency_port_index(plugin) as _ })
282 } else {
283 None
284 }
285 }
286
287 pub fn iter_ports(&self) -> impl Iterator<Item = Port> {
289 PortsIter {
290 plugin: self.clone(),
291 index: 0,
292 }
293 }
294
295 #[must_use]
297 pub fn port_by_index(&self, index: usize) -> Option<Port> {
298 let _life = self.life.inner.lock();
299 let plugin = self.inner.as_ptr();
300 let index = u32::try_from(index).ok()?;
301
302 Some({
303 let inner = NonNull::new(unsafe {
304 lib::lilv_plugin_get_port_by_index(plugin, index as _) as _
305 })?;
306 Port {
307 inner,
308 plugin: self.clone(),
309 }
310 })
311 }
312
313 #[must_use]
318 pub fn port_by_symbol(&self, symbol: &Node) -> Option<Port> {
319 let _life = self.life.inner.lock();
320 let plugin = self.inner.as_ptr();
321 let symbol = symbol.inner.as_ptr();
322
323 Some({
324 let inner =
325 NonNull::new(unsafe { lib::lilv_plugin_get_port_by_symbol(plugin, symbol) as _ })?;
326 Port {
327 inner,
328 plugin: self.clone(),
329 }
330 })
331 }
332
333 #[must_use]
342 pub fn port_by_designation(
343 &self,
344 port_class: Option<&Node>,
345 designation: &Node,
346 ) -> Option<Port> {
347 let _life = self.life.inner.lock();
348 let plugin = self.inner.as_ptr();
349 let port_class = port_class.map_or(std::ptr::null(), |n| n.inner.as_ptr());
350 let designation = designation.inner.as_ptr();
351
352 Some({
353 let inner = NonNull::new(unsafe {
354 lib::lilv_plugin_get_port_by_designation(plugin, port_class, designation) as _
355 })?;
356 Port {
357 inner,
358 plugin: self.clone(),
359 }
360 })
361 }
362
363 #[must_use]
367 pub fn project(&self) -> Option<Node> {
368 let _life = self.life.inner.lock();
369 let plugin = self.inner.as_ptr();
370
371 Some({
372 let ptr = NonNull::new(unsafe { lib::lilv_plugin_get_project(plugin) })?;
373 let world = self.life.clone();
374 Node {
375 inner: ptr,
376 borrowed: false,
377 life: world,
378 }
379 })
380 }
381
382 #[must_use]
384 pub fn author_name(&self) -> Option<Node> {
385 let _life = self.life.inner.lock();
386 let plugin = self.inner.as_ptr();
387
388 Some({
389 let ptr = NonNull::new(unsafe { lib::lilv_plugin_get_author_name(plugin) })?;
390 let world = self.life.clone();
391 Node {
392 inner: ptr,
393 borrowed: false,
394 life: world,
395 }
396 })
397 }
398
399 #[must_use]
401 pub fn author_email(&self) -> Option<Node> {
402 let _life = self.life.inner.lock();
403 let plugin = self.inner.as_ptr();
404
405 Some({
406 let ptr = NonNull::new(unsafe { lib::lilv_plugin_get_author_email(plugin) })?;
407 let world = self.life.clone();
408 Node {
409 inner: ptr,
410 borrowed: false,
411 life: world,
412 }
413 })
414 }
415
416 #[must_use]
417 pub fn author_homepage(&self) -> Option<Node> {
418 let _life = self.life.inner.lock();
419 let plugin = self.inner.as_ptr();
420 let ptr = NonNull::new(unsafe { lib::lilv_plugin_get_author_homepage(plugin) })?;
421 let world = self.life.clone();
422
423 Some(Node {
424 inner: ptr,
425 borrowed: false,
426 life: world,
427 })
428 }
429
430 #[must_use]
435 pub fn is_replaced(&self) -> bool {
436 let _life = self.life.inner.lock();
437 let plugin = self.inner.as_ptr();
438 unsafe { lib::lilv_plugin_is_replaced(plugin) }
439 }
440
441 #[must_use]
454 pub fn related(&self, typ: Option<&Node>) -> Option<Nodes> {
455 let _life = self.life.inner.lock();
456 let plugin = self.inner.as_ptr();
457 let plugin_type = typ.map_or(std::ptr::null(), |n| n.inner.as_ptr() as _);
458
459 Some({
460 let inner = unsafe { lib::lilv_plugin_get_related(plugin, plugin_type) };
461 let world = self.life.clone();
462 Nodes { inner, life: world }
463 })
464 }
465
466 #[must_use]
468 pub fn uis(&self) -> Option<Uis> {
469 let _life = self.life.inner.lock();
470 let plugin = self.inner.as_ptr();
471
472 Some(Uis {
473 inner: NonNull::new(unsafe { lib::lilv_plugin_get_uis(plugin) })?,
474 life: self.life.clone(),
475 plugin: self.clone(),
476 })
477 }
478
479 #[must_use]
485 pub unsafe fn instantiate<'a, FS>(&self, sample_rate: f64, features: FS) -> Option<Instance>
486 where
487 FS: IntoIterator<Item = &'a LV2Feature>,
488 {
489 let _life = self.life.inner.lock();
490 let plugin = self.inner.as_ptr();
491 let features_vec: Vec<*const LV2Feature> = features
492 .into_iter()
493 .map(|f| f as *const LV2Feature)
494 .chain(std::iter::once(std::ptr::null()))
495 .collect();
496 let inner = NonNull::new(lib::lilv_plugin_instantiate(
497 plugin,
498 sample_rate,
499 features_vec.as_ptr(),
500 ))?;
501
502 Some(Instance { inner })
503 }
504}
505
506impl Debug for Plugin {
507 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
508 f.debug_struct("Plugin")
509 .field("uri", &self.uri())
510 .field("bundle_uri", &self.bundle_uri())
511 .field("data_uris", &self.data_uris())
512 .field("library_uri", &self.library_uri())
513 .field("class", &self.class())
514 .field("required_features", &self.required_features())
515 .field("optional_features", &self.optional_features())
516 .field("ports_count", &self.ports_count())
517 .field("has_latency", &self.has_latency())
518 .field("project", &self.project())
519 .field("author_name", &self.author_name())
520 .field("author_email", &self.author_email())
521 .field("author_homepage", &self.author_homepage())
522 .field("is_replaced", &self.is_replaced())
523 .finish()
524 }
525}
526
527pub struct Plugins {
529 pub(crate) life: Arc<Life>,
530 pub(crate) ptr: *const lib::LilvPlugins,
531}
532
533impl Plugins {
534 pub fn iter(&self) -> impl '_ + Iterator<Item = Plugin> {
536 let _life = self.life.inner.lock();
537 PluginsIter {
538 plugins: self,
539 iter: { unsafe { lib::lilv_plugins_begin(self.ptr) } },
540 }
541 }
542
543 #[must_use]
545 pub fn plugin(&self, uri: &Node) -> Option<Plugin> {
546 let _life = self.life.inner.lock();
547 let uri_ptr = uri.inner.as_ptr();
548 let plugin_ptr: *mut lib::LilvPlugin =
549 unsafe { lib::lilv_plugins_get_by_uri(self.ptr, uri_ptr) as *mut _ };
550 Some(Plugin {
551 life: self.life.clone(),
552 inner: NonNull::new(plugin_ptr)?,
553 })
554 }
555
556 #[must_use]
558 pub fn count(&self) -> usize {
559 let _life = self.life.inner.lock();
560 let size = unsafe { lib::lilv_plugins_size(self.ptr) };
561 size as usize
562 }
563}
564
565impl IntoIterator for Plugins {
566 type Item = Plugin;
567
568 type IntoIter = PluginsIter<Plugins>;
569
570 fn into_iter(self) -> Self::IntoIter {
571 let iter = {
572 let _life = self.life.inner.lock();
573 unsafe { lib::lilv_plugins_begin(self.ptr) }
574 };
575 PluginsIter {
576 plugins: self,
577 iter,
578 }
579 }
580}
581
582pub struct PluginsIter<PS> {
584 pub(crate) plugins: PS,
585 pub(crate) iter: *mut lib::LilvIter,
586}
587
588impl<PS> Iterator for PluginsIter<PS>
589where
590 PS: Borrow<Plugins>,
591{
592 type Item = Plugin;
593
594 fn next(&mut self) -> Option<Plugin> {
595 let _life = self.plugins.borrow().life.inner.lock();
596 let ptr: *mut lib::LilvPlugin =
597 unsafe { lib::lilv_plugins_get(self.plugins.borrow().ptr, self.iter) } as *mut _;
598 self.iter = unsafe { lib::lilv_plugins_next(self.plugins.borrow().ptr, self.iter) };
599 match NonNull::new(ptr) {
600 Some(ptr) => Some(Plugin {
601 life: self.plugins.borrow().life.clone(),
602 inner: ptr,
603 }),
604 None => None,
605 }
606 }
607}
608
609struct PortsIter {
611 pub(crate) plugin: Plugin,
612 pub(crate) index: usize,
613}
614
615impl Iterator for PortsIter {
616 type Item = Port;
617
618 fn next(&mut self) -> Option<Port> {
619 let index = self.index;
620 self.index += 1;
621 self.plugin.port_by_index(index)
622 }
623}
624
625unsafe impl Send for Class {}
626unsafe impl Sync for Class {}
627
628pub struct Class {
632 pub(crate) inner: NonNull<lib::LilvPluginClass>,
633 pub(crate) life: Arc<Life>,
634}
635
636impl Class {
637 #[must_use]
642 pub fn label(&self) -> Node {
643 let _life = self.life.inner.lock();
644 let inner = self.inner.as_ptr();
645
646 {
647 let ptr =
648 NonNull::new(unsafe { lib::lilv_plugin_class_get_label(inner) as _ }).unwrap();
649 let world = self.life.clone();
650 Node {
651 inner: ptr,
652 borrowed: true,
653 life: world,
654 }
655 }
656 }
657
658 #[must_use]
660 pub fn uri(&self) -> Option<Node> {
661 let _life = self.life.inner.lock();
662 let inner = self.inner.as_ptr();
663
664 {
665 let ptr = NonNull::new(unsafe { lib::lilv_plugin_class_get_uri(inner) as _ })?;
666 let world = self.life.clone();
667 Node {
668 inner: ptr,
669 borrowed: true,
670 life: world,
671 }
672 }
673 .into()
674 }
675
676 #[must_use]
680 pub fn parent_uri(&self) -> Option<Node> {
681 let _life = self.life.inner.lock();
682 let inner = self.inner.as_ptr();
683
684 Some({
685 let ptr = NonNull::new(unsafe { lib::lilv_plugin_class_get_parent_uri(inner) as _ })?;
686 let world = self.life.clone();
687 Node {
688 inner: ptr,
689 borrowed: true,
690 life: world,
691 }
692 })
693 }
694
695 #[must_use]
700 pub fn children(&self) -> Option<Classes> {
701 let _life = self.life.inner.lock();
702 let inner = self.inner.as_ptr();
703 Classes {
704 inner: NonNull::new(unsafe { lib::lilv_plugin_class_get_children(inner) })?,
705 life: self.life.clone(),
706 }
707 .into()
708 }
709}
710
711impl Debug for Class {
712 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
713 f.debug_struct("PluginClass")
714 .field("label", &self.label())
715 .field("uri", &self.uri())
716 .field("parent_uri", &self.parent_uri())
717 .finish()
718 }
719}
720
721pub struct Classes {
723 pub(crate) inner: NonNull<lib::LilvPluginClasses>,
724 pub(crate) life: Arc<Life>,
725}
726
727impl Classes {
728 #[must_use]
730 pub fn iter(&self) -> ClassIter {
731 let _life = self.life.inner.lock();
732 ClassIter {
733 classes: self.inner.as_ptr(),
734 iter: unsafe { lib::lilv_plugin_classes_begin(self.inner.as_ptr()) },
735 life: self.life.clone(),
736 }
737 }
738
739 #[must_use]
741 pub fn count(&self) -> usize {
742 let _life = self.life.inner.lock();
743 unsafe { lib::lilv_plugin_classes_size(self.inner.as_ptr()) as _ }
744 }
745
746 #[must_use]
748 pub fn get_by_uri(&self, uri: &Node) -> Option<Class> {
749 let _life = self.life.inner.lock();
750 let inner = self.inner.as_ptr();
751 let uri = uri.inner.as_ptr();
752
753 Some({
754 let ptr =
755 NonNull::new(unsafe { lib::lilv_plugin_classes_get_by_uri(inner, uri) as _ })?;
756 let world = self.life.clone();
757 Class {
758 inner: ptr,
759 life: world,
760 }
761 })
762 }
763}
764
765pub struct ClassIter {
767 classes: *mut lib::LilvPluginClasses,
768 iter: *mut lib::LilvIter,
769 life: Arc<Life>,
770}
771
772impl Iterator for ClassIter {
773 type Item = Class;
774
775 #[must_use]
776 fn next(&mut self) -> Option<Class> {
777 let _life = self.life.inner.lock();
778 let ptr = unsafe { lib::lilv_plugin_classes_get(self.classes, self.iter) };
779 if ptr.is_null() {
780 None
781 } else {
782 self.iter = unsafe { lib::lilv_plugin_classes_next(self.classes, self.iter) };
783 Some({
784 let ptr = NonNull::new(ptr as _)?;
785 let world = self.life.clone();
786 Class {
787 inner: ptr,
788 life: world,
789 }
790 })
791 }
792 }
793}
794
795#[cfg(test)]
796mod tests {
797 use crate::world::World;
798
799 #[test]
800 fn test_plugin_format() {
801 let world = World::new();
802 for plugin in world.plugins() {
803 _ = format!("{:?}", plugin);
805 }
806 }
807}