1 /*
2  * Carla Plugin discovery
3  * Copyright (C) 2011-2020 Filipe Coelho <falktx@falktx.com>
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License as
7  * published by the Free Software Foundation; either version 2 of
8  * the License, or any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * For a full copy of the GNU General Public License see the doc/GPL.txt file.
16  */
17 
18 #include "CarlaBackendUtils.hpp"
19 #include "CarlaLibUtils.hpp"
20 #include "CarlaMathUtils.hpp"
21 #include "CarlaMIDI.h"
22 #include "LinkedList.hpp"
23 
24 #ifdef BUILD_BRIDGE
25 # undef HAVE_FLUIDSYNTH
26 #endif
27 
28 #ifdef USING_JUCE
29 # if defined(__clang__)
30 #  pragma clang diagnostic push
31 #  pragma clang diagnostic ignored "-Wfloat-equal"
32 #  pragma clang diagnostic ignored "-Wimplicit-int-float-conversion"
33 # elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
34 #  pragma GCC diagnostic push
35 #  pragma GCC diagnostic ignored "-Wconversion"
36 #  pragma GCC diagnostic ignored "-Wdouble-promotion"
37 #  pragma GCC diagnostic ignored "-Weffc++"
38 #  pragma GCC diagnostic ignored "-Wfloat-equal"
39 # endif
40 # include "../backend/utils/JUCE.cpp"
41 # include "AppConfig.h"
42 # include "juce_audio_processors/juce_audio_processors.h"
43 # if JUCE_PLUGINHOST_VST
44 #  define USING_JUCE_FOR_VST2
45 # endif
46 # if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
47 #  pragma GCC diagnostic pop
48 # endif
49 #endif
50 
51 #include "CarlaLadspaUtils.hpp"
52 #include "CarlaLv2Utils.hpp"
53 
54 #ifndef USING_JUCE_FOR_VST2
55 # include "CarlaVst2Utils.hpp"
56 #endif
57 
58 #ifdef CARLA_OS_MAC
59 # define Component CocoaComponent
60 # define MemoryBlock CocoaMemoryBlock
61 # define Point CocoaPoint
62 # import <Foundation/Foundation.h>
63 # undef Component
64 # undef MemoryBlock
65 # undef Point
66 # include "CarlaMacUtils.cpp"
67 # include <spawn.h>
68 # if defined(USING_JUCE) && defined(__aarch64__)
69 #  include <spawn.h>
70 # endif
71 #endif
72 
73 #ifdef CARLA_OS_WIN
74 # include <pthread.h>
75 # include <objbase.h>
76 #endif
77 
78 #ifdef HAVE_FLUIDSYNTH
79 # include <fluidsynth.h>
80 #endif
81 
82 #include <iostream>
83 
84 #include "water/files/File.h"
85 
86 #ifndef BUILD_BRIDGE
87 # include "water/text/StringArray.h"
88 # include "CarlaDssiUtils.cpp"
89 # include "../backend/utils/CachedPlugins.cpp"
90 #else
91 # include "CarlaDssiUtils.hpp"
92 #endif
93 
94 #define DISCOVERY_OUT(x, y) std::cout << "\ncarla-discovery::" << x << "::" << y << std::endl;
95 
96 using water::CharPointer_UTF8;
97 using water::File;
98 using water::StringArray;
99 
100 CARLA_BACKEND_USE_NAMESPACE
101 
102 // -------------------------------------------------------------------------------------------------------------------
103 // Dummy values to test plugins with
104 
105 static const uint32_t kBufferSize  = 512;
106 static const double   kSampleRate  = 44100.0;
107 static const int32_t  kSampleRatei = 44100;
108 static const float    kSampleRatef = 44100.0f;
109 
110 // -------------------------------------------------------------------------------------------------------------------
111 // Don't print ELF/EXE related errors since discovery can find multi-architecture binaries
112 
print_lib_error(const char * const filename)113 static void print_lib_error(const char* const filename)
114 {
115     const char* const error(lib_error(filename));
116 
117     if (error != nullptr &&
118         std::strstr(error, "wrong ELF class") == nullptr &&
119         std::strstr(error, "invalid ELF header") == nullptr &&
120         std::strstr(error, "Bad EXE format") == nullptr &&
121         std::strstr(error, "no suitable image found") == nullptr &&
122         std::strstr(error, "not a valid Win32 application") == nullptr)
123     {
124         DISCOVERY_OUT("error", error);
125     }
126 }
127 
128 // ------------------------------ Plugin Checks -----------------------------
129 
130 #ifndef BUILD_BRIDGE
print_cached_plugin(const CarlaCachedPluginInfo * const pinfo)131 static void print_cached_plugin(const CarlaCachedPluginInfo* const pinfo)
132 {
133     if (! pinfo->valid)
134         return;
135 
136     DISCOVERY_OUT("init", "-----------");
137     DISCOVERY_OUT("build", BINARY_NATIVE);
138     DISCOVERY_OUT("hints", pinfo->hints);
139     DISCOVERY_OUT("category", getPluginCategoryAsString(pinfo->category));
140     DISCOVERY_OUT("name", pinfo->name);
141     DISCOVERY_OUT("maker", pinfo->maker);
142     DISCOVERY_OUT("label", pinfo->label);
143     DISCOVERY_OUT("audio.ins", pinfo->audioIns);
144     DISCOVERY_OUT("audio.outs", pinfo->audioOuts);
145     DISCOVERY_OUT("cv.ins", pinfo->cvIns);
146     DISCOVERY_OUT("cv.outs", pinfo->cvOuts);
147     DISCOVERY_OUT("midi.ins", pinfo->midiIns);
148     DISCOVERY_OUT("midi.outs", pinfo->midiOuts);
149     DISCOVERY_OUT("parameters.ins", pinfo->parameterIns);
150     DISCOVERY_OUT("parameters.outs", pinfo->parameterOuts);
151     DISCOVERY_OUT("end", "------------");
152 }
153 
do_cached_check(const PluginType type)154 static void do_cached_check(const PluginType type)
155 {
156     const char* plugPath;
157 
158     switch (type)
159     {
160     case PLUGIN_LV2:
161         plugPath = std::getenv("LV2_PATH");
162         break;
163     case PLUGIN_SFZ:
164         plugPath = std::getenv("SFZ_PATH");
165         break;
166     default:
167         plugPath = nullptr;
168         break;
169     }
170 
171 # ifdef USING_JUCE
172     if (type == PLUGIN_AU)
173         carla_juce_init();
174 # endif
175 
176     const uint count = carla_get_cached_plugin_count(type, plugPath);
177 
178     for (uint i=0; i<count; ++i)
179     {
180         const CarlaCachedPluginInfo* pinfo(carla_get_cached_plugin_info(type, i));
181         CARLA_SAFE_ASSERT_CONTINUE(pinfo != nullptr);
182 
183         print_cached_plugin(pinfo);
184     }
185 
186 # ifdef USING_JUCE
187     if (type == PLUGIN_AU)
188         carla_juce_cleanup();
189 # endif
190 }
191 #endif
192 
do_ladspa_check(lib_t & libHandle,const char * const filename,const bool doInit)193 static void do_ladspa_check(lib_t& libHandle, const char* const filename, const bool doInit)
194 {
195     LADSPA_Descriptor_Function descFn = lib_symbol<LADSPA_Descriptor_Function>(libHandle, "ladspa_descriptor");
196 
197     if (descFn == nullptr)
198     {
199         DISCOVERY_OUT("error", "Not a LADSPA plugin");
200         return;
201     }
202 
203     const LADSPA_Descriptor* descriptor;
204 
205     {
206         descriptor = descFn(0);
207 
208         if (descriptor == nullptr)
209         {
210             DISCOVERY_OUT("error", "Binary doesn't contain any plugins");
211             return;
212         }
213 
214         if (doInit && descriptor->instantiate != nullptr && descriptor->cleanup != nullptr)
215         {
216             LADSPA_Handle handle = descriptor->instantiate(descriptor, kSampleRatei);
217 
218             if (handle == nullptr)
219             {
220                 DISCOVERY_OUT("error", "Failed to init first LADSPA plugin");
221                 return;
222             }
223 
224             descriptor->cleanup(handle);
225 
226             lib_close(libHandle);
227             libHandle = lib_open(filename);
228 
229             if (libHandle == nullptr)
230             {
231                 print_lib_error(filename);
232                 return;
233             }
234 
235             descFn = lib_symbol<LADSPA_Descriptor_Function>(libHandle, "ladspa_descriptor");
236 
237             if (descFn == nullptr)
238             {
239                 DISCOVERY_OUT("error", "Not a LADSPA plugin (#2)");
240                 return;
241             }
242         }
243     }
244 
245     unsigned long i = 0;
246 
247     while ((descriptor = descFn(i++)) != nullptr)
248     {
249         if (descriptor->instantiate == nullptr)
250         {
251             DISCOVERY_OUT("error", "Plugin '" << descriptor->Name << "' has no instantiate()");
252             continue;
253         }
254         if (descriptor->cleanup == nullptr)
255         {
256             DISCOVERY_OUT("error", "Plugin '" << descriptor->Name << "' has no cleanup()");
257             continue;
258         }
259         if (descriptor->run == nullptr)
260         {
261             DISCOVERY_OUT("error", "Plugin '" << descriptor->Name << "' has no run()");
262             continue;
263         }
264         if (! LADSPA_IS_HARD_RT_CAPABLE(descriptor->Properties))
265         {
266             DISCOVERY_OUT("warning", "Plugin '" << descriptor->Name << "' is not hard real-time capable");
267         }
268 
269         uint hints = 0x0;
270         uint audioIns = 0;
271         uint audioOuts = 0;
272         uint audioTotal = 0;
273         uint parametersIns = 0;
274         uint parametersOuts = 0;
275         uint parametersTotal = 0;
276 
277         if (LADSPA_IS_HARD_RT_CAPABLE(descriptor->Properties))
278             hints |= PLUGIN_IS_RTSAFE;
279 
280         for (unsigned long j=0; j < descriptor->PortCount; ++j)
281         {
282             CARLA_ASSERT(descriptor->PortNames[j] != nullptr);
283             const LADSPA_PortDescriptor portDescriptor = descriptor->PortDescriptors[j];
284 
285             if (LADSPA_IS_PORT_AUDIO(portDescriptor))
286             {
287                 if (LADSPA_IS_PORT_INPUT(portDescriptor))
288                     audioIns += 1;
289                 else if (LADSPA_IS_PORT_OUTPUT(portDescriptor))
290                     audioOuts += 1;
291 
292                 audioTotal += 1;
293             }
294             else if (LADSPA_IS_PORT_CONTROL(portDescriptor))
295             {
296                 if (LADSPA_IS_PORT_INPUT(portDescriptor))
297                     parametersIns += 1;
298                 else if (LADSPA_IS_PORT_OUTPUT(portDescriptor) && std::strcmp(descriptor->PortNames[j], "latency") != 0 && std::strcmp(descriptor->PortNames[j], "_latency") != 0)
299                     parametersOuts += 1;
300 
301                 parametersTotal += 1;
302             }
303         }
304 
305         if (doInit)
306         {
307             // -----------------------------------------------------------------------
308             // start crash-free plugin test
309 
310             LADSPA_Handle handle = descriptor->instantiate(descriptor, kSampleRatei);
311 
312             if (handle == nullptr)
313             {
314                 DISCOVERY_OUT("error", "Failed to init LADSPA plugin");
315                 continue;
316             }
317 
318             // Test quick init and cleanup
319             descriptor->cleanup(handle);
320 
321             handle = descriptor->instantiate(descriptor, kSampleRatei);
322 
323             if (handle == nullptr)
324             {
325                 DISCOVERY_OUT("error", "Failed to init LADSPA plugin (#2)");
326                 continue;
327             }
328 
329             LADSPA_Data bufferAudio[kBufferSize][audioTotal];
330             LADSPA_Data bufferParams[parametersTotal];
331             LADSPA_Data min, max, def;
332 
333             for (unsigned long j=0, iA=0, iC=0; j < descriptor->PortCount; ++j)
334             {
335                 const LADSPA_PortDescriptor portDescriptor = descriptor->PortDescriptors[j];
336                 const LADSPA_PortRangeHint  portRangeHints = descriptor->PortRangeHints[j];
337                 const char* const portName = descriptor->PortNames[j];
338 
339                 if (LADSPA_IS_PORT_AUDIO(portDescriptor))
340                 {
341                     carla_zeroFloats(bufferAudio[iA], kBufferSize);
342                     descriptor->connect_port(handle, j, bufferAudio[iA++]);
343                 }
344                 else if (LADSPA_IS_PORT_CONTROL(portDescriptor))
345                 {
346                     // min value
347                     if (LADSPA_IS_HINT_BOUNDED_BELOW(portRangeHints.HintDescriptor))
348                         min = portRangeHints.LowerBound;
349                     else
350                         min = 0.0f;
351 
352                     // max value
353                     if (LADSPA_IS_HINT_BOUNDED_ABOVE(portRangeHints.HintDescriptor))
354                         max = portRangeHints.UpperBound;
355                     else
356                         max = 1.0f;
357 
358                     if (min > max)
359                     {
360                         DISCOVERY_OUT("warning", "Parameter '" << portName << "' is broken: min > max");
361                         max = min + 0.1f;
362                     }
363                     else if (carla_isEqual(min, max))
364                     {
365                         DISCOVERY_OUT("warning", "Parameter '" << portName << "' is broken: max == min");
366                         max = min + 0.1f;
367                     }
368 
369                     // default value
370                     def = get_default_ladspa_port_value(portRangeHints.HintDescriptor, min, max);
371 
372                     if (LADSPA_IS_HINT_SAMPLE_RATE(portRangeHints.HintDescriptor))
373                     {
374                         min *= kSampleRatef;
375                         max *= kSampleRatef;
376                         def *= kSampleRatef;
377                     }
378 
379                     if (LADSPA_IS_PORT_OUTPUT(portDescriptor) && (std::strcmp(portName, "latency") == 0 || std::strcmp(portName, "_latency") == 0))
380                     {
381                         // latency parameter
382                         def = 0.0f;
383                     }
384                     else
385                     {
386                         if (def < min)
387                             def = min;
388                         else if (def > max)
389                             def = max;
390                     }
391 
392                     bufferParams[iC] = def;
393                     descriptor->connect_port(handle, j, &bufferParams[iC++]);
394                 }
395             }
396 
397             if (descriptor->activate != nullptr)
398                 descriptor->activate(handle);
399 
400             descriptor->run(handle, kBufferSize);
401 
402             if (descriptor->deactivate != nullptr)
403                 descriptor->deactivate(handle);
404 
405             descriptor->cleanup(handle);
406 
407             // end crash-free plugin test
408             // -----------------------------------------------------------------------
409         }
410 
411         DISCOVERY_OUT("init", "-----------");
412         DISCOVERY_OUT("build", BINARY_NATIVE);
413         DISCOVERY_OUT("hints", hints);
414         DISCOVERY_OUT("category", getPluginCategoryAsString(getPluginCategoryFromName(descriptor->Name)));
415         DISCOVERY_OUT("name", descriptor->Name);
416         DISCOVERY_OUT("label", descriptor->Label);
417         DISCOVERY_OUT("maker", descriptor->Maker);
418         DISCOVERY_OUT("uniqueId", descriptor->UniqueID);
419         DISCOVERY_OUT("audio.ins", audioIns);
420         DISCOVERY_OUT("audio.outs", audioOuts);
421         DISCOVERY_OUT("parameters.ins", parametersIns);
422         DISCOVERY_OUT("parameters.outs", parametersOuts);
423         DISCOVERY_OUT("end", "------------");
424     }
425 }
426 
do_dssi_check(lib_t & libHandle,const char * const filename,const bool doInit)427 static void do_dssi_check(lib_t& libHandle, const char* const filename, const bool doInit)
428 {
429     DSSI_Descriptor_Function descFn = lib_symbol<DSSI_Descriptor_Function>(libHandle, "dssi_descriptor");
430 
431     if (descFn == nullptr)
432     {
433         DISCOVERY_OUT("error", "Not a DSSI plugin");
434         return;
435     }
436 
437     const DSSI_Descriptor* descriptor;
438 
439     {
440         descriptor = descFn(0);
441 
442         if (descriptor == nullptr)
443         {
444             DISCOVERY_OUT("error", "Binary doesn't contain any plugins");
445             return;
446         }
447 
448         const LADSPA_Descriptor* const ldescriptor(descriptor->LADSPA_Plugin);
449 
450         if (ldescriptor == nullptr)
451         {
452             DISCOVERY_OUT("error", "DSSI plugin doesn't provide the LADSPA interface");
453             return;
454         }
455 
456         if (doInit && ldescriptor->instantiate != nullptr && ldescriptor->cleanup != nullptr)
457         {
458             LADSPA_Handle handle = ldescriptor->instantiate(ldescriptor, kSampleRatei);
459 
460             if (handle == nullptr)
461             {
462                 DISCOVERY_OUT("error", "Failed to init first LADSPA plugin");
463                 return;
464             }
465 
466             ldescriptor->cleanup(handle);
467 
468             lib_close(libHandle);
469             libHandle = lib_open(filename);
470 
471             if (libHandle == nullptr)
472             {
473                 print_lib_error(filename);
474                 return;
475             }
476 
477             descFn = lib_symbol<DSSI_Descriptor_Function>(libHandle, "dssi_descriptor");
478 
479             if (descFn == nullptr)
480             {
481                 DISCOVERY_OUT("error", "Not a DSSI plugin (#2)");
482                 return;
483             }
484         }
485     }
486 
487     unsigned long i = 0;
488 
489     while ((descriptor = descFn(i++)) != nullptr)
490     {
491         const LADSPA_Descriptor* const ldescriptor = descriptor->LADSPA_Plugin;
492 
493         if (ldescriptor == nullptr)
494         {
495             DISCOVERY_OUT("error", "Plugin has no LADSPA interface");
496             continue;
497         }
498         if (descriptor->DSSI_API_Version != DSSI_VERSION_MAJOR)
499         {
500             DISCOVERY_OUT("error", "Plugin '" << ldescriptor->Name << "' uses an unsupported DSSI spec version " << descriptor->DSSI_API_Version);
501             continue;
502         }
503         if (ldescriptor->instantiate == nullptr)
504         {
505             DISCOVERY_OUT("error", "Plugin '" << ldescriptor->Name << "' has no instantiate()");
506             continue;
507         }
508         if (ldescriptor->cleanup == nullptr)
509         {
510             DISCOVERY_OUT("error", "Plugin '" << ldescriptor->Name << "' has no cleanup()");
511             continue;
512         }
513         if (ldescriptor->run == nullptr && descriptor->run_synth == nullptr)
514         {
515             DISCOVERY_OUT("error", "Plugin '" << ldescriptor->Name << "' has no run() or run_synth()");
516             continue;
517         }
518         if (descriptor->run_synth == nullptr && descriptor->run_multiple_synths != nullptr)
519         {
520             DISCOVERY_OUT("error", "Plugin '" << ldescriptor->Name << "' requires run_multiple_synths which is not supported");
521             continue;
522         }
523         if (! LADSPA_IS_HARD_RT_CAPABLE(ldescriptor->Properties))
524         {
525             DISCOVERY_OUT("warning", "Plugin '" << ldescriptor->Name << "' is not hard real-time capable");
526         }
527 
528         uint hints = 0x0;
529         uint audioIns = 0;
530         uint audioOuts = 0;
531         uint audioTotal = 0;
532         uint midiIns = 0;
533         uint parametersIns = 0;
534         uint parametersOuts = 0;
535         uint parametersTotal = 0;
536 
537         if (LADSPA_IS_HARD_RT_CAPABLE(ldescriptor->Properties))
538             hints |= PLUGIN_IS_RTSAFE;
539 
540         for (unsigned long j=0; j < ldescriptor->PortCount; ++j)
541         {
542             CARLA_ASSERT(ldescriptor->PortNames[j] != nullptr);
543             const LADSPA_PortDescriptor portDescriptor = ldescriptor->PortDescriptors[j];
544 
545             if (LADSPA_IS_PORT_AUDIO(portDescriptor))
546             {
547                 if (LADSPA_IS_PORT_INPUT(portDescriptor))
548                     audioIns += 1;
549                 else if (LADSPA_IS_PORT_OUTPUT(portDescriptor))
550                     audioOuts += 1;
551 
552                 audioTotal += 1;
553             }
554             else if (LADSPA_IS_PORT_CONTROL(portDescriptor))
555             {
556                 if (LADSPA_IS_PORT_INPUT(portDescriptor))
557                     parametersIns += 1;
558                 else if (LADSPA_IS_PORT_OUTPUT(portDescriptor) && std::strcmp(ldescriptor->PortNames[j], "latency") != 0 && std::strcmp(ldescriptor->PortNames[j], "_latency") != 0)
559                     parametersOuts += 1;
560 
561                 parametersTotal += 1;
562             }
563         }
564 
565         if (descriptor->run_synth != nullptr)
566             midiIns = 1;
567 
568         if (midiIns > 0 && audioIns == 0 && audioOuts > 0)
569             hints |= PLUGIN_IS_SYNTH;
570 
571 #ifndef BUILD_BRIDGE
572         if (const char* const ui = find_dssi_ui(filename, ldescriptor->Label))
573         {
574             hints |= PLUGIN_HAS_CUSTOM_UI;
575             delete[] ui;
576         }
577 #endif
578 
579         if (doInit)
580         {
581             // -----------------------------------------------------------------------
582             // start crash-free plugin test
583 
584             LADSPA_Handle handle = ldescriptor->instantiate(ldescriptor, kSampleRatei);
585 
586             if (handle == nullptr)
587             {
588                 DISCOVERY_OUT("error", "Failed to init DSSI plugin");
589                 continue;
590             }
591 
592             // Test quick init and cleanup
593             ldescriptor->cleanup(handle);
594 
595             handle = ldescriptor->instantiate(ldescriptor, kSampleRatei);
596 
597             if (handle == nullptr)
598             {
599                 DISCOVERY_OUT("error", "Failed to init DSSI plugin (#2)");
600                 continue;
601             }
602 
603             LADSPA_Data bufferAudio[kBufferSize][audioTotal];
604             LADSPA_Data bufferParams[parametersTotal];
605             LADSPA_Data min, max, def;
606 
607             for (unsigned long j=0, iA=0, iC=0; j < ldescriptor->PortCount; ++j)
608             {
609                 const LADSPA_PortDescriptor portDescriptor = ldescriptor->PortDescriptors[j];
610                 const LADSPA_PortRangeHint  portRangeHints = ldescriptor->PortRangeHints[j];
611                 const char* const portName = ldescriptor->PortNames[j];
612 
613                 if (LADSPA_IS_PORT_AUDIO(portDescriptor))
614                 {
615                     carla_zeroFloats(bufferAudio[iA], kBufferSize);
616                     ldescriptor->connect_port(handle, j, bufferAudio[iA++]);
617                 }
618                 else if (LADSPA_IS_PORT_CONTROL(portDescriptor))
619                 {
620                     // min value
621                     if (LADSPA_IS_HINT_BOUNDED_BELOW(portRangeHints.HintDescriptor))
622                         min = portRangeHints.LowerBound;
623                     else
624                         min = 0.0f;
625 
626                     // max value
627                     if (LADSPA_IS_HINT_BOUNDED_ABOVE(portRangeHints.HintDescriptor))
628                         max = portRangeHints.UpperBound;
629                     else
630                         max = 1.0f;
631 
632                     if (min > max)
633                     {
634                         DISCOVERY_OUT("warning", "Parameter '" << portName << "' is broken: min > max");
635                         max = min + 0.1f;
636                     }
637                     else if (carla_isEqual(min, max))
638                     {
639                         DISCOVERY_OUT("warning", "Parameter '" << portName << "' is broken: max == min");
640                         max = min + 0.1f;
641                     }
642 
643                     // default value
644                     def = get_default_ladspa_port_value(portRangeHints.HintDescriptor, min, max);
645 
646                     if (LADSPA_IS_HINT_SAMPLE_RATE(portRangeHints.HintDescriptor))
647                     {
648                         min *= kSampleRatef;
649                         max *= kSampleRatef;
650                         def *= kSampleRatef;
651                     }
652 
653                     if (LADSPA_IS_PORT_OUTPUT(portDescriptor) && (std::strcmp(portName, "latency") == 0 || std::strcmp(portName, "_latency") == 0))
654                     {
655                         // latency parameter
656                         def = 0.0f;
657                     }
658                     else
659                     {
660                         if (def < min)
661                             def = min;
662                         else if (def > max)
663                             def = max;
664                     }
665 
666                     bufferParams[iC] = def;
667                     ldescriptor->connect_port(handle, j, &bufferParams[iC++]);
668                 }
669             }
670 
671             // select first midi-program if available
672             if (descriptor->get_program != nullptr && descriptor->select_program != nullptr)
673             {
674                 if (const DSSI_Program_Descriptor* const pDesc = descriptor->get_program(handle, 0))
675                     descriptor->select_program(handle, pDesc->Bank, pDesc->Program);
676             }
677 
678             if (ldescriptor->activate != nullptr)
679                 ldescriptor->activate(handle);
680 
681             if (descriptor->run_synth != nullptr)
682             {
683                 snd_seq_event_t midiEvents[2];
684                 carla_zeroStructs(midiEvents, 2);
685 
686                 const unsigned long midiEventCount = 2;
687 
688                 midiEvents[0].type = SND_SEQ_EVENT_NOTEON;
689                 midiEvents[0].data.note.note     = 64;
690                 midiEvents[0].data.note.velocity = 100;
691 
692                 midiEvents[1].type = SND_SEQ_EVENT_NOTEOFF;
693                 midiEvents[1].data.note.note     = 64;
694                 midiEvents[1].data.note.velocity = 0;
695                 midiEvents[1].time.tick = kBufferSize/2;
696 
697                 descriptor->run_synth(handle, kBufferSize, midiEvents, midiEventCount);
698             }
699             else
700                 ldescriptor->run(handle, kBufferSize);
701 
702             if (ldescriptor->deactivate != nullptr)
703                 ldescriptor->deactivate(handle);
704 
705             ldescriptor->cleanup(handle);
706 
707             // end crash-free plugin test
708             // -----------------------------------------------------------------------
709         }
710 
711         DISCOVERY_OUT("init", "-----------");
712         DISCOVERY_OUT("build", BINARY_NATIVE);
713         DISCOVERY_OUT("category", ((hints & PLUGIN_IS_SYNTH)
714                                    ? "synth"
715                                    : getPluginCategoryAsString(getPluginCategoryFromName(ldescriptor->Name))));
716         DISCOVERY_OUT("hints", hints);
717         DISCOVERY_OUT("name", ldescriptor->Name);
718         DISCOVERY_OUT("label", ldescriptor->Label);
719         DISCOVERY_OUT("maker", ldescriptor->Maker);
720         DISCOVERY_OUT("uniqueId", ldescriptor->UniqueID);
721         DISCOVERY_OUT("audio.ins", audioIns);
722         DISCOVERY_OUT("audio.outs", audioOuts);
723         DISCOVERY_OUT("midi.ins", midiIns);
724         DISCOVERY_OUT("parameters.ins", parametersIns);
725         DISCOVERY_OUT("parameters.outs", parametersOuts);
726         DISCOVERY_OUT("end", "------------");
727     }
728 }
729 
730 #ifndef BUILD_BRIDGE
do_lv2_check(const char * const bundle,const bool doInit)731 static void do_lv2_check(const char* const bundle, const bool doInit)
732 {
733     Lv2WorldClass& lv2World(Lv2WorldClass::getInstance());
734 
735     Lilv::Node bundleNode(lv2World.new_file_uri(nullptr, bundle));
736     CARLA_SAFE_ASSERT_RETURN(bundleNode.is_uri(),);
737 
738     CarlaString sBundle(bundleNode.as_uri());
739 
740     if (! sBundle.endsWith("/"))
741         sBundle += "/";
742 
743     // Load bundle
744     lv2World.load_bundle(sBundle);
745 
746     // Load plugins in this bundle
747     const Lilv::Plugins lilvPlugins(lv2World.get_all_plugins());
748 
749     // Get all plugin URIs in this bundle
750     water::StringArray URIs;
751 
752     LILV_FOREACH(plugins, it, lilvPlugins)
753     {
754         Lilv::Plugin lilvPlugin(lilv_plugins_get(lilvPlugins, it));
755 
756         if (const char* const uri = lilvPlugin.get_uri().as_string())
757             URIs.addIfNotAlreadyThere(water::String(uri));
758     }
759 
760     if (URIs.size() == 0)
761     {
762         DISCOVERY_OUT("warning", "LV2 Bundle doesn't provide any plugins");
763         return;
764     }
765 
766     // Get & check every plugin-instance
767     for (int i=0, count=URIs.size(); i < count; ++i)
768     {
769         const char* const URI = URIs[i].toRawUTF8();
770         CarlaScopedPointer<const LV2_RDF_Descriptor> rdfDescriptor(lv2_rdf_new(URI, false));
771 
772         if (rdfDescriptor == nullptr || rdfDescriptor->URI == nullptr)
773         {
774             DISCOVERY_OUT("error", "Failed to find LV2 plugin '" << URI << "'");
775             continue;
776         }
777 
778         if (doInit)
779         {
780             // test if lib is loadable, twice
781             const lib_t libHandle1 = lib_open(rdfDescriptor->Binary);
782 
783             if (libHandle1 == nullptr)
784             {
785                 print_lib_error(rdfDescriptor->Binary);
786                 delete rdfDescriptor;
787                 continue;
788             }
789 
790             lib_close(libHandle1);
791 
792             const lib_t libHandle2 = lib_open(rdfDescriptor->Binary);
793 
794             if (libHandle2 == nullptr)
795             {
796                 print_lib_error(rdfDescriptor->Binary);
797                 delete rdfDescriptor;
798                 continue;
799             }
800 
801             lib_close(libHandle2);
802         }
803 
804         const LilvPlugin* const cPlugin(lv2World.getPluginFromURI(URI));
805         CARLA_SAFE_ASSERT_CONTINUE(cPlugin != nullptr);
806 
807         Lilv::Plugin lilvPlugin(cPlugin);
808         CARLA_SAFE_ASSERT_CONTINUE(lilvPlugin.get_uri().is_uri());
809 
810         print_cached_plugin(get_cached_plugin_lv2(lv2World, lilvPlugin));
811     }
812 }
813 #endif
814 
815 #ifndef USING_JUCE_FOR_VST2
816 // -------------------------------------------------------------------------------------------------------------------
817 // VST stuff
818 
819 // Check if plugin is currently processing
820 static bool gVstIsProcessing = false;
821 
822 // Check if plugin needs idle
823 static bool gVstNeedsIdle = false;
824 
825 // Check if plugin wants midi
826 static bool gVstWantsMidi = false;
827 
828 // Check if plugin wants time
829 static bool gVstWantsTime = false;
830 
831 // Current uniqueId for VST shell plugins
832 static intptr_t gVstCurrentUniqueId = 0;
833 
834 // Supported Carla features
vstHostCanDo(const char * const feature)835 static intptr_t vstHostCanDo(const char* const feature)
836 {
837     carla_debug("vstHostCanDo(\"%s\")", feature);
838 
839     if (std::strcmp(feature, "supplyIdle") == 0)
840         return 1;
841     if (std::strcmp(feature, "sendVstEvents") == 0)
842         return 1;
843     if (std::strcmp(feature, "sendVstMidiEvent") == 0)
844         return 1;
845     if (std::strcmp(feature, "sendVstMidiEventFlagIsRealtime") == 0)
846         return 1;
847     if (std::strcmp(feature, "sendVstTimeInfo") == 0)
848     {
849         gVstWantsTime = true;
850         return 1;
851     }
852     if (std::strcmp(feature, "receiveVstEvents") == 0)
853         return 1;
854     if (std::strcmp(feature, "receiveVstMidiEvent") == 0)
855         return 1;
856     if (std::strcmp(feature, "receiveVstTimeInfo") == 0)
857         return -1;
858     if (std::strcmp(feature, "reportConnectionChanges") == 0)
859         return -1;
860     if (std::strcmp(feature, "acceptIOChanges") == 0)
861         return 1;
862     if (std::strcmp(feature, "sizeWindow") == 0)
863         return 1;
864     if (std::strcmp(feature, "offline") == 0)
865         return -1;
866     if (std::strcmp(feature, "openFileSelector") == 0)
867         return -1;
868     if (std::strcmp(feature, "closeFileSelector") == 0)
869         return -1;
870     if (std::strcmp(feature, "startStopProcess") == 0)
871         return 1;
872     if (std::strcmp(feature, "supportShell") == 0)
873         return 1;
874     if (std::strcmp(feature, "shellCategory") == 0)
875         return 1;
876     if (std::strcmp(feature, "NIMKPIVendorSpecificCallbacks") == 0)
877         return -1;
878 
879     // non-official features found in some plugins:
880     // "asyncProcessing"
881     // "editFile"
882 
883     // unimplemented
884     carla_stderr("vstHostCanDo(\"%s\") - unknown feature", feature);
885     return 0;
886 }
887 
888 // Host-side callback
vstHostCallback(AEffect * const effect,const int32_t opcode,const int32_t index,const intptr_t value,void * const ptr,const float opt)889 static intptr_t VSTCALLBACK vstHostCallback(AEffect* const effect, const int32_t opcode, const int32_t index, const intptr_t value, void* const ptr, const float opt)
890 {
891     carla_debug("vstHostCallback(%p, %i:%s, %i, " P_INTPTR ", %p, %f)",
892                 effect, opcode, vstMasterOpcode2str(opcode), index, value, ptr, static_cast<double>(opt));
893 
894     static VstTimeInfo timeInfo;
895     intptr_t ret = 0;
896 
897     switch (opcode)
898     {
899     case audioMasterAutomate:
900         ret = 1;
901         break;
902 
903     case audioMasterVersion:
904         ret = kVstVersion;
905         break;
906 
907     case audioMasterCurrentId:
908         ret = gVstCurrentUniqueId;
909         break;
910 
911     case DECLARE_VST_DEPRECATED(audioMasterWantMidi):
912         if (gVstWantsMidi) { DISCOVERY_OUT("warning", "Plugin requested MIDI more than once"); }
913 
914         gVstWantsMidi = true;
915         ret = 1;
916         break;
917 
918     case audioMasterGetTime:
919         if (! gVstIsProcessing) { DISCOVERY_OUT("warning", "Plugin requested timeInfo out of process"); }
920         if (! gVstWantsTime)    { DISCOVERY_OUT("warning", "Plugin requested timeInfo but didn't ask if host could do \"sendVstTimeInfo\""); }
921 
922         carla_zeroStruct(timeInfo);
923         timeInfo.sampleRate = kSampleRate;
924 
925         // Tempo
926         timeInfo.tempo  = 120.0;
927         timeInfo.flags |= kVstTempoValid;
928 
929         // Time Signature
930         timeInfo.timeSigNumerator   = 4;
931         timeInfo.timeSigDenominator = 4;
932         timeInfo.flags |= kVstTimeSigValid;
933 
934         ret = (intptr_t)&timeInfo;
935         break;
936 
937     case DECLARE_VST_DEPRECATED(audioMasterTempoAt):
938         ret = 120 * 10000;
939         break;
940 
941     case DECLARE_VST_DEPRECATED(audioMasterGetNumAutomatableParameters):
942         ret = carla_minPositive(effect->numParams, static_cast<int>(MAX_DEFAULT_PARAMETERS));
943         break;
944 
945     case DECLARE_VST_DEPRECATED(audioMasterGetParameterQuantization):
946         ret = 1; // full single float precision
947         break;
948 
949     case DECLARE_VST_DEPRECATED(audioMasterNeedIdle):
950         if (gVstNeedsIdle) { DISCOVERY_OUT("warning", "Plugin requested idle more than once"); }
951 
952         gVstNeedsIdle = true;
953         ret = 1;
954         break;
955 
956     case audioMasterGetSampleRate:
957         ret = kSampleRatei;
958         break;
959 
960     case audioMasterGetBlockSize:
961         ret = kBufferSize;
962         break;
963 
964     case DECLARE_VST_DEPRECATED(audioMasterWillReplaceOrAccumulate):
965         ret = 1; // replace
966         break;
967 
968     case audioMasterGetCurrentProcessLevel:
969         ret = gVstIsProcessing ? kVstProcessLevelRealtime : kVstProcessLevelUser;
970         break;
971 
972     case audioMasterGetAutomationState:
973         ret = kVstAutomationOff;
974         break;
975 
976     case audioMasterGetVendorString:
977         CARLA_SAFE_ASSERT_BREAK(ptr != nullptr);
978         std::strcpy((char*)ptr, "falkTX");
979         ret = 1;
980         break;
981 
982     case audioMasterGetProductString:
983         CARLA_SAFE_ASSERT_BREAK(ptr != nullptr);
984         std::strcpy((char*)ptr, "Carla-Discovery");
985         ret = 1;
986         break;
987 
988     case audioMasterGetVendorVersion:
989         ret = CARLA_VERSION_HEX;
990         break;
991 
992     case audioMasterCanDo:
993         CARLA_SAFE_ASSERT_BREAK(ptr != nullptr);
994         ret = vstHostCanDo((const char*)ptr);
995         break;
996 
997     case audioMasterGetLanguage:
998         ret = kVstLangEnglish;
999         break;
1000 
1001     default:
1002         carla_stdout("vstHostCallback(%p, %i:%s, %i, " P_INTPTR ", %p, %f)",
1003                      effect, opcode, vstMasterOpcode2str(opcode), index, value, ptr, static_cast<double>(opt));
1004         break;
1005     }
1006 
1007     return ret;
1008 }
1009 
do_vst_check(lib_t & libHandle,const char * const filename,const bool doInit)1010 static void do_vst_check(lib_t& libHandle, const char* const filename, const bool doInit)
1011 {
1012     VST_Function vstFn = nullptr;
1013 
1014 #ifdef CARLA_OS_MAC
1015     CFBundleRef bundleRef = nullptr;
1016     CFBundleRefNum resFileId = 0;
1017 
1018     if (libHandle == nullptr)
1019     {
1020         const CFURLRef urlRef = CFURLCreateFromFileSystemRepresentation(0, (const UInt8*)filename, (CFIndex)strlen(filename), true);
1021         CARLA_SAFE_ASSERT_RETURN(urlRef != nullptr,);
1022 
1023         bundleRef = CFBundleCreate(kCFAllocatorDefault, urlRef);
1024         CFRelease(urlRef);
1025         CARLA_SAFE_ASSERT_RETURN(bundleRef != nullptr,);
1026 
1027         if (! CFBundleLoadExecutable(bundleRef))
1028         {
1029             CFRelease(bundleRef);
1030             DISCOVERY_OUT("error", "Failed to load VST bundle executable");
1031             return;
1032         }
1033 
1034         vstFn = (VST_Function)CFBundleGetFunctionPointerForName(bundleRef, CFSTR("main_macho"));
1035 
1036         if (vstFn == nullptr)
1037             vstFn = (VST_Function)CFBundleGetFunctionPointerForName(bundleRef, CFSTR("VSTPluginMain"));
1038 
1039         if (vstFn == nullptr)
1040         {
1041             CFBundleUnloadExecutable(bundleRef);
1042             CFRelease(bundleRef);
1043             DISCOVERY_OUT("error", "Not a VST plugin");
1044             return;
1045         }
1046 
1047         resFileId = CFBundleOpenBundleResourceMap(bundleRef);
1048     }
1049     else
1050 #endif
1051     {
1052         vstFn = lib_symbol<VST_Function>(libHandle, "VSTPluginMain");
1053 
1054         if (vstFn == nullptr)
1055         {
1056             vstFn = lib_symbol<VST_Function>(libHandle, "main");
1057 
1058             if (vstFn == nullptr)
1059             {
1060                 DISCOVERY_OUT("error", "Not a VST plugin");
1061                 return;
1062             }
1063         }
1064     }
1065 
1066     AEffect* effect = vstFn(vstHostCallback);
1067 
1068     if (effect == nullptr || effect->magic != kEffectMagic)
1069     {
1070         DISCOVERY_OUT("error", "Failed to init VST plugin, or VST magic failed");
1071         return;
1072     }
1073 
1074     if (effect->uniqueID == 0)
1075     {
1076         DISCOVERY_OUT("warning", "Plugin doesn't have an Unique ID when first loaded");
1077     }
1078 
1079     effect->dispatcher(effect, DECLARE_VST_DEPRECATED(effIdentify), 0, 0, nullptr, 0.0f);
1080     effect->dispatcher(effect, DECLARE_VST_DEPRECATED(effSetBlockSizeAndSampleRate), 0, kBufferSize, nullptr, kSampleRatef);
1081     effect->dispatcher(effect, effSetSampleRate, 0, 0, nullptr, kSampleRatef);
1082     effect->dispatcher(effect, effSetBlockSize, 0, kBufferSize, nullptr, 0.0f);
1083     effect->dispatcher(effect, effSetProcessPrecision, 0, kVstProcessPrecision32, nullptr, 0.0f);
1084 
1085     effect->dispatcher(effect, effOpen, 0, 0, nullptr, 0.0f);
1086 
1087     if (effect->numPrograms > 0)
1088         effect->dispatcher(effect, effSetProgram, 0, 0, nullptr, 0.0f);
1089 
1090     const bool isShell = (effect->dispatcher(effect, effGetPlugCategory, 0, 0, nullptr, 0.0f) == kPlugCategShell);
1091 
1092     if (effect->uniqueID == 0 && !isShell)
1093     {
1094         DISCOVERY_OUT("error", "Plugin doesn't have an Unique ID after being open");
1095         effect->dispatcher(effect, effClose, 0, 0, nullptr, 0.0f);
1096         return;
1097     }
1098 
1099     gVstCurrentUniqueId =  effect->uniqueID;
1100 
1101     char strBuf[STR_MAX+1];
1102     CarlaString cName;
1103     CarlaString cProduct;
1104     CarlaString cVendor;
1105     PluginCategory category;
1106     LinkedList<intptr_t> uniqueIds;
1107 
1108     if (isShell)
1109     {
1110         for (;;)
1111         {
1112             carla_zeroChars(strBuf, STR_MAX+1);
1113 
1114             gVstCurrentUniqueId = effect->dispatcher(effect, effShellGetNextPlugin, 0, 0, strBuf, 0.0f);
1115 
1116             if (gVstCurrentUniqueId == 0)
1117                 break;
1118 
1119             uniqueIds.append(gVstCurrentUniqueId);
1120         }
1121 
1122         effect->dispatcher(effect, effClose, 0, 0, nullptr, 0.0f);
1123         effect = nullptr;
1124     }
1125     else
1126     {
1127         uniqueIds.append(gVstCurrentUniqueId);
1128     }
1129 
1130     for (LinkedList<intptr_t>::Itenerator it = uniqueIds.begin2(); it.valid(); it.next())
1131     {
1132         gVstCurrentUniqueId = it.getValue(0);
1133 
1134         if (effect == nullptr)
1135         {
1136             effect = vstFn(vstHostCallback);
1137 
1138             effect->dispatcher(effect, DECLARE_VST_DEPRECATED(effIdentify), 0, 0, nullptr, 0.0f);
1139             effect->dispatcher(effect, DECLARE_VST_DEPRECATED(effSetBlockSizeAndSampleRate), 0, kBufferSize, nullptr, kSampleRatef);
1140             effect->dispatcher(effect, effSetSampleRate, 0, 0, nullptr, kSampleRatef);
1141             effect->dispatcher(effect, effSetBlockSize, 0, kBufferSize, nullptr, 0.0f);
1142             effect->dispatcher(effect, effSetProcessPrecision, 0, kVstProcessPrecision32, nullptr, 0.0f);
1143 
1144             effect->dispatcher(effect, effOpen, 0, 0, nullptr, 0.0f);
1145 
1146             if (effect->numPrograms > 0)
1147                 effect->dispatcher(effect, effSetProgram, 0, 0, nullptr, 0.0f);
1148         }
1149 
1150         // get name
1151         carla_zeroChars(strBuf, STR_MAX+1);
1152 
1153         if (effect->dispatcher(effect, effGetEffectName, 0, 0, strBuf, 0.0f) == 1)
1154             cName = strBuf;
1155         else
1156             cName.clear();
1157 
1158         // get product
1159         carla_zeroChars(strBuf, STR_MAX+1);
1160 
1161         if (effect->dispatcher(effect, effGetProductString, 0, 0, strBuf, 0.0f) == 1)
1162             cProduct = strBuf;
1163         else
1164             cProduct.clear();
1165 
1166         // get vendor
1167         carla_zeroChars(strBuf, STR_MAX+1);
1168 
1169         if (effect->dispatcher(effect, effGetVendorString, 0, 0, strBuf, 0.0f) == 1)
1170             cVendor = strBuf;
1171         else
1172             cVendor.clear();
1173 
1174         // get category
1175         switch (effect->dispatcher(effect, effGetPlugCategory, 0, 0, nullptr, 0.0f))
1176         {
1177         case kPlugCategSynth:
1178             category = PLUGIN_CATEGORY_SYNTH;
1179             break;
1180         case kPlugCategAnalysis:
1181             category = PLUGIN_CATEGORY_UTILITY;
1182             break;
1183         case kPlugCategMastering:
1184             category = PLUGIN_CATEGORY_DYNAMICS;
1185             break;
1186         case kPlugCategRoomFx:
1187             category = PLUGIN_CATEGORY_DELAY;
1188             break;
1189         case kPlugCategRestoration:
1190             category = PLUGIN_CATEGORY_UTILITY;
1191             break;
1192         case kPlugCategGenerator:
1193             category = PLUGIN_CATEGORY_SYNTH;
1194             break;
1195         default:
1196             if (effect->flags & effFlagsIsSynth)
1197                 category = PLUGIN_CATEGORY_SYNTH;
1198             else
1199                 category = PLUGIN_CATEGORY_NONE;
1200             break;
1201         }
1202 
1203         // get everything else
1204         uint hints = 0x0;
1205         uint audioIns = static_cast<uint>(std::max(0, effect->numInputs));
1206         uint audioOuts = static_cast<uint>(std::max(0, effect->numOutputs));
1207         uint midiIns = 0;
1208         uint midiOuts = 0;
1209         uint parameters = static_cast<uint>(std::max(0, effect->numParams));
1210 
1211         if (effect->flags & effFlagsHasEditor)
1212             hints |= PLUGIN_HAS_CUSTOM_UI;
1213 
1214         if (effect->flags & effFlagsIsSynth)
1215         {
1216             hints |= PLUGIN_IS_SYNTH;
1217             midiIns = 1;
1218         }
1219 
1220         if (vstPluginCanDo(effect, "receiveVstEvents") || vstPluginCanDo(effect, "receiveVstMidiEvent") || (effect->flags & effFlagsIsSynth) != 0)
1221             midiIns = 1;
1222 
1223         if (vstPluginCanDo(effect, "sendVstEvents") || vstPluginCanDo(effect, "sendVstMidiEvent"))
1224             midiOuts = 1;
1225 
1226         // -----------------------------------------------------------------------
1227         // start crash-free plugin test
1228 
1229         if (doInit)
1230         {
1231             if (gVstNeedsIdle)
1232                 effect->dispatcher(effect, DECLARE_VST_DEPRECATED(effIdle), 0, 0, nullptr, 0.0f);
1233 
1234             effect->dispatcher(effect, effMainsChanged, 0, 1, nullptr, 0.0f);
1235             effect->dispatcher(effect, effStartProcess, 0, 0, nullptr, 0.0f);
1236 
1237             if (gVstNeedsIdle)
1238                 effect->dispatcher(effect, DECLARE_VST_DEPRECATED(effIdle), 0, 0, nullptr, 0.0f);
1239 
1240             // Plugin might call wantMidi() during resume
1241             if (midiIns == 0 && gVstWantsMidi)
1242             {
1243                 midiIns = 1;
1244             }
1245 
1246             float* bufferAudioIn[std::max(1U, audioIns)];
1247             float* bufferAudioOut[std::max(1U, audioOuts)];
1248 
1249             if (audioIns == 0)
1250             {
1251                 bufferAudioIn[0] = nullptr;
1252             }
1253             else
1254             {
1255                 for (uint j=0; j < audioIns; ++j)
1256                 {
1257                     bufferAudioIn[j] = new float[kBufferSize];
1258                     carla_zeroFloats(bufferAudioIn[j], kBufferSize);
1259                 }
1260             }
1261 
1262             if (audioOuts == 0)
1263             {
1264                 bufferAudioOut[0] = nullptr;
1265             }
1266             else
1267             {
1268                 for (uint j=0; j < audioOuts; ++j)
1269                 {
1270                     bufferAudioOut[j] = new float[kBufferSize];
1271                     carla_zeroFloats(bufferAudioOut[j], kBufferSize);
1272                 }
1273             }
1274 
1275             struct VstEventsFixed {
1276                 int32_t numEvents;
1277                 intptr_t reserved;
1278                 VstEvent* data[2];
1279 
1280                 VstEventsFixed()
1281                     : numEvents(0),
1282                       reserved(0)
1283                 {
1284                     data[0] = data[1] = nullptr;
1285                 }
1286             } events;
1287 
1288             VstMidiEvent midiEvents[2];
1289             carla_zeroStructs(midiEvents, 2);
1290 
1291             midiEvents[0].type = kVstMidiType;
1292             midiEvents[0].byteSize = sizeof(VstMidiEvent);
1293             midiEvents[0].midiData[0] = char(MIDI_STATUS_NOTE_ON);
1294             midiEvents[0].midiData[1] = 64;
1295             midiEvents[0].midiData[2] = 100;
1296 
1297             midiEvents[1].type = kVstMidiType;
1298             midiEvents[1].byteSize = sizeof(VstMidiEvent);
1299             midiEvents[1].midiData[0] = char(MIDI_STATUS_NOTE_OFF);
1300             midiEvents[1].midiData[1] = 64;
1301             midiEvents[1].deltaFrames = kBufferSize/2;
1302 
1303             events.numEvents = 2;
1304             events.data[0] = (VstEvent*)&midiEvents[0];
1305             events.data[1] = (VstEvent*)&midiEvents[1];
1306 
1307             // processing
1308             gVstIsProcessing = true;
1309 
1310             if (midiIns > 0)
1311                 effect->dispatcher(effect, effProcessEvents, 0, 0, &events, 0.0f);
1312 
1313             if ((effect->flags & effFlagsCanReplacing) > 0 && effect->processReplacing != nullptr && effect->processReplacing != effect->DECLARE_VST_DEPRECATED(process))
1314                 effect->processReplacing(effect, bufferAudioIn, bufferAudioOut, kBufferSize);
1315             else if (effect->DECLARE_VST_DEPRECATED(process) != nullptr)
1316                 effect->DECLARE_VST_DEPRECATED(process)(effect, bufferAudioIn, bufferAudioOut, kBufferSize);
1317             else
1318                 DISCOVERY_OUT("error", "Plugin doesn't have a process function");
1319 
1320             gVstIsProcessing = false;
1321 
1322             effect->dispatcher(effect, effStopProcess, 0, 0, nullptr, 0.0f);
1323             effect->dispatcher(effect, effMainsChanged, 0, 0, nullptr, 0.0f);
1324 
1325             if (gVstNeedsIdle)
1326                 effect->dispatcher(effect, DECLARE_VST_DEPRECATED(effIdle), 0, 0, nullptr, 0.0f);
1327 
1328             for (uint j=0; j < audioIns; ++j)
1329                 delete[] bufferAudioIn[j];
1330             for (uint j=0; j < audioOuts; ++j)
1331                 delete[] bufferAudioOut[j];
1332         }
1333 
1334         // end crash-free plugin test
1335         // -----------------------------------------------------------------------
1336 
1337         DISCOVERY_OUT("init", "-----------");
1338         DISCOVERY_OUT("build", BINARY_NATIVE);
1339         DISCOVERY_OUT("hints", hints);
1340         DISCOVERY_OUT("category", getPluginCategoryAsString(category));
1341         DISCOVERY_OUT("name", cName.buffer());
1342         DISCOVERY_OUT("label", cProduct.buffer());
1343         DISCOVERY_OUT("maker", cVendor.buffer());
1344         DISCOVERY_OUT("uniqueId", gVstCurrentUniqueId);
1345         DISCOVERY_OUT("audio.ins", audioIns);
1346         DISCOVERY_OUT("audio.outs", audioOuts);
1347         DISCOVERY_OUT("midi.ins", midiIns);
1348         DISCOVERY_OUT("midi.outs", midiOuts);
1349         DISCOVERY_OUT("parameters.ins", parameters);
1350         DISCOVERY_OUT("end", "------------");
1351 
1352         gVstWantsMidi = false;
1353         gVstWantsTime = false;
1354 
1355         if (! isShell)
1356             break;
1357 
1358         effect->dispatcher(effect, effClose, 0, 0, nullptr, 0.0f);
1359         effect = nullptr;
1360     }
1361 
1362     uniqueIds.clear();
1363 
1364     if (effect != nullptr)
1365     {
1366         if (gVstNeedsIdle)
1367             effect->dispatcher(effect, DECLARE_VST_DEPRECATED(effIdle), 0, 0, nullptr, 0.0f);
1368 
1369         effect->dispatcher(effect, effClose, 0, 0, nullptr, 0.0f);
1370     }
1371 
1372 #ifdef CARLA_OS_MAC
1373     if (bundleRef != nullptr)
1374     {
1375         CFBundleCloseBundleResourceMap(bundleRef, resFileId);
1376         CFBundleUnloadExecutable(bundleRef);
1377         CFRelease(bundleRef);
1378     }
1379 #else
1380     return;
1381 
1382     // unused
1383     (void)filename;
1384 #endif
1385 }
1386 #endif // ! USING_JUCE_FOR_VST2
1387 
1388 #ifdef USING_JUCE
1389 // -------------------------------------------------------------------------------------------------------------------
1390 // find all available plugin audio ports
1391 
findMaxTotalChannels(juce::AudioProcessor * const filter,int & maxTotalIns,int & maxTotalOuts)1392 static void findMaxTotalChannels(juce::AudioProcessor* const filter, int& maxTotalIns, int& maxTotalOuts)
1393 {
1394     filter->enableAllBuses();
1395 
1396     int numInputBuses  = filter->getBusCount(true);
1397     int numOutputBuses = filter->getBusCount(false);
1398 
1399     if (numInputBuses > 1 || numOutputBuses > 1)
1400     {
1401         maxTotalIns = maxTotalOuts = 0;
1402 
1403         for (int i = 0; i < numInputBuses; ++i)
1404             maxTotalIns += filter->getChannelCountOfBus(true, i);
1405 
1406         for (int i = 0; i < numOutputBuses; ++i)
1407             maxTotalOuts += filter->getChannelCountOfBus(false, i);
1408     }
1409     else
1410     {
1411         maxTotalIns  = numInputBuses  > 0 ? filter->getBus(true,  0)->getMaxSupportedChannels(64) : 0;
1412         maxTotalOuts = numOutputBuses > 0 ? filter->getBus(false, 0)->getMaxSupportedChannels(64) : 0;
1413     }
1414 }
1415 
1416 // -------------------------------------------------------------------------------------------------------------------
1417 
do_juce_check(const char * const filename_,const char * const stype,const bool doInit)1418 static bool do_juce_check(const char* const filename_, const char* const stype, const bool doInit)
1419 {
1420     CARLA_SAFE_ASSERT_RETURN(stype != nullptr && stype[0] != 0, false) // FIXME
1421     carla_debug("do_juce_check(%s, %s, %s)", filename_, stype, bool2str(doInit));
1422 
1423     carla_juce_init();
1424 
1425     juce::String filename;
1426 
1427 #ifdef CARLA_OS_WIN
1428     // Fix for wine usage
1429     if (juce::File("Z:\\usr\\").isDirectory() && filename_[0] == '/')
1430     {
1431         filename = filename_;
1432         filename.replace("/", "\\");
1433         filename = "Z:" + filename;
1434     }
1435     else
1436 #endif
1437     filename = juce::File(filename_).getFullPathName();
1438 
1439     CarlaScopedPointer<juce::AudioPluginFormat> pluginFormat;
1440 
1441     /* */ if (std::strcmp(stype, "VST2") == 0)
1442     {
1443 #if JUCE_PLUGINHOST_VST
1444         pluginFormat = new juce::VSTPluginFormat();
1445 #else
1446         DISCOVERY_OUT("error", "VST2 support not available");
1447         return false;
1448 #endif
1449     }
1450     else if (std::strcmp(stype, "VST3") == 0)
1451     {
1452 #if JUCE_PLUGINHOST_VST3
1453         pluginFormat = new juce::VST3PluginFormat();
1454 #else
1455         DISCOVERY_OUT("error", "VST3 support not available");
1456         return false;
1457 #endif
1458     }
1459     else if (std::strcmp(stype, "AU") == 0)
1460     {
1461 #if JUCE_PLUGINHOST_AU
1462         pluginFormat = new juce::AudioUnitPluginFormat();
1463 #else
1464         DISCOVERY_OUT("error", "AU support not available");
1465         return false;
1466 #endif
1467     }
1468 
1469     if (pluginFormat == nullptr)
1470     {
1471         DISCOVERY_OUT("error", stype << " support not available");
1472         return false;
1473     }
1474 
1475 #ifdef CARLA_OS_WIN
1476     CARLA_CUSTOM_SAFE_ASSERT_RETURN("Plugin file/folder does not exist", juce::File(filename).exists(), false);
1477 #endif
1478     CARLA_SAFE_ASSERT_RETURN(pluginFormat->fileMightContainThisPluginType(filename), false);
1479 
1480     juce::OwnedArray<juce::PluginDescription> results;
1481     pluginFormat->findAllTypesForFile(results, filename);
1482 
1483     if (results.size() == 0)
1484     {
1485 #if defined(CARLA_OS_MAC) && defined(__aarch64__)
1486         if (std::strcmp(stype, "VST2") == 0 || std::strcmp(stype, "VST3") == 0)
1487             return true;
1488 #endif
1489         DISCOVERY_OUT("error", "No plugins found");
1490         return false;
1491     }
1492 
1493     for (juce::PluginDescription **it = results.begin(), **end = results.end(); it != end; ++it)
1494     {
1495         juce::PluginDescription* const desc(*it);
1496 
1497         uint hints = 0x0;
1498         int audioIns = desc->numInputChannels;
1499         int audioOuts = desc->numOutputChannels;
1500         int midiIns = 0;
1501         int midiOuts = 0;
1502         int parameters = 0;
1503 
1504         if (desc->isInstrument)
1505         {
1506             hints |= PLUGIN_IS_SYNTH;
1507             midiIns = 1;
1508         }
1509 
1510         if (doInit)
1511         {
1512             if (std::unique_ptr<juce::AudioPluginInstance> instance
1513                     = pluginFormat->createInstanceFromDescription(*desc, kSampleRate, kBufferSize))
1514             {
1515                 carla_juce_idle();
1516 
1517                 findMaxTotalChannels(instance.get(), audioIns, audioOuts);
1518                 instance->refreshParameterList();
1519 
1520                 parameters = instance->getParameters().size();
1521 
1522                 if (instance->hasEditor())
1523                     hints |= PLUGIN_HAS_CUSTOM_UI;
1524                 if (instance->acceptsMidi())
1525                     midiIns = 1;
1526                 if (instance->producesMidi())
1527                     midiOuts = 1;
1528             }
1529         }
1530 
1531         DISCOVERY_OUT("init", "-----------");
1532         DISCOVERY_OUT("build", BINARY_NATIVE);
1533         DISCOVERY_OUT("hints", hints);
1534         DISCOVERY_OUT("category", getPluginCategoryAsString(getPluginCategoryFromName(desc->category.toRawUTF8())));
1535         DISCOVERY_OUT("name", desc->descriptiveName);
1536         DISCOVERY_OUT("label", desc->name);
1537         DISCOVERY_OUT("maker", desc->manufacturerName);
1538         DISCOVERY_OUT("uniqueId", desc->uid);
1539         DISCOVERY_OUT("audio.ins", audioIns);
1540         DISCOVERY_OUT("audio.outs", audioOuts);
1541         DISCOVERY_OUT("midi.ins", midiIns);
1542         DISCOVERY_OUT("midi.outs", midiOuts);
1543         DISCOVERY_OUT("parameters.ins", parameters);
1544         DISCOVERY_OUT("end", "------------");
1545     }
1546 
1547     carla_juce_idle();
1548     carla_juce_cleanup();
1549     return false;
1550 }
1551 #endif // USING_JUCE_FOR_VST2
1552 
do_fluidsynth_check(const char * const filename,const PluginType type,const bool doInit)1553 static void do_fluidsynth_check(const char* const filename, const PluginType type, const bool doInit)
1554 {
1555 #ifdef HAVE_FLUIDSYNTH
1556     const water::String jfilename = water::String(water::CharPointer_UTF8(filename));
1557     const water::File file(jfilename);
1558 
1559     if (! file.existsAsFile())
1560     {
1561         DISCOVERY_OUT("error", "Requested file is not valid or does not exist");
1562         return;
1563     }
1564 
1565     if (type == PLUGIN_SF2 && ! fluid_is_soundfont(filename))
1566     {
1567         DISCOVERY_OUT("error", "Not a SF2 file");
1568         return;
1569     }
1570 
1571     int programs = 0;
1572 
1573     if (doInit)
1574     {
1575         fluid_settings_t* const f_settings = new_fluid_settings();
1576         CARLA_SAFE_ASSERT_RETURN(f_settings != nullptr,);
1577 
1578         fluid_synth_t* const f_synth = new_fluid_synth(f_settings);
1579         CARLA_SAFE_ASSERT_RETURN(f_synth != nullptr,);
1580 
1581         const int f_id_test = fluid_synth_sfload(f_synth, filename, 0);
1582 
1583         if (f_id_test < 0)
1584         {
1585             DISCOVERY_OUT("error", "Failed to load SF2 file");
1586             return;
1587         }
1588 
1589 #if FLUIDSYNTH_VERSION_MAJOR >= 2
1590         const int f_id = f_id_test;
1591 #else
1592         const uint f_id = static_cast<uint>(f_id_test);
1593 #endif
1594 
1595         if (fluid_sfont_t* const f_sfont = fluid_synth_get_sfont_by_id(f_synth, f_id))
1596         {
1597 #if FLUIDSYNTH_VERSION_MAJOR >= 2
1598             fluid_sfont_iteration_start(f_sfont);
1599             for (; fluid_sfont_iteration_next(f_sfont);)
1600                 ++programs;
1601 #else
1602             fluid_preset_t f_preset;
1603 
1604             f_sfont->iteration_start(f_sfont);
1605             for (; f_sfont->iteration_next(f_sfont, &f_preset);)
1606                 ++programs;
1607 #endif
1608         }
1609 
1610         delete_fluid_synth(f_synth);
1611         delete_fluid_settings(f_settings);
1612     }
1613 
1614     CarlaString name(file.getFileNameWithoutExtension().toRawUTF8());
1615     CarlaString label(name);
1616 
1617     // 2 channels
1618     DISCOVERY_OUT("init", "-----------");
1619     DISCOVERY_OUT("build", BINARY_NATIVE);
1620     DISCOVERY_OUT("hints", PLUGIN_IS_SYNTH);
1621     DISCOVERY_OUT("category", "synth");
1622     DISCOVERY_OUT("name", name.buffer());
1623     DISCOVERY_OUT("label", label.buffer());
1624     DISCOVERY_OUT("audio.outs", 2);
1625     DISCOVERY_OUT("midi.ins", 1);
1626     DISCOVERY_OUT("parameters.ins", 13); // defined in Carla
1627     DISCOVERY_OUT("parameters.outs", 1);
1628     DISCOVERY_OUT("end", "------------");
1629 
1630     // 16 channels
1631     if (doInit && (name.isEmpty() || programs <= 1))
1632         return;
1633 
1634     name += " (16 outputs)";
1635 
1636     DISCOVERY_OUT("init", "-----------");
1637     DISCOVERY_OUT("build", BINARY_NATIVE);
1638     DISCOVERY_OUT("hints", PLUGIN_IS_SYNTH);
1639     DISCOVERY_OUT("category", "synth");
1640     DISCOVERY_OUT("name", name.buffer());
1641     DISCOVERY_OUT("label", label.buffer());
1642     DISCOVERY_OUT("audio.outs", 32);
1643     DISCOVERY_OUT("midi.ins", 1);
1644     DISCOVERY_OUT("parameters.ins", 13); // defined in Carla
1645     DISCOVERY_OUT("parameters.outs", 1);
1646     DISCOVERY_OUT("end", "------------");
1647 #else // HAVE_FLUIDSYNTH
1648     DISCOVERY_OUT("error", "SF2 support not available");
1649     return;
1650 
1651     // unused
1652     (void)filename;
1653     (void)type;
1654     (void)doInit;
1655 #endif
1656 }
1657 
1658 // ------------------------------ main entry point ------------------------------
1659 
main(int argc,char * argv[])1660 int main(int argc, char* argv[])
1661 {
1662     if (argc != 3)
1663     {
1664         carla_stdout("usage: %s <type> </path/to/plugin>", argv[0]);
1665         return 1;
1666     }
1667 
1668     const char* const stype    = argv[1];
1669     const char* const filename = argv[2];
1670     const PluginType  type     = getPluginTypeFromString(stype);
1671 
1672     CarlaString filenameCheck(filename);
1673     filenameCheck.toLower();
1674 
1675     bool openLib = false;
1676     lib_t handle = nullptr;
1677 
1678     switch (type)
1679     {
1680     case PLUGIN_LADSPA:
1681     case PLUGIN_DSSI:
1682     case PLUGIN_VST2:
1683         openLib = true;
1684         break;
1685     case PLUGIN_VST3:
1686         openLib = water::File(filename).existsAsFile();
1687         break;
1688     default:
1689         break;
1690     }
1691 
1692     if (type != PLUGIN_SF2 && filenameCheck.contains("fluidsynth", true))
1693     {
1694         DISCOVERY_OUT("info", "skipping fluidsynth based plugin");
1695         return 0;
1696     }
1697 
1698 #ifdef CARLA_OS_MAC
1699     if (type == PLUGIN_VST2 && (filenameCheck.endsWith(".vst") || filenameCheck.endsWith(".vst/")))
1700         openLib = false;
1701 #endif
1702 
1703     // ---------------------------------------------------------------------------------------------------------------
1704     // Initialize OS features
1705 
1706     // we want stuff in English so we can parse error messages
1707     ::setlocale(LC_ALL, "C");
1708 #ifndef CARLA_OS_WIN
1709     carla_setenv("LC_ALL", "C");
1710 #endif
1711 
1712 #ifdef CARLA_OS_WIN
1713     OleInitialize(nullptr);
1714     CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
1715 # ifndef __WINPTHREADS_VERSION
1716     // (non-portable) initialization of statically linked pthread library
1717     pthread_win32_process_attach_np();
1718     pthread_win32_thread_attach_np();
1719 # endif
1720 #endif
1721 
1722     // ---------------------------------------------------------------------------------------------------------------
1723 
1724     if (openLib)
1725     {
1726         handle = lib_open(filename);
1727 
1728         if (handle == nullptr)
1729         {
1730             print_lib_error(filename);
1731             return 1;
1732         }
1733     }
1734 
1735     // never do init for dssi-vst, takes too long and it's crashy
1736     bool doInit = ! filenameCheck.contains("dssi-vst", true);
1737 
1738     if (doInit && getenv("CARLA_DISCOVERY_NO_PROCESSING_CHECKS") != nullptr)
1739         doInit = false;
1740 
1741     // ---------------------------------------------------------------------------------------------------------------
1742 
1743     if (doInit && openLib && handle != nullptr)
1744     {
1745         // test fast loading & unloading DLL without initializing the plugin(s)
1746         if (! lib_close(handle))
1747         {
1748             print_lib_error(filename);
1749             return 1;
1750         }
1751 
1752         handle = lib_open(filename);
1753 
1754         if (handle == nullptr)
1755         {
1756             print_lib_error(filename);
1757             return 1;
1758         }
1759     }
1760 
1761 #ifndef BUILD_BRIDGE
1762     if (std::strcmp(filename, ":all") == 0)
1763     {
1764         do_cached_check(type);
1765         return 0;
1766     }
1767 #endif
1768 
1769 #ifdef CARLA_OS_MAC
1770     // Plugin might be in quarentine due to Apple stupid notarization rules, let's remove that if possible
1771     switch (type)
1772     {
1773     case PLUGIN_LADSPA:
1774     case PLUGIN_DSSI:
1775     case PLUGIN_VST2:
1776     case PLUGIN_VST3:
1777         removeFileFromQuarantine(filename);
1778         break;
1779     default:
1780         break;
1781     }
1782 #endif
1783 #ifdef USING_JUCE
1784     // some macOS plugins have not been yet ported to arm64, re-run them in x86_64 mode if discovery fails
1785     bool retryJucePlugin = false;
1786 #endif
1787 
1788     switch (type)
1789     {
1790     case PLUGIN_LADSPA:
1791         do_ladspa_check(handle, filename, doInit);
1792         break;
1793 
1794     case PLUGIN_DSSI:
1795         do_dssi_check(handle, filename, doInit);
1796         break;
1797 
1798 #ifndef BUILD_BRIDGE
1799     case PLUGIN_LV2:
1800         do_lv2_check(filename, doInit);
1801         break;
1802 #endif
1803 
1804     case PLUGIN_VST2:
1805 #if defined(USING_JUCE) && JUCE_PLUGINHOST_VST
1806         retryJucePlugin = do_juce_check(filename, "VST2", doInit);
1807 #else
1808         do_vst_check(handle, filename, doInit);
1809 #endif
1810         break;
1811 
1812     case PLUGIN_VST3:
1813 #if defined(USING_JUCE) && JUCE_PLUGINHOST_VST3
1814         retryJucePlugin = do_juce_check(filename, "VST3", doInit);
1815 #else
1816         DISCOVERY_OUT("error", "VST3 support not available");
1817 #endif
1818         break;
1819 
1820     case PLUGIN_AU:
1821 #if defined(USING_JUCE) && JUCE_PLUGINHOST_AU
1822         do_juce_check(filename, "AU", doInit);
1823 #else
1824         DISCOVERY_OUT("error", "AU support not available");
1825 #endif
1826          break;
1827 
1828     case PLUGIN_DLS:
1829     case PLUGIN_GIG:
1830     case PLUGIN_SF2:
1831         do_fluidsynth_check(filename, type, doInit);
1832         break;
1833 
1834     default:
1835         break;
1836     }
1837 
1838 #if defined(CARLA_OS_MAC) && defined(USING_JUCE) && defined(__aarch64__)
1839     if (retryJucePlugin)
1840     {
1841         DISCOVERY_OUT("warning", "No plugins found while scanning in arm64 mode, will try x86_64 now");
1842 
1843         cpu_type_t pref = CPU_TYPE_X86_64;
1844         pid_t pid = -1;
1845 
1846         posix_spawnattr_t attr;
1847         posix_spawnattr_init(&attr);
1848         CARLA_SAFE_ASSERT_RETURN(posix_spawnattr_setbinpref_np(&attr, 1, &pref, nullptr) == 0, 1);
1849         CARLA_SAFE_ASSERT_RETURN(posix_spawn(&pid, argv[0], nullptr, &attr, argv, nullptr) == 0, 1);
1850         posix_spawnattr_destroy(&attr);
1851 
1852         if (pid > 0)
1853         {
1854             int status;
1855             waitpid(pid, &status, 0);
1856         }
1857     }
1858 #endif
1859 
1860     if (openLib && handle != nullptr)
1861         lib_close(handle);
1862 
1863     // ---------------------------------------------------------------------------------------------------------------
1864 
1865 #ifdef CARLA_OS_WIN
1866 #ifndef __WINPTHREADS_VERSION
1867     pthread_win32_thread_detach_np();
1868     pthread_win32_process_detach_np();
1869 #endif
1870     CoUninitialize();
1871     OleUninitialize();
1872 #endif
1873 
1874     return 0;
1875 
1876 #ifdef USING_JUCE
1877     // might be unused
1878     (void)retryJucePlugin;
1879 #endif
1880 }
1881 
1882 // -------------------------------------------------------------------------------------------------------------------
1883