1 /*
2 Copyright 2007-2020 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 #undef NDEBUG
18
19 #include "lilv_test_utils.h"
20
21 #include "lilv/lilv.h"
22
23 #include <assert.h>
24 #include <stdbool.h>
25 #include <string.h>
26
27 static const char* const plugin_ttl = "\
28 @prefix lv2ev: <http://lv2plug.in/ns/ext/event#> . \n\
29 :plug\n\
30 a lv2:Plugin ;\n\
31 doap:name \"Test plugin\" ;\n\
32 doap:homepage <http://example.org/someplug> ;\n\
33 lv2:port [\n\
34 a lv2:ControlPort ;\n\
35 a lv2:InputPort ;\n\
36 lv2:index 0 ;\n\
37 lv2:symbol \"foo\" ;\n\
38 lv2:name \"store\" ;\n\
39 lv2:name \"Laden\"@de-de ;\n\
40 lv2:name \"Geschaeft\"@de-at ;\n\
41 lv2:name \"tienda\"@es ;\n\
42 rdfs:comment \"comment\"@en , \"commentaires\"@fr ;\n\
43 lv2:portProperty lv2:integer ;\n\
44 lv2:minimum -1.0 ;\n\
45 lv2:maximum 1.0 ;\n\
46 lv2:default 0.5 ;\n\
47 lv2:scalePoint [\n\
48 rdfs:label \"Sin\";\n\
49 rdf:value 3\n\
50 ] ;\n\
51 lv2:scalePoint [\n\
52 rdfs:label \"Cos\";\n\
53 rdf:value 4\n\
54 ]\n\
55 ] , [\n\
56 a lv2:EventPort ;\n\
57 a lv2:InputPort ;\n\
58 lv2:index 1 ;\n\
59 lv2:symbol \"event_in\" ;\n\
60 lv2:name \"Event Input\" ;\n\
61 lv2ev:supportsEvent <http://example.org/event> ;\n\
62 atom:supports <http://example.org/atomEvent>\n\
63 ] , [\n\
64 a lv2:AudioPort ;\n\
65 a lv2:InputPort ;\n\
66 lv2:index 2 ;\n\
67 lv2:symbol \"audio_in\" ;\n\
68 lv2:name \"Audio Input\" ;\n\
69 ] , [\n\
70 a lv2:AudioPort ;\n\
71 a lv2:OutputPort ;\n\
72 lv2:index 3 ;\n\
73 lv2:symbol \"audio_out\" ;\n\
74 lv2:name \"Audio Output\" ;\n\
75 ] .\n";
76
77 int
main(void)78 main(void)
79 {
80 LilvTestEnv* const env = lilv_test_env_new();
81 LilvWorld* const world = env->world;
82
83 if (start_bundle(env, SIMPLE_MANIFEST_TTL, plugin_ttl)) {
84 return 1;
85 }
86
87 const LilvPlugins* plugins = lilv_world_get_all_plugins(world);
88 const LilvPlugin* plug = lilv_plugins_get_by_uri(plugins, env->plugin1_uri);
89 assert(plug);
90
91 LilvNode* psym = lilv_new_string(world, "foo");
92 const LilvPort* p = lilv_plugin_get_port_by_index(plug, 0);
93 const LilvPort* p2 = lilv_plugin_get_port_by_symbol(plug, psym);
94 lilv_node_free(psym);
95 assert(p != NULL);
96 assert(p2 != NULL);
97 assert(p == p2);
98
99 LilvNode* nopsym = lilv_new_string(world, "thisaintnoportfoo");
100 const LilvPort* p3 = lilv_plugin_get_port_by_symbol(plug, nopsym);
101 assert(p3 == NULL);
102 lilv_node_free(nopsym);
103
104 // Try getting an invalid property
105 LilvNode* num = lilv_new_int(world, 1);
106 LilvNodes* nothing = lilv_port_get_value(plug, p, num);
107 assert(!nothing);
108 lilv_node_free(num);
109
110 LilvNode* audio_class =
111 lilv_new_uri(world, "http://lv2plug.in/ns/lv2core#AudioPort");
112 LilvNode* control_class =
113 lilv_new_uri(world, "http://lv2plug.in/ns/lv2core#ControlPort");
114 LilvNode* in_class =
115 lilv_new_uri(world, "http://lv2plug.in/ns/lv2core#InputPort");
116 LilvNode* out_class =
117 lilv_new_uri(world, "http://lv2plug.in/ns/lv2core#OutputPort");
118
119 assert(lilv_nodes_size(lilv_port_get_classes(plug, p)) == 2);
120 assert(lilv_plugin_get_num_ports(plug) == 4);
121 assert(lilv_port_is_a(plug, p, control_class));
122 assert(lilv_port_is_a(plug, p, in_class));
123 assert(!lilv_port_is_a(plug, p, audio_class));
124
125 LilvNodes* port_properties = lilv_port_get_properties(plug, p);
126 assert(lilv_nodes_size(port_properties) == 1);
127 lilv_nodes_free(port_properties);
128
129 // Untranslated name (current locale is set to "C" in main)
130 assert(!strcmp(lilv_node_as_string(lilv_port_get_symbol(plug, p)), "foo"));
131 LilvNode* name = lilv_port_get_name(plug, p);
132 assert(!strcmp(lilv_node_as_string(name), "store"));
133 lilv_node_free(name);
134
135 // Exact language match
136 set_env("LANG", "de_DE");
137 name = lilv_port_get_name(plug, p);
138 assert(!strcmp(lilv_node_as_string(name), "Laden"));
139 lilv_node_free(name);
140
141 // Exact language match (with charset suffix)
142 set_env("LANG", "de_AT.utf8");
143 name = lilv_port_get_name(plug, p);
144 assert(!strcmp(lilv_node_as_string(name), "Geschaeft"));
145 lilv_node_free(name);
146
147 // Partial language match (choose value translated for different country)
148 set_env("LANG", "de_CH");
149 name = lilv_port_get_name(plug, p);
150 assert((!strcmp(lilv_node_as_string(name), "Laden")) ||
151 (!strcmp(lilv_node_as_string(name), "Geschaeft")));
152 lilv_node_free(name);
153
154 // Partial language match (choose country-less language tagged value)
155 set_env("LANG", "es_MX");
156 name = lilv_port_get_name(plug, p);
157 assert(!strcmp(lilv_node_as_string(name), "tienda"));
158 lilv_node_free(name);
159
160 // No language match (choose untranslated value)
161 set_env("LANG", "cn");
162 name = lilv_port_get_name(plug, p);
163 assert(!strcmp(lilv_node_as_string(name), "store"));
164 lilv_node_free(name);
165
166 // Invalid language
167 set_env("LANG", "1!");
168 name = lilv_port_get_name(plug, p);
169 assert(!strcmp(lilv_node_as_string(name), "store"));
170 lilv_node_free(name);
171
172 set_env("LANG", "en_CA.utf-8");
173
174 // Language tagged value with no untranslated values
175 LilvNode* rdfs_comment = lilv_new_uri(world, LILV_NS_RDFS "comment");
176 LilvNodes* comments = lilv_port_get_value(plug, p, rdfs_comment);
177 assert(
178 !strcmp(lilv_node_as_string(lilv_nodes_get_first(comments)), "comment"));
179 LilvNode* comment = lilv_port_get(plug, p, rdfs_comment);
180 assert(!strcmp(lilv_node_as_string(comment), "comment"));
181 lilv_node_free(comment);
182 lilv_nodes_free(comments);
183
184 set_env("LANG", "fr");
185
186 comments = lilv_port_get_value(plug, p, rdfs_comment);
187 assert(!strcmp(lilv_node_as_string(lilv_nodes_get_first(comments)),
188 "commentaires"));
189 lilv_nodes_free(comments);
190
191 set_env("LANG", "cn");
192
193 comments = lilv_port_get_value(plug, p, rdfs_comment);
194 assert(!comments);
195 lilv_nodes_free(comments);
196
197 lilv_node_free(rdfs_comment);
198
199 set_env("LANG", "C"); // Reset locale
200
201 LilvScalePoints* points = lilv_port_get_scale_points(plug, p);
202 assert(lilv_scale_points_size(points) == 2);
203
204 LilvIter* sp_iter = lilv_scale_points_begin(points);
205 const LilvScalePoint* sp0 = lilv_scale_points_get(points, sp_iter);
206 assert(sp0);
207 sp_iter = lilv_scale_points_next(points, sp_iter);
208 const LilvScalePoint* sp1 = lilv_scale_points_get(points, sp_iter);
209 assert(sp1);
210
211 assert(
212 ((!strcmp(lilv_node_as_string(lilv_scale_point_get_label(sp0)), "Sin") &&
213 lilv_node_as_float(lilv_scale_point_get_value(sp0)) == 3) &&
214 (!strcmp(lilv_node_as_string(lilv_scale_point_get_label(sp1)), "Cos") &&
215 lilv_node_as_float(lilv_scale_point_get_value(sp1)) == 4)) ||
216 ((!strcmp(lilv_node_as_string(lilv_scale_point_get_label(sp0)), "Cos") &&
217 lilv_node_as_float(lilv_scale_point_get_value(sp0)) == 4) &&
218 (!strcmp(lilv_node_as_string(lilv_scale_point_get_label(sp1)), "Sin") &&
219 lilv_node_as_float(lilv_scale_point_get_value(sp1)) == 3)));
220
221 LilvNode* homepage_p =
222 lilv_new_uri(world, "http://usefulinc.com/ns/doap#homepage");
223 LilvNodes* homepages = lilv_plugin_get_value(plug, homepage_p);
224 assert(lilv_nodes_size(homepages) == 1);
225 assert(!strcmp(lilv_node_as_string(lilv_nodes_get_first(homepages)),
226 "http://example.org/someplug"));
227
228 LilvNode* min = NULL;
229 LilvNode* max = NULL;
230 LilvNode* def = NULL;
231 lilv_port_get_range(plug, p, &def, &min, &max);
232 assert(def);
233 assert(min);
234 assert(max);
235 assert(lilv_node_as_float(def) == 0.5);
236 assert(lilv_node_as_float(min) == -1.0);
237 assert(lilv_node_as_float(max) == 1.0);
238
239 LilvNode* integer_prop =
240 lilv_new_uri(world, "http://lv2plug.in/ns/lv2core#integer");
241 LilvNode* toggled_prop =
242 lilv_new_uri(world, "http://lv2plug.in/ns/lv2core#toggled");
243
244 assert(lilv_port_has_property(plug, p, integer_prop));
245 assert(!lilv_port_has_property(plug, p, toggled_prop));
246
247 const LilvPort* ep = lilv_plugin_get_port_by_index(plug, 1);
248
249 LilvNode* event_type = lilv_new_uri(world, "http://example.org/event");
250 LilvNode* event_type_2 = lilv_new_uri(world, "http://example.org/otherEvent");
251 LilvNode* atom_event = lilv_new_uri(world, "http://example.org/atomEvent");
252 assert(lilv_port_supports_event(plug, ep, event_type));
253 assert(!lilv_port_supports_event(plug, ep, event_type_2));
254 assert(lilv_port_supports_event(plug, ep, atom_event));
255
256 LilvNode* name_p = lilv_new_uri(world, "http://lv2plug.in/ns/lv2core#name");
257 LilvNodes* names = lilv_port_get_value(plug, p, name_p);
258 assert(lilv_nodes_size(names) == 1);
259 assert(!strcmp(lilv_node_as_string(lilv_nodes_get_first(names)), "store"));
260 lilv_nodes_free(names);
261
262 LilvNode* true_val = lilv_new_bool(world, true);
263 LilvNode* false_val = lilv_new_bool(world, false);
264
265 assert(!lilv_node_equals(true_val, false_val));
266
267 lilv_world_set_option(world, LILV_OPTION_FILTER_LANG, false_val);
268 names = lilv_port_get_value(plug, p, name_p);
269 assert(lilv_nodes_size(names) == 4);
270 lilv_nodes_free(names);
271 lilv_world_set_option(world, LILV_OPTION_FILTER_LANG, true_val);
272
273 lilv_node_free(false_val);
274 lilv_node_free(true_val);
275
276 names = lilv_port_get_value(plug, ep, name_p);
277 assert(lilv_nodes_size(names) == 1);
278 assert(
279 !strcmp(lilv_node_as_string(lilv_nodes_get_first(names)), "Event Input"));
280
281 const LilvPort* ap_in = lilv_plugin_get_port_by_index(plug, 2);
282
283 assert(lilv_port_is_a(plug, ap_in, in_class));
284 assert(!lilv_port_is_a(plug, ap_in, out_class));
285 assert(lilv_port_is_a(plug, ap_in, audio_class));
286 assert(!lilv_port_is_a(plug, ap_in, control_class));
287
288 const LilvPort* ap_out = lilv_plugin_get_port_by_index(plug, 3);
289
290 assert(lilv_port_is_a(plug, ap_out, out_class));
291 assert(!lilv_port_is_a(plug, ap_out, in_class));
292 assert(lilv_port_is_a(plug, ap_out, audio_class));
293 assert(!lilv_port_is_a(plug, ap_out, control_class));
294
295 assert(lilv_plugin_get_num_ports_of_class(
296 plug, control_class, in_class, NULL) == 1);
297 assert(
298 lilv_plugin_get_num_ports_of_class(plug, audio_class, in_class, NULL) == 1);
299 assert(lilv_plugin_get_num_ports_of_class(
300 plug, audio_class, out_class, NULL) == 1);
301
302 lilv_nodes_free(names);
303 lilv_node_free(name_p);
304
305 lilv_node_free(integer_prop);
306 lilv_node_free(toggled_prop);
307 lilv_node_free(event_type);
308 lilv_node_free(event_type_2);
309 lilv_node_free(atom_event);
310
311 lilv_node_free(min);
312 lilv_node_free(max);
313 lilv_node_free(def);
314
315 lilv_node_free(homepage_p);
316 lilv_nodes_free(homepages);
317
318 lilv_scale_points_free(points);
319 lilv_node_free(control_class);
320 lilv_node_free(audio_class);
321 lilv_node_free(out_class);
322 lilv_node_free(in_class);
323
324 delete_bundle(env);
325 lilv_test_env_free(env);
326
327 return 0;
328 }
329