lv2info/
lv2info.rs

1use lilv::{node::Node, plugin::Plugin, port::FloatRanges, World};
2
3struct Nodes {
4    control_class: Node,
5    event_class: Node,
6    group_pred: Node,
7    label_pred: Node,
8    preset_class: Node,
9    designation_pred: Node,
10    supports_event_pred: Node,
11}
12
13fn print_port(p: &Plugin, index: usize, port_ranges: &FloatRanges, nodes: &Nodes) {
14    let port = p.port_by_index(index);
15
16    println!("\n\tPort {}:", index);
17
18    if port.is_none() {
19        println!("\t\tERROR: Illegal/nonexistent port");
20        return;
21    }
22
23    let port = port.unwrap();
24
25    print!("\t\tType:        ");
26
27    for (i, value) in port.classes().iter().enumerate() {
28        if i != 0 {
29            print!("\n\t\t             ");
30        }
31        print!("{}", value.as_uri().unwrap());
32    }
33
34    if port.is_a(&nodes.event_class) {
35        let supported = port.value(&nodes.supports_event_pred);
36        if supported.count() > 0 {
37            println!("\n\t\tSupported events:\n");
38            for value in supported {
39                println!("\t\t\t{}", value.as_uri().unwrap());
40            }
41        }
42    }
43
44    let points = port.scale_points();
45    println!("\n\t\tScale Points:");
46    for point in points {
47        println!(
48            "\t\t\t{} = \"{}\"",
49            point.value().as_str().unwrap(),
50            point.label().as_str().unwrap(),
51        );
52    }
53
54    println!(
55        "\n\t\tSymbol:      {}",
56        port.symbol().unwrap().as_str().unwrap(),
57    );
58
59    println!(
60        "\t\tName:        {}",
61        port.name().unwrap().as_str().unwrap(),
62    );
63
64    let groups = port.value(&nodes.group_pred);
65    if let Some(group) = groups.iter().next() {
66        println!("\t\tGroup:       {}", group.as_str().unwrap(),);
67    }
68
69    let designations = port.value(&nodes.designation_pred);
70    if let Some(designation) = designations.iter().next() {
71        println!("\t\tDesignation: {}", designation.as_str().unwrap(),);
72    }
73
74    if port.is_a(&nodes.control_class) {
75        let (min, max, def) = (port_ranges.min, port_ranges.max, port_ranges.default);
76
77        if !min.is_nan() {
78            println!("\t\tMinimum:     {}", min);
79        }
80
81        if !max.is_nan() {
82            println!("\t\tMaximum:     {}", max);
83        }
84
85        if !def.is_nan() {
86            println!("\t\tDefault:     {}", def);
87        }
88
89        let properties = port.properties();
90        for (i, property) in properties.iter().enumerate() {
91            if i != 0 {
92                print!("\t\t             ");
93            }
94            println!("{}", property.as_uri().unwrap());
95        }
96        println!();
97    }
98}
99
100#[allow(clippy::too_many_lines)]
101fn print_plugin(world: &World, p: &Plugin, nodes: &Nodes) {
102    println!("{}\n", p.uri().as_uri().unwrap());
103    println!("\tName:              {}", p.name().as_str().unwrap());
104    println!(
105        "\tClass:             {}",
106        p.class().label().as_str().unwrap()
107    );
108
109    if let Some(val) = p.author_name() {
110        println!("\tAuthor:            {}", val.as_str().unwrap());
111    }
112
113    if let Some(val) = p.author_email() {
114        println!("\tAuthor Email:      {}", val.as_str().unwrap());
115    }
116
117    if let Some(val) = p.author_homepage() {
118        println!("\tAuthor Homepage:   {}", val.as_uri().unwrap());
119    }
120
121    if let Some(latency_port) = p.latency_port_index() {
122        println!(
123            "\tHas latency:       yes, reported by port {}",
124            latency_port
125        );
126    } else {
127        println!("\tHas latency:       no");
128    }
129
130    println!("\tBundle:            {}", p.bundle_uri().as_uri().unwrap());
131    println!(
132        "\tBinary:            {}",
133        p.library_uri().map_or("<none>".to_string(), |node| node
134            .as_uri()
135            .unwrap()
136            .to_string())
137    );
138
139    if let Some(uis) = p.uis() {
140        println!("\tUIs:");
141
142        for ui in uis {
143            println!("\t\t{}", ui.uri().as_uri().unwrap());
144
145            for tyep in ui.classes() {
146                println!("\t\t\tClass:  {}", tyep.as_uri().unwrap());
147            }
148
149            println!(
150                "\t\t\tBinary: {}",
151                ui.binary_uri().unwrap().as_uri().unwrap()
152            );
153            println!(
154                "\t\t\tBundle: {}",
155                ui.bundle_uri().unwrap().as_uri().unwrap()
156            );
157        }
158    }
159
160    print!("\tData URIs:         ");
161
162    for (i, uri) in p.data_uris().iter().enumerate() {
163        if i != 0 {
164            print!("\n\t                   ");
165        }
166
167        print!("{}", uri.as_uri().unwrap());
168    }
169
170    println!();
171
172    let features = p.required_features();
173    print!("\tRequired Features: ");
174
175    for (i, feature) in features.iter().enumerate() {
176        if i != 0 {
177            print!("\n\t                   ");
178        }
179        print!("{}", feature.as_uri().unwrap());
180    }
181    println!();
182
183    let features = p.optional_features();
184    print!("\tOptional Features: ");
185
186    for (i, feature) in features.iter().enumerate() {
187        if i != 0 {
188            print!("\n\t                   ");
189        }
190        print!("{}", feature.as_uri().unwrap());
191    }
192    println!();
193
194    if let Some(data) = p.extension_data() {
195        print!("\tExtension Data:    ");
196
197        for (i, d) in data.iter().enumerate() {
198            if i != 0 {
199                print!("\n\t                   ");
200            }
201            print!("{}", d.as_uri().unwrap());
202        }
203        println!();
204    }
205
206    if let Some(presets) = p.related(Some(&nodes.preset_class)) {
207        if presets.count() != 0 {
208            println!("\tPresets: ");
209
210            for preset in presets {
211                world.load_resource(&preset).unwrap();
212
213                let titles = world.find_nodes(Some(&preset), &nodes.label_pred, None);
214                if titles.count() > 0 {
215                    if let Some(title) = titles.iter().next() {
216                        println!("\t         {}", title.as_str().unwrap());
217                    } else {
218                        println!("\t         <{}>", preset.as_uri().unwrap());
219                    }
220                } else {
221                    println!("\t         <{}>", preset.as_uri().unwrap());
222                }
223            }
224        }
225    }
226
227    let num_ports = p.ports_count();
228    let port_ranges = p.port_ranges_float();
229    assert_eq!(num_ports, port_ranges.len());
230    for (i, pr) in port_ranges.iter().enumerate() {
231        print_port(p, i, pr, nodes);
232    }
233}
234
235fn main() {
236    let w = World::new();
237    w.load_all();
238
239    let nodes = Nodes {
240        control_class: w.new_uri("http://lv2plug.in/ns/lv2core#ControlPort"),
241        event_class: w.new_uri("http://lv2plug.in/ns/ext/atom#AtomPort"),
242        group_pred: w.new_uri("http://lv2plug.in/ns/ext/port-groups#group"),
243        label_pred: w.new_uri("http://www.w3.org/2000/01/rdf-schema#label"),
244        preset_class: w.new_uri("http://lv2plug.in/ns/ext/presets#Preset"),
245        designation_pred: w.new_uri("http://lv2plug.in/ns/lv2core#designation"),
246        supports_event_pred: w.new_uri("http://lv2plug.in/ns/ext/atom#supportsEvent"),
247    };
248
249    for p in w.plugins().iter().filter(Plugin::verify) {
250        print_plugin(&w, &p, &nodes);
251    }
252}