1 /*
2  * Copyright (c) 2016-2021 Hanspeter Portner (dev@open-music-kontrollers.ch)
3  *
4  * This is free software: you can redistribute it and/or modify
5  * it under the terms of the Artistic License 2.0 as published by
6  * The Perl Foundation.
7  *
8  * This source is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * Artistic License 2.0 for more details.
12  *
13  * You should have received a copy of the Artistic License 2.0
14  * along the source as a COPYING file. If not, obtain it from
15  * http://www.perlfoundation.org/artistic_license_2_0.
16  */
17 
18 #ifndef _LV2LINT_H
19 #define _LV2LINT_H
20 
21 #include <unistd.h> // isatty
22 #include <string.h>
23 #include <stdlib.h>
24 
25 #include <lilv/lilv.h>
26 
27 #include <lv2/worker/worker.h>
28 #include <lv2/state/state.h>
29 #include <lv2/options/options.h>
30 #include <lv2/ui/ui.h>
31 #include <lv2/midi/midi.h>
32 #include <lv2/time/time.h>
33 #include <lv2/presets/presets.h>
34 #include <lv2/uri-map/uri-map.h>
35 
36 #include <ardour.lv2/lv2_extensions.h>
37 #include <kx.lv2/lv2_external_ui.h>
38 #include <kx.lv2/lv2_programs.h>
39 #include <kx.lv2/lv2_rtmempool.h>
40 
41 #ifdef ENABLE_ONLINE_TESTS
42 #	include <curl/curl.h>
43 #endif
44 
45 #ifndef __unused
46 #	define __unused __attribute__((unused))
47 #endif
48 
49 #ifndef LV2_UI__makeSONameResident
50 #	define LV2_UI__makeSONameResident          LV2_UI_PREFIX "makeSONameResident"
51 #endif
52 
53 #define NODE(APP, ID) (APP)->nodes[ID]
54 
55 typedef enum _ansi_color_t {
56 	ANSI_COLOR_BOLD,
57 	ANSI_COLOR_RED,
58 	ANSI_COLOR_GREEN,
59 	ANSI_COLOR_YELLOW,
60 	ANSI_COLOR_BLUE,
61 	ANSI_COLOR_MAGENTA,
62 	ANSI_COLOR_CYAN,
63 	ANSI_COLOR_RESET,
64 
65 	ANSI_COLOR_MAX
66 } ansi_color_t;
67 
68 extern const char *colors [2][ANSI_COLOR_MAX];
69 
70 typedef union _var_t var_t;
71 typedef struct _white_t white_t;
72 typedef struct _urid_t urid_t;
73 typedef struct _app_t app_t;
74 typedef struct _test_t test_t;
75 typedef struct _ret_t ret_t;
76 typedef struct _res_t res_t;
77 typedef const ret_t *(*test_cb_t)(app_t *app);
78 
79 typedef enum _lint_t {
80 	LINT_NONE     = 0,
81 	LINT_NOTE     = (1 << 1),
82 	LINT_WARN     = (1 << 2),
83 	LINT_FAIL     = (1 << 3),
84 	LINT_PASS     = (1 << 4)
85 } lint_t;
86 
87 struct _white_t {
88 	const char *uri;
89 	const char *pattern;
90 	white_t *next;
91 };
92 
93 struct _urid_t {
94 	char *uri;
95 };
96 
97 struct _ret_t {
98 	lint_t lnt;
99 	lint_t pck;
100 	const char *msg;
101 	const char *uri;
102 	const char *dsc;
103 };
104 
105 struct _res_t {
106 	const ret_t *ret;
107 	char *urn;
108 	bool is_whitelisted;
109 };
110 
111 union _var_t {
112 	uint32_t u32;
113 	int32_t i32;
114 	int64_t i64;
115 	float f32;
116 	double f64;
117 };
118 
119 typedef enum _stat_urid_t {
120 	STAT_URID_INVALID = 0,
121 
122 	RDFS__label,
123 	RDFS__comment,
124 	RDFS__range,
125 	RDFS__subClassOf,
126 
127 	RDF__type,
128 	RDF__value,
129 
130 	DOAP__description,
131 	DOAP__license,
132 	DOAP__name,
133 	DOAP__shortdesc,
134 
135 	XSD__int,
136 	XSD__nonNegativeInteger,
137 	XSD__long,
138 	XSD__float,
139 	XSD__double,
140 
141 	ATOM__Atom,
142 	ATOM__AtomPort,
143 	ATOM__Blank,
144 	ATOM__Bool,
145 	ATOM__Chunk,
146 	ATOM__Double,
147 	ATOM__Event,
148 	ATOM__Float,
149 	ATOM__Int,
150 	ATOM__Literal,
151 	ATOM__Long,
152 	ATOM__Number,
153 	ATOM__Object,
154 	ATOM__Path,
155 	ATOM__Property,
156 	ATOM__Resource,
157 	ATOM__Sequence,
158 	ATOM__Sound,
159 	ATOM__String,
160 	ATOM__Tuple,
161 	ATOM__URI,
162 	ATOM__URID,
163 	ATOM__Vector,
164 	ATOM__atomTransfer,
165 	ATOM__beatTime,
166 	ATOM__bufferType,
167 	ATOM__childType,
168 	ATOM__eventTransfer,
169 	ATOM__frameTime,
170 	ATOM__supports,
171 	ATOM__timeUnit,
172 
173 	BUF_SIZE__boundedBlockLength,
174 	BUF_SIZE__coarseBlockLength,
175 	BUF_SIZE__fixedBlockLength,
176 	BUF_SIZE__maxBlockLength,
177 	BUF_SIZE__minBlockLength,
178 	BUF_SIZE__nominalBlockLength,
179 	BUF_SIZE__powerOf2BlockLength,
180 	BUF_SIZE__sequenceSize,
181 
182 	CORE__AllpassPlugin,
183 	CORE__AmplifierPlugin,
184 	CORE__AnalyserPlugin,
185 	CORE__AudioPort,
186 	CORE__BandpassPlugin,
187 	CORE__CVPort,
188 	CORE__ChorusPlugin,
189 	CORE__CombPlugin,
190 	CORE__CompressorPlugin,
191 	CORE__ConstantPlugin,
192 	CORE__ControlPort,
193 	CORE__ConverterPlugin,
194 	CORE__DelayPlugin,
195 	CORE__DistortionPlugin,
196 	CORE__DynamicsPlugin,
197 	CORE__EQPlugin,
198 	CORE__EnvelopePlugin,
199 	CORE__ExpanderPlugin,
200 	CORE__ExtensionData,
201 	CORE__Feature,
202 	CORE__FilterPlugin,
203 	CORE__FlangerPlugin,
204 	CORE__FunctionPlugin,
205 	CORE__GatePlugin,
206 	CORE__GeneratorPlugin,
207 	CORE__HighpassPlugin,
208 	CORE__InputPort,
209 	CORE__InstrumentPlugin,
210 	CORE__LimiterPlugin,
211 	CORE__LowpassPlugin,
212 	CORE__MixerPlugin,
213 	CORE__ModulatorPlugin,
214 	CORE__MultiEQPlugin,
215 	CORE__OscillatorPlugin,
216 	CORE__OutputPort,
217 	CORE__ParaEQPlugin,
218 	CORE__PhaserPlugin,
219 	CORE__PitchPlugin,
220 	CORE__Plugin,
221 	CORE__PluginBase,
222 	CORE__Point,
223 	CORE__Port,
224 	CORE__PortProperty,
225 	CORE__Resource,
226 	CORE__ReverbPlugin,
227 	CORE__ScalePoint,
228 	CORE__SimulatorPlugin,
229 	CORE__SpatialPlugin,
230 	CORE__Specification,
231 	CORE__SpectralPlugin,
232 	CORE__UtilityPlugin,
233 	CORE__WaveshaperPlugin,
234 	CORE__appliesTo,
235 	CORE__binary,
236 	CORE__connectionOptional,
237 	CORE__control,
238 	CORE__default,
239 	CORE__designation,
240 	CORE__documentation,
241 	CORE__enumeration,
242 	CORE__extensionData,
243 	CORE__freeWheeling,
244 	CORE__hardRTCapable,
245 	CORE__inPlaceBroken,
246 	CORE__index,
247 	CORE__integer,
248 	CORE__isLive,
249 	CORE__latency,
250 	CORE__maximum,
251 	CORE__microVersion,
252 	CORE__minimum,
253 	CORE__minorVersion,
254 	CORE__name,
255 	CORE__optionalFeature,
256 	CORE__port,
257 	CORE__portProperty,
258 	CORE__project,
259 	CORE__prototype,
260 	CORE__reportsLatency,
261 	CORE__requiredFeature,
262 	CORE__sampleRate,
263 	CORE__scalePoint,
264 	CORE__symbol,
265 	CORE__toggled,
266 
267 	DATA_ACCESS,
268 
269 	DYN_MANIFEST,
270 
271 	EVENT__Event,
272 	EVENT__EventPort,
273 	EVENT__FrameStamp,
274 	EVENT__TimeStamp,
275 	EVENT__generatesTimeStamp,
276 	EVENT__generic,
277 	EVENT__inheritsEvent,
278 	EVENT__inheritsTimeStamp,
279 	EVENT__supportsEvent,
280 	EVENT__supportsTimeStamp,
281 
282 	INSTANCE_ACCESS,
283 
284 	LOG__Entry,
285 	LOG__Error,
286 	LOG__Note,
287 	LOG__Trace,
288 	LOG__Warning,
289 	LOG__log,
290 
291 	MIDI__ActiveSense,
292 	MIDI__Aftertouch,
293 	MIDI__Bender,
294 	MIDI__ChannelPressure,
295 	MIDI__Chunk,
296 	MIDI__Clock,
297 	MIDI__Continue,
298 	MIDI__Controller,
299 	MIDI__MidiEvent,
300 	MIDI__NoteOff,
301 	MIDI__NoteOn,
302 	MIDI__ProgramChange,
303 	MIDI__QuarterFrame,
304 	MIDI__Reset,
305 	MIDI__SongPosition,
306 	MIDI__SongSelect,
307 	MIDI__Start,
308 	MIDI__Stop,
309 	MIDI__SystemCommon,
310 	MIDI__SystemExclusive,
311 	MIDI__SystemMessage,
312 	MIDI__SystemRealtime,
313 	MIDI__Tick,
314 	MIDI__TuneRequest,
315 	MIDI__VoiceMessage,
316 	MIDI__benderValue,
317 	MIDI__binding,
318 	MIDI__byteNumber,
319 	MIDI__channel,
320 	MIDI__chunk,
321 	MIDI__controllerNumber,
322 	MIDI__controllerValue,
323 	MIDI__noteNumber,
324 	MIDI__pressure,
325 	MIDI__programNumber,
326 	MIDI__property,
327 	MIDI__songNumber,
328 	MIDI__songPosition,
329 	MIDI__status,
330 	MIDI__statusMask,
331 	MIDI__velocity,
332 
333 	MORPH__AutoMorphPort,
334 	MORPH__MorphPort,
335 	MORPH__interface,
336 	MORPH__supportsType,
337 	MORPH__currentType,
338 
339 	OPTIONS__Option,
340 	OPTIONS__interface,
341 	OPTIONS__options,
342 	OPTIONS__requiredOption,
343 	OPTIONS__supportedOption,
344 
345 	PARAMETERS__CompressorControls,
346 	PARAMETERS__ControlGroup,
347 	PARAMETERS__EnvelopeControls,
348 	PARAMETERS__FilterControls,
349 	PARAMETERS__OscillatorControls,
350 	PARAMETERS__amplitude,
351 	PARAMETERS__attack,
352 	PARAMETERS__bypass,
353 	PARAMETERS__cutoffFrequency,
354 	PARAMETERS__decay,
355 	PARAMETERS__delay,
356 	PARAMETERS__dryLevel,
357 	PARAMETERS__frequency,
358 	PARAMETERS__gain,
359 	PARAMETERS__hold,
360 	PARAMETERS__pulseWidth,
361 	PARAMETERS__ratio,
362 	PARAMETERS__release,
363 	PARAMETERS__resonance,
364 	PARAMETERS__sampleRate,
365 	PARAMETERS__sustain,
366 	PARAMETERS__threshold,
367 	PARAMETERS__waveform,
368 	PARAMETERS__wetDryRatio,
369 	PARAMETERS__wetLevel,
370 
371 	PATCH__Ack,
372 	PATCH__Delete,
373 	PATCH__Copy,
374 	PATCH__Error,
375 	PATCH__Get,
376 	PATCH__Message,
377 	PATCH__Move,
378 	PATCH__Patch,
379 	PATCH__Post,
380 	PATCH__Put,
381 	PATCH__Request,
382 	PATCH__Response,
383 	PATCH__Set,
384 	PATCH__accept,
385 	PATCH__add,
386 	PATCH__body,
387 	PATCH__context,
388 	PATCH__destination,
389 	PATCH__property,
390 	PATCH__readable,
391 	PATCH__remove,
392 	PATCH__request,
393 	PATCH__subject,
394 	PATCH__sequenceNumber,
395 	PATCH__value,
396 	PATCH__wildcard,
397 	PATCH__writable,
398 
399 	PORT_GROUPS__DiscreteGroup,
400 	PORT_GROUPS__Element,
401 	PORT_GROUPS__FivePointOneGroup,
402 	PORT_GROUPS__FivePointZeroGroup,
403 	PORT_GROUPS__FourPointZeroGroup,
404 	PORT_GROUPS__Group,
405 	PORT_GROUPS__InputGroup,
406 	PORT_GROUPS__MidSideGroup,
407 	PORT_GROUPS__MonoGroup,
408 	PORT_GROUPS__OutputGroup,
409 	PORT_GROUPS__SevenPointOneGroup,
410 	PORT_GROUPS__SevenPointOneWideGroup,
411 	PORT_GROUPS__SixPointOneGroup,
412 	PORT_GROUPS__StereoGroup,
413 	PORT_GROUPS__ThreePointZeroGroup,
414 	PORT_GROUPS__center,
415 	PORT_GROUPS__centerLeft,
416 	PORT_GROUPS__centerRight,
417 	PORT_GROUPS__element,
418 	PORT_GROUPS__group,
419 	PORT_GROUPS__left,
420 	PORT_GROUPS__lowFrequencyEffects,
421 	PORT_GROUPS__mainInput,
422 	PORT_GROUPS__mainOutput,
423 	PORT_GROUPS__rearCenter,
424 	PORT_GROUPS__rearLeft,
425 	PORT_GROUPS__rearRight,
426 	PORT_GROUPS__right,
427 	PORT_GROUPS__side,
428 	PORT_GROUPS__sideChainOf,
429 	PORT_GROUPS__sideLeft,
430 	PORT_GROUPS__sideRight,
431 	PORT_GROUPS__source,
432 	PORT_GROUPS__subGroupOf,
433 
434 	PORT_PROPS__causesArtifacts,
435 	PORT_PROPS__continuousCV,
436 	PORT_PROPS__discreteCV,
437 	PORT_PROPS__displayPriority,
438 	PORT_PROPS__expensive,
439 	PORT_PROPS__hasStrictBounds,
440 	PORT_PROPS__logarithmic,
441 	PORT_PROPS__notAutomatic,
442 	PORT_PROPS__notOnGUI,
443 	PORT_PROPS__rangeSteps,
444 	PORT_PROPS__supportsStrictBounds,
445 	PORT_PROPS__trigger,
446 
447 	PRESETS__Bank,
448 	PRESETS__Preset,
449 	PRESETS__bank,
450 	PRESETS__preset,
451 	PRESETS__value,
452 
453 	RESIZE_PORT__asLargeAs,
454 	RESIZE_PORT__minimumSize,
455 	RESIZE_PORT__resize,
456 
457 	STATE__State,
458 	STATE__interface,
459 	STATE__loadDefaultState,
460 	STATE__freePath,
461 	STATE__makePath,
462 	STATE__mapPath,
463 	STATE__state,
464 	STATE__threadSafeRestore,
465 	STATE__StateChanged,
466 
467 	TIME__Time,
468 	TIME__Position,
469 	TIME__Rate,
470 	TIME__position,
471 	TIME__barBeat,
472 	TIME__bar,
473 	TIME__beat,
474 	TIME__beatUnit,
475 	TIME__beatsPerBar,
476 	TIME__beatsPerMinute,
477 	TIME__frame,
478 	TIME__framesPerSecond,
479 	TIME__speed,
480 
481 	UI__CocoaUI,
482 	UI__Gtk3UI,
483 	UI__GtkUI,
484 	UI__PortNotification,
485 	UI__PortProtocol,
486 	UI__Qt4UI,
487 	UI__Qt5UI,
488 	UI__UI,
489 	UI__WindowsUI,
490 	UI__X11UI,
491 	UI__binary,
492 	UI__fixedSize,
493 	UI__idleInterface,
494 	UI__noUserResize,
495 	UI__notifyType,
496 	UI__parent,
497 	UI__plugin,
498 	UI__portIndex,
499 	UI__portMap,
500 	UI__portNotification,
501 	UI__portSubscribe,
502 	UI__protocol,
503 	UI__requestValue,
504 	UI__floatProtocol,
505 	UI__peakProtocol,
506 	UI__resize,
507 	UI__showInterface,
508 	UI__touch,
509 	UI__ui,
510 	UI__updateRate,
511 	UI__windowTitle,
512 	UI__scaleFactor,
513 	UI__foregroundColor,
514 	UI__backgroundColor,
515 	UI__makeSONameResident,
516 
517 	UNITS__Conversion,
518 	UNITS__Unit,
519 	UNITS__bar,
520 	UNITS__beat,
521 	UNITS__bpm,
522 	UNITS__cent,
523 	UNITS__cm,
524 	UNITS__coef,
525 	UNITS__conversion,
526 	UNITS__db,
527 	UNITS__degree,
528 	UNITS__frame,
529 	UNITS__hz,
530 	UNITS__inch,
531 	UNITS__khz,
532 	UNITS__km,
533 	UNITS__m,
534 	UNITS__mhz,
535 	UNITS__midiNote,
536 	UNITS__mile,
537 	UNITS__min,
538 	UNITS__mm,
539 	UNITS__ms,
540 	UNITS__name,
541 	UNITS__oct,
542 	UNITS__pc,
543 	UNITS__prefixConversion,
544 	UNITS__render,
545 	UNITS__s,
546 	UNITS__semitone12TET,
547 	UNITS__symbol,
548 	UNITS__unit,
549 
550 	URID__map,
551 	URID__unmap,
552 
553 	URI_MAP,
554 
555 	WORKER__interface,
556 	WORKER__schedule,
557 
558 	EXTERNAL_UI__Widget,
559 
560 	INLINEDISPLAY__interface,
561 	INLINEDISPLAY__queue_draw,
562 
563 	STAT_URID_MAX
564 } stat_urid_t;
565 
566 struct _app_t {
567 	LilvWorld *world;
568 	const char *plugin_uri;
569 	const LilvPlugin *plugin;
570 	LilvInstance *instance;
571 	const LV2_Descriptor *descriptor;
572 	const LV2UI_Descriptor *ui_descriptor;
573 	const LilvPort *port;
574 	const LilvNode *parameter;
575 	const LilvUI *ui;
576 	const char *ui_uri;
577 	LV2_URID_Map *map;
578 	LV2_URID_Unmap *unmap;
579 	void *ui_instance;
580 	uintptr_t ui_widget;
581 	LilvNodes *writables;
582 	LilvNodes *readables;
583 	const LV2_Worker_Interface *work_iface;
584 	const LV2_Inline_Display_Interface *idisp_iface;
585 	const LV2_State_Interface *state_iface;
586 	const LV2_Options_Interface *opts_iface;
587 	const LV2UI_Idle_Interface *ui_idle_iface;
588 	const LV2UI_Show_Interface *ui_show_iface;
589 	const LV2UI_Resize *ui_resize_iface;
590 	var_t min;
591 	var_t max;
592 	var_t dflt;
593 	lint_t show;
594 	lint_t mask;
595 	bool pck;
596 	urid_t *urids;
597 	LV2_URID nurids;
598 	char **urn;
599 	unsigned n_include_dirs;
600 	char **include_dirs;
601 	white_t *whitelist_symbols;
602 	white_t *whitelist_libs;
603 	white_t *whitelist_tests;
604 	bool atty;
605 	bool debug;
606 	bool quiet;
607 #ifdef ENABLE_ONLINE_TESTS
608 	bool online;
609 	char *mail;
610 	bool mailto;
611 	CURL *curl;
612 	char *greet;
613 #endif
614 	LilvNode *nodes [STAT_URID_MAX];
615 };
616 
617 struct _test_t {
618 	const char *id;
619 	test_cb_t cb;
620 };
621 
622 bool
623 test_plugin(app_t *app);
624 
625 bool
626 test_port(app_t *app);
627 
628 bool
629 test_parameter(app_t *app);
630 
631 bool
632 test_ui(app_t *app);
633 
634 #ifdef ENABLE_X11_TESTS
635 void
636 test_x11(app_t *app, bool *flag);
637 #endif
638 
639 #ifdef ENABLE_ONLINE_TESTS
640 bool
641 is_url(const char *uri);
642 
643 bool
644 test_url(app_t *app, const char *url);
645 #endif
646 
647 #ifdef ENABLE_ELF_TESTS
648 bool
649 test_visibility(app_t *app, const char *path, const char *uri,
650 	const char *description, char **symbols);
651 
652 bool
653 check_for_symbol(app_t *app, const char *path, const char *description);
654 
655 bool
656 test_shared_libraries(app_t *app, const char *path, const char *uri,
657 	const char *const *whitelist, unsigned n_whitelist,
658 	const char *const *blacklist, unsigned n_blacklist,
659 	char **libraries);
660 #endif
661 
662 int
663 lv2lint_vprintf(app_t *app, const char *fmt, va_list args);
664 
665 int
666 lv2lint_printf(app_t *app, const char *fmt, ...);
667 
668 void
669 lv2lint_report(app_t *app, const test_t *test, res_t *res, bool show_passes, bool *flag);
670 
671 lint_t
672 lv2lint_extract(app_t *app, const ret_t *ret);
673 
674 bool
675 lv2lint_test_is_whitelisted(app_t *app, const char *uri, const test_t *test);
676 
677 char *
678 lv2lint_node_as_string_strdup(const LilvNode *node);
679 
680 char *
681 lv2lint_node_as_uri_strdup(const LilvNode *node);
682 
683 char *
684 lv2lint_strdup(const char *str);
685 
686 int
687 log_vprintf(void *data, LV2_URID type , const char *fmt, va_list args);
688 
689 int
690 log_printf(void *data, LV2_URID type, const char *fmt, ...);
691 
692 #pragma GCC diagnostic push
693 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
694 uint32_t
695 uri_to_id(LV2_URI_Map_Callback_Data instance, const char *_map, const char *uri);
696 #pragma GCC diagnostic pop
697 
698 #endif
699