lilv/
port.rs

1use crate::node::{Node, Nodes};
2use crate::plugin::Plugin;
3use lilv_sys as lib;
4use std::fmt::Debug;
5use std::ptr::NonNull;
6
7#[derive(Clone)]
8pub struct Port {
9    pub(crate) inner: NonNull<lib::LilvPort>,
10    pub(crate) plugin: Plugin,
11}
12
13impl Port {
14    /// Get the node for the port.
15    ///
16    /// # Panics
17    /// Panics if the node could not be obtained.
18    #[must_use]
19    pub fn node(&self) -> Node {
20        let _life = self.plugin.life.inner.lock();
21        let plugin = self.plugin.inner.as_ptr();
22        let port = self.inner.as_ptr();
23
24        {
25            let ptr = NonNull::new(unsafe { lib::lilv_port_get_node(plugin, port) as _ }).unwrap();
26            let world = self.plugin.life.clone();
27            Node {
28                inner: ptr,
29                borrowed: true,
30                life: world,
31            }
32        }
33    }
34
35    /// Get the value associated with the port in a plugin's data files.
36    ///
37    /// `predicate` must be either a URI or a `QName`.
38    /// Returns the ?object of all triples found of the form:
39    ///     `<plugin-uri> predicate ?object`
40    #[must_use]
41    pub fn value(&self, predicate: &Node) -> Nodes {
42        let _life = self.plugin.life.inner.lock();
43        let plugin = self.plugin.inner.as_ptr();
44        let port = self.inner.as_ptr();
45        let predicate = predicate.inner.as_ptr();
46        let inner = unsafe { lib::lilv_port_get_value(plugin, port, predicate) };
47        let world = self.plugin.life.clone();
48        Nodes { inner, life: world }
49    }
50
51    /// Get a single property value of a port.
52    ///
53    /// This is equivalent to getting the first iterable value of
54    /// `self.value(predicate)`.
55    #[must_use]
56    pub fn get(&self, predicate: &Node) -> Option<Node> {
57        let _life = self.plugin.life.inner.lock();
58        let plugin = self.plugin.inner.as_ptr();
59        let port = self.inner.as_ptr();
60        let predicate = predicate.inner.as_ptr();
61
62        Some({
63            let ptr = NonNull::new(unsafe { lib::lilv_port_get(plugin, port, predicate) })?;
64            let world = self.plugin.life.clone();
65            Node {
66                inner: ptr,
67                borrowed: false,
68                life: world,
69            }
70        })
71    }
72
73    /// Return the LV2 port properties of a port.
74    #[must_use]
75    pub fn properties(&self) -> Nodes {
76        let _life = self.plugin.life.inner.lock();
77        let plugin = self.plugin.inner.as_ptr();
78        let port = self.inner.as_ptr();
79        let inner = unsafe { lib::lilv_port_get_properties(plugin, port) };
80        let world = self.plugin.life.clone();
81        Nodes { inner, life: world }
82    }
83
84    /// Returns true if the port has the given property.
85    #[must_use]
86    pub fn has_property(&self, property_uri: &Node) -> bool {
87        let _life = self.plugin.life.inner.lock();
88        let plugin = self.plugin.inner.as_ptr();
89        let port = self.inner.as_ptr();
90        let property_uri = property_uri.inner.as_ptr();
91
92        unsafe { lib::lilv_port_has_property(plugin, port, property_uri) }
93    }
94
95    /// Returns `true` if the port supports a certain event type.
96    ///
97    /// More precisely, this returns `true` if and only iff the port has an
98    /// `atom:supports` or an `ev:supportsEvent` property with `event_type` as
99    /// the value.
100    #[must_use]
101    pub fn supports_event(&self, event_type: &Node) -> bool {
102        let _life = self.plugin.life.inner.lock();
103        let plugin = self.plugin.inner.as_ptr();
104        let port = self.inner.as_ptr();
105        let event_type = event_type.inner.as_ptr();
106
107        unsafe { lib::lilv_port_supports_event(plugin, port, event_type) }
108    }
109
110    /// Returns the index of the port within the plugin.
111    #[must_use]
112    pub fn index(&self) -> usize {
113        let _life = self.plugin.life.inner.lock();
114        let plugin = self.plugin.inner.as_ptr();
115        let port = self.inner.as_ptr();
116
117        unsafe { lib::lilv_port_get_index(plugin, port) as _ }
118    }
119
120    /// Get the symbol of a port.
121    ///
122    /// Symbol is a short string.
123    #[must_use]
124    pub fn symbol(&self) -> Option<Node> {
125        let _life = self.plugin.life.inner.lock();
126        let plugin = self.plugin.inner.as_ptr();
127        let port = self.inner.as_ptr();
128
129        {
130            let ptr = NonNull::new(unsafe { lib::lilv_port_get_symbol(plugin, port) as _ })?;
131            let world = self.plugin.life.clone();
132            Node {
133                inner: ptr,
134                borrowed: true,
135                life: world,
136            }
137        }
138        .into()
139    }
140
141    /// Get the name of a port.
142    ///
143    /// The is guaranteed to return the untraslated name (the doap:name in the
144    /// data file without a language tag).
145    #[must_use]
146    pub fn name(&self) -> Option<Node> {
147        let _life = self.plugin.life.inner.lock();
148        let plugin = self.plugin.inner.as_ptr();
149        let port = self.inner.as_ptr();
150
151        Some({
152            let ptr = NonNull::new(unsafe { lib::lilv_port_get_name(plugin, port) })?;
153            let world = self.plugin.life.clone();
154            Node {
155                inner: ptr,
156                borrowed: false,
157                life: world,
158            }
159        })
160    }
161
162    /// Get all the classes of the port.
163    ///
164    /// This can be used to determine if a port is an input, output, audio,
165    /// control, midi, etc... although it's simpler to use `Port::is_a`.
166    #[must_use]
167    pub fn classes(&self) -> Nodes {
168        let _life = self.plugin.life.inner.lock();
169        let plugin = self.plugin.inner.as_ptr();
170        let port = self.inner.as_ptr();
171        let inner = unsafe { lib::lilv_port_get_classes(plugin, port) };
172        let world = self.plugin.life.clone();
173        Nodes { inner, life: world }
174    }
175
176    /// Returns `true` if the port is of the given type.
177    #[must_use]
178    pub fn is_a(&self, port_class: &Node) -> bool {
179        let _life = self.plugin.life.inner.lock();
180        let plugin = self.plugin.inner.as_ptr();
181        let port = self.inner.as_ptr();
182        let port_class = port_class.inner.as_ptr();
183
184        unsafe { lib::lilv_port_is_a(plugin, port, port_class) }
185    }
186
187    /// The the range (default, minimum, maximum) values of the port.
188    ///
189    /// # Panics
190    /// Panics if the range could not be obtained.
191    #[must_use]
192    pub fn range(&self) -> Range {
193        let _life = self.plugin.life.inner.lock();
194        let plugin = self.plugin.inner.as_ptr();
195        let port = self.inner.as_ptr();
196
197        let mut default_ptr: *mut lib::LilvNodeImpl = std::ptr::null_mut();
198        let mut minimum_ptr: *mut lib::LilvNodeImpl = std::ptr::null_mut();
199        let mut maximum_ptr: *mut lib::LilvNodeImpl = std::ptr::null_mut();
200
201        unsafe {
202            lib::lilv_port_get_range(
203                plugin,
204                port,
205                &mut default_ptr,
206                &mut minimum_ptr,
207                &mut maximum_ptr,
208            );
209        };
210        let ptr_to_node = |ptr: *mut lib::LilvNodeImpl| -> Option<Node> {
211            let ptr = NonNull::new(ptr.cast())?;
212            let world = self.plugin.life.clone();
213            Some(Node {
214                inner: ptr,
215                borrowed: false,
216                life: world,
217            })
218        };
219        Range {
220            default: ptr_to_node(default_ptr),
221            minimum: ptr_to_node(minimum_ptr),
222            maximum: ptr_to_node(maximum_ptr),
223        }
224    }
225
226    /// Get the scale points (enumeration values) of a port.
227    ///
228    /// This returns a collection of "interesting" named values of a port. These
229    /// are appropriate entries for a UI selector.
230    #[must_use]
231    pub fn scale_points(&self) -> ScalePoints {
232        let _life = self.plugin.life.inner.lock();
233        let plugin = self.plugin.inner.as_ptr() as *const _;
234        let port = self.inner.as_ptr() as *const _;
235
236        ScalePoints {
237            inner: unsafe { lib::lilv_port_get_scale_points(plugin, port) },
238            port: self.clone(),
239            refs: std::sync::Arc::new(1.into()),
240        }
241    }
242}
243
244impl Debug for Port {
245    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
246        f.debug_struct("Port")
247            .field("name", &self.name())
248            .field("symbol", &self.symbol())
249            .field("classes", &self.classes())
250            .field("range", &self.range())
251            .field("properties", &self.properties())
252            .finish()
253    }
254}
255
256unsafe impl Sync for ScalePoint {}
257
258#[derive(Clone)]
259pub struct ScalePoint {
260    pub(crate) inner: NonNull<lib::LilvScalePoint>,
261    pub(crate) port: Port,
262
263    // The underlying ScalePoints must be kept alive for the lifetime of the
264    // ScalePoint object.
265    _collection: ScalePoints,
266}
267
268impl ScalePoint {
269    /// Get the label of the scale point (enumeration value).
270    ///
271    /// # Panics
272    /// Panics if the node for the value could not be obtained.
273    #[must_use]
274    pub fn label(&self) -> Node {
275        let _life = self.port.plugin.life.inner.lock();
276        let inner = self.inner.as_ptr();
277
278        {
279            let ptr = NonNull::new(unsafe { lib::lilv_scale_point_get_label(inner) as _ }).unwrap();
280            let world = self.port.plugin.life.clone();
281            Node {
282                inner: ptr,
283                borrowed: true,
284                life: world,
285            }
286        }
287    }
288
289    /// Get the value of the scale point (enumeration value).
290    ///
291    /// # Panics
292    /// Panics if the node for the value could not be obtained.
293    #[must_use]
294    pub fn value(&self) -> Node {
295        let _life = self.port.plugin.life.inner.lock();
296        let inner = self.inner.as_ptr();
297
298        {
299            let ptr = NonNull::new(unsafe { lib::lilv_scale_point_get_value(inner) as _ }).unwrap();
300            let world = self.port.plugin.life.clone();
301            Node {
302                inner: ptr,
303                borrowed: true,
304                life: world,
305            }
306        }
307    }
308}
309
310impl Debug for ScalePoint {
311    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
312        f.debug_struct("ScalePoint")
313            .field("label", &self.label())
314            .field("value", &self.value())
315            .finish()
316    }
317}
318
319pub struct ScalePoints {
320    pub(crate) inner: *const lib::LilvScalePoints,
321    pub(crate) port: Port,
322    pub(crate) refs: std::sync::Arc<std::sync::atomic::AtomicUsize>,
323}
324
325impl ScalePoints {
326    /// The number of scale points within the collection.
327    #[must_use]
328    pub fn count(&self) -> usize {
329        let _life = self.port.plugin.life.inner.lock();
330        let size: u32 = unsafe { lib::lilv_scale_points_size(self.inner) };
331        size as usize
332    }
333
334    /// An iterator over the scale points in the collection.
335    #[must_use]
336    pub fn iter(&self) -> ScalePointsIter {
337        let _life = self.port.plugin.life.inner.lock();
338        ScalePointsIter {
339            inner: self.clone(),
340            iter: unsafe { lib::lilv_scale_points_begin(self.inner) },
341        }
342    }
343}
344
345impl Drop for ScalePoints {
346    fn drop(&mut self) {
347        let refs = self.refs.fetch_sub(1, std::sync::atomic::Ordering::SeqCst);
348        if refs == 0 {
349            unsafe {
350                lib::lilv_scale_points_free(self.inner as *mut _);
351            }
352        }
353    }
354}
355
356impl Clone for ScalePoints {
357    fn clone(&self) -> Self {
358        self.refs.fetch_add(1, std::sync::atomic::Ordering::SeqCst);
359        Self {
360            inner: self.inner,
361            port: self.port.clone(),
362            refs: self.refs.clone(),
363        }
364    }
365}
366
367impl Debug for ScalePoints {
368    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
369        let pts = self.iter().collect::<Vec<_>>();
370        f.debug_struct("ScalePoints")
371            .field("scale_points", &pts)
372            .finish()
373    }
374}
375
376impl IntoIterator for ScalePoints {
377    type Item = ScalePoint;
378
379    type IntoIter = ScalePointsIter;
380
381    fn into_iter(self) -> Self::IntoIter {
382        self.iter()
383    }
384}
385
386/// An iterator over scale points.
387#[derive(Clone)]
388pub struct ScalePointsIter {
389    inner: ScalePoints,
390    iter: *mut lib::LilvIter,
391}
392
393impl Iterator for ScalePointsIter {
394    type Item = ScalePoint;
395
396    fn next(&mut self) -> Option<ScalePoint> {
397        let _life = self.inner.port.plugin.life.inner.lock();
398        let next_ptr =
399            unsafe { lib::lilv_scale_points_get(self.inner.inner, self.iter.cast()) } as *mut _;
400        let next = Some(ScalePoint {
401            inner: NonNull::new(next_ptr)?,
402            port: self.inner.port.clone(),
403            _collection: self.inner.clone(),
404        });
405        self.iter = unsafe { lib::lilv_scale_points_next(self.inner.inner, self.iter) };
406        next
407    }
408}
409
410/// Describes the ranges of the port if possible.
411#[allow(clippy::module_name_repetitions)]
412#[derive(Clone, Debug, PartialEq)]
413pub struct Range {
414    /// The default value of the port.
415    pub default: Option<Node>,
416    /// The minimum value of the port.
417    pub minimum: Option<Node>,
418    /// The maximum value of the port.
419    pub maximum: Option<Node>,
420}
421
422/// Describes the range of the ports of a plugin.
423#[derive(Copy, Clone, Debug, PartialEq)]
424pub struct FloatRanges {
425    /// The default value of the port.
426    pub default: f32,
427    /// The minimum value of the port.
428    pub min: f32,
429    /// The maximum value of the port.
430    pub max: f32,
431}