Browse Source

Import discovery fixes from main branch, allow IPC

Signed-off-by: falkTX <falktx@falktx.com>
tags/v2.5.5
falkTX 1 year ago
parent
commit
99364a2582
Signed by: falkTX <falktx@falktx.com> GPG Key ID: CDBAA37ABC74FBA0
2 changed files with 141 additions and 61 deletions
  1. +1
    -1
      source/discovery/Makefile
  2. +140
    -60
      source/discovery/carla-discovery.cpp

+ 1
- 1
source/discovery/Makefile View File

@@ -36,7 +36,7 @@ BUILD_CXX_FLAGS += -ObjC++
endif

ifeq ($(WINDOWS),true)
LINK_FLAGS += -lole32 -lssp -mwindows
LINK_FLAGS += -lole32 lws2_32 -mwindows
endif

ifeq ($(USING_JUCE),true)


+ 140
- 60
source/discovery/carla-discovery.cpp View File

@@ -1,6 +1,6 @@
/*
* Carla Plugin discovery
* Copyright (C) 2011-2022 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2011-2023 Filipe Coelho <falktx@falktx.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@@ -18,6 +18,7 @@
#include "CarlaBackendUtils.hpp"
#include "CarlaLibUtils.hpp"
#include "CarlaMathUtils.hpp"
#include "CarlaPipeUtils.cpp"
#include "CarlaScopeUtils.hpp"

#include "CarlaMIDI.h"
@@ -31,7 +32,7 @@

#ifdef CARLA_OS_MAC
# include "CarlaMacUtils.cpp"
# if defined(USING_JUCE) && defined(__aarch64__)
# ifdef __aarch64__
# include <spawn.h>
# endif
#endif
@@ -50,6 +51,7 @@
#endif

#include <iostream>
#include <sstream>

#include "water/files/File.h"

@@ -75,13 +77,15 @@
# pragma GCC diagnostic pop
#endif

#define DISCOVERY_OUT(x, y) std::cout << "\ncarla-discovery::" << x << "::" << y << std::endl;
#define DISCOVERY_OUT(x, y) \
if (gPipe != nullptr) { std::stringstream s; s << y; gPipe->writeDiscoveryMessage(x, s.str().c_str()); } \
else { std::cout << "\ncarla-discovery::" << x << "::" << y << std::endl; }

using water::File;

CARLA_BACKEND_USE_NAMESPACE

// -------------------------------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------
// Dummy values to test plugins with

static const uint32_t kBufferSize = 512;
@@ -89,7 +93,47 @@ static const double kSampleRate = 44100.0;
static const int32_t kSampleRatei = 44100;
static const float kSampleRatef = 44100.0f;

// -------------------------------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------
// Dynamic discovery

class DiscoveryPipe : public CarlaPipeClient
{
public:
DiscoveryPipe() {}

~DiscoveryPipe()
{
writeExitingMessageAndWait();
}

bool writeDiscoveryMessage(const char* const key, const char* const value) const noexcept
{
CARLA_SAFE_ASSERT_RETURN(key != nullptr && key[0] != '\0', false);
CARLA_SAFE_ASSERT_RETURN(value != nullptr, false);

const CarlaMutexLocker cml(pData->writeLock);

if (! writeAndFixMessage(key))
return false;
if (! writeAndFixMessage(value))
return false;

flushMessages();
return true;
}

protected:
bool msgReceived(const char* const msg) noexcept
{
carla_stdout("discovery msgReceived %s", msg);
return true;
}
};

CarlaScopedPointer<DiscoveryPipe> gPipe;


// --------------------------------------------------------------------------------------------------------------------
// Don't print ELF/EXE related errors since discovery can find multi-architecture binaries

static void print_lib_error(const char* const filename)
@@ -107,7 +151,8 @@ static void print_lib_error(const char* const filename)
}
}

// ------------------------------ Plugin Checks -----------------------------
// --------------------------------------------------------------------------------------------------------------------
// Plugin Checks

#ifndef BUILD_BRIDGE
static void print_cached_plugin(const CarlaCachedPluginInfo* const pinfo)
@@ -251,7 +296,6 @@ static void do_ladspa_check(lib_t& libHandle, const char* const filename, const
uint hints = 0x0;
uint audioIns = 0;
uint audioOuts = 0;
uint audioTotal = 0;
uint parametersIns = 0;
uint parametersOuts = 0;
uint parametersTotal = 0;
@@ -270,8 +314,6 @@ static void do_ladspa_check(lib_t& libHandle, const char* const filename, const
audioIns += 1;
else if (LADSPA_IS_PORT_OUTPUT(portDescriptor))
audioOuts += 1;

audioTotal += 1;
}
else if (LADSPA_IS_PORT_CONTROL(portDescriptor))
{
@@ -308,7 +350,7 @@ static void do_ladspa_check(lib_t& libHandle, const char* const filename, const
continue;
}

LADSPA_Data bufferAudio[kBufferSize][audioTotal];
LADSPA_Data bufferAudio[kBufferSize][std::max(1u, audioIns + audioOuts)];
LADSPA_Data bufferParams[parametersTotal];
LADSPA_Data min, max, def;

@@ -510,7 +552,6 @@ static void do_dssi_check(lib_t& libHandle, const char* const filename, const bo
uint hints = 0x0;
uint audioIns = 0;
uint audioOuts = 0;
uint audioTotal = 0;
uint midiIns = 0;
uint parametersIns = 0;
uint parametersOuts = 0;
@@ -530,8 +571,6 @@ static void do_dssi_check(lib_t& libHandle, const char* const filename, const bo
audioIns += 1;
else if (LADSPA_IS_PORT_OUTPUT(portDescriptor))
audioOuts += 1;

audioTotal += 1;
}
else if (LADSPA_IS_PORT_CONTROL(portDescriptor))
{
@@ -582,7 +621,7 @@ static void do_dssi_check(lib_t& libHandle, const char* const filename, const bo
continue;
}

LADSPA_Data bufferAudio[kBufferSize][audioTotal];
LADSPA_Data bufferAudio[kBufferSize][std::max(1u, audioIns + audioOuts)];
LADSPA_Data bufferParams[parametersTotal];
LADSPA_Data min, max, def;

@@ -797,7 +836,7 @@ static void do_lv2_check(const char* const bundle, const bool doInit)
#endif

#ifndef USING_JUCE_FOR_VST2
// -------------------------------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------
// VST stuff

// Check if plugin is currently processing
@@ -991,7 +1030,7 @@ static intptr_t VSTCALLBACK vstHostCallback(AEffect* const effect, const int32_t
return ret;
}

static void do_vst2_check(lib_t& libHandle, const char* const filename, const bool doInit)
static bool do_vst2_check(lib_t& libHandle, const char* const filename, const bool doInit)
{
VST_Function vstFn = nullptr;

@@ -1002,8 +1041,12 @@ static void do_vst2_check(lib_t& libHandle, const char* const filename, const bo
{
if (! bundleLoader.load(filename))
{
#ifdef __aarch64__
return true;
#else
DISCOVERY_OUT("error", "Failed to load VST2 bundle executable");
return;
return false;
#endif
}

vstFn = (VST_Function)CFBundleGetFunctionPointerForName(bundleLoader.getRef(), CFSTR("main_macho"));
@@ -1014,7 +1057,7 @@ static void do_vst2_check(lib_t& libHandle, const char* const filename, const bo
if (vstFn == nullptr)
{
DISCOVERY_OUT("error", "Not a VST2 plugin");
return;
return false;
}
}
else
@@ -1029,7 +1072,7 @@ static void do_vst2_check(lib_t& libHandle, const char* const filename, const bo
if (vstFn == nullptr)
{
DISCOVERY_OUT("error", "Not a VST plugin");
return;
return false;
}
}
}
@@ -1039,7 +1082,7 @@ static void do_vst2_check(lib_t& libHandle, const char* const filename, const bo
if (effect == nullptr || effect->magic != kEffectMagic)
{
DISCOVERY_OUT("error", "Failed to init VST plugin, or VST magic failed");
return;
return false;
}

if (effect->uniqueID == 0)
@@ -1064,7 +1107,7 @@ static void do_vst2_check(lib_t& libHandle, const char* const filename, const bo
{
DISCOVERY_OUT("error", "Plugin doesn't have an Unique ID after being open");
effect->dispatcher(effect, effClose, 0, 0, nullptr, 0.0f);
return;
return false;
}

gVstCurrentUniqueId = effect->uniqueID;
@@ -1340,9 +1383,9 @@ static void do_vst2_check(lib_t& libHandle, const char* const filename, const bo
effect->dispatcher(effect, effClose, 0, 0, nullptr, 0.0f);
}

#ifndef CARLA_OS_MAC
return;
return false;

#ifndef CARLA_OS_MAC
// unused
(void)filename;
#endif
@@ -1447,7 +1490,13 @@ struct carla_v3_event_list : v3_event_list_cpp {
static v3_result V3_API carla_add_event(void*, v3_event*) { return V3_NOT_IMPLEMENTED; }
};

static void do_vst3_check(lib_t& libHandle, const char* const filename, const bool doInit)
static bool v3_exit_false(const V3_EXITFN v3_exit)
{
v3_exit();
return false;
}

static bool do_vst3_check(lib_t& libHandle, const char* const filename, const bool doInit)
{
V3_ENTRYFN v3_entry = nullptr;
V3_EXITFN v3_exit = nullptr;
@@ -1463,8 +1512,12 @@ static void do_vst3_check(lib_t& libHandle, const char* const filename, const bo
#ifdef CARLA_OS_MAC
if (! bundleLoader.load(filename))
{
#ifdef __aarch64__
return true;
#else
DISCOVERY_OUT("error", "Failed to load VST3 bundle executable");
return;
return false;
#endif
}

v3_entry = (V3_ENTRYFN)CFBundleGetFunctionPointerForName(bundleLoader.getRef(), CFSTR(V3_ENTRYFNNAME));
@@ -1487,7 +1540,7 @@ static void do_vst3_check(lib_t& libHandle, const char* const filename, const bo
if (! water::File(binaryfilename).existsAsFile())
{
DISCOVERY_OUT("error", "Failed to find a suitable VST3 bundle binary");
return;
return false;
}

libHandle = lib_open(binaryfilename.toRawUTF8());
@@ -1495,7 +1548,7 @@ static void do_vst3_check(lib_t& libHandle, const char* const filename, const bo
if (libHandle == nullptr)
{
print_lib_error(filename);
return;
return false;
}
#endif
}
@@ -1510,7 +1563,7 @@ static void do_vst3_check(lib_t& libHandle, const char* const filename, const bo
if (v3_entry == nullptr || v3_exit == nullptr || v3_get == nullptr)
{
DISCOVERY_OUT("error", "Not a VST3 plugin");
return;
return false;
}

// call entry point
@@ -1528,21 +1581,21 @@ static void do_vst3_check(lib_t& libHandle, const char* const filename, const bo

// fetch initial factory
v3_plugin_factory** factory1 = v3_get();
CARLA_SAFE_ASSERT_RETURN(factory1 != nullptr, v3_exit());
CARLA_SAFE_ASSERT_RETURN(factory1 != nullptr, v3_exit_false(v3_exit));

// get factory info
v3_factory_info factoryInfo = {};
CARLA_SAFE_ASSERT_RETURN(v3_cpp_obj(factory1)->get_factory_info(factory1, &factoryInfo) == V3_OK, v3_exit());
CARLA_SAFE_ASSERT_RETURN(v3_cpp_obj(factory1)->get_factory_info(factory1, &factoryInfo) == V3_OK, v3_exit_false(v3_exit));

// get num classes
const int32_t numClasses = v3_cpp_obj(factory1)->num_classes(factory1);
CARLA_SAFE_ASSERT_RETURN(numClasses > 0, v3_exit());
CARLA_SAFE_ASSERT_RETURN(numClasses > 0, v3_exit_false(v3_exit));

// query 2nd factory
v3_plugin_factory_2** factory2 = nullptr;
if (v3_cpp_obj_query_interface(factory1, v3_plugin_factory_2_iid, &factory2) == V3_OK)
{
CARLA_SAFE_ASSERT_RETURN(factory2 != nullptr, v3_exit());
CARLA_SAFE_ASSERT_RETURN(factory2 != nullptr, v3_exit_false(v3_exit));
}
else
{
@@ -1554,7 +1607,7 @@ static void do_vst3_check(lib_t& libHandle, const char* const filename, const bo
v3_plugin_factory_3** factory3 = nullptr;
if (factory2 != nullptr && v3_cpp_obj_query_interface(factory2, v3_plugin_factory_3_iid, &factory3) == V3_OK)
{
CARLA_SAFE_ASSERT_RETURN(factory3 != nullptr, v3_exit());
CARLA_SAFE_ASSERT_RETURN(factory3 != nullptr, v3_exit_false(v3_exit));
}
else
{
@@ -1842,11 +1895,12 @@ static void do_vst3_check(lib_t& libHandle, const char* const filename, const bo
v3_cpp_obj_unref(factory1);

v3_exit();
return false;
}
#endif // ! USING_JUCE_FOR_VST3

#ifdef USING_JUCE
// -------------------------------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------
// find all available plugin audio ports

static void findMaxTotalChannels(juce::AudioProcessor* const filter, int& maxTotalIns, int& maxTotalOuts)
@@ -1873,7 +1927,7 @@ static void findMaxTotalChannels(juce::AudioProcessor* const filter, int& maxTot
}
}

// -------------------------------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------

static bool do_juce_check(const char* const filename_, const char* const stype, const bool doInit)
{
@@ -1942,10 +1996,10 @@ static bool do_juce_check(const char* const filename_, const char* const stype,

if (results.size() == 0)
{
#if defined(CARLA_OS_MAC) && defined(__aarch64__)
#if defined(CARLA_OS_MAC) && defined(__aarch64__)
if (std::strcmp(stype, "VST2") == 0 || std::strcmp(stype, "VST3") == 0)
return true;
#endif
#endif
DISCOVERY_OUT("error", "No plugins found");
return false;
}
@@ -2114,7 +2168,7 @@ static void do_fluidsynth_check(const char* const filename, const PluginType typ
#endif
}

// -------------------------------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------

#ifndef BUILD_BRIDGE
static void do_jsfx_check(const char* const filename, bool doInit)
@@ -2177,9 +2231,9 @@ static void do_jsfx_check(const char* const filename, bool doInit)

// ------------------------------ main entry point ------------------------------

int main(int argc, char* argv[])
int main(int argc, const char* argv[])
{
if (argc != 3)
if (argc != 3 && argc != 7)
{
carla_stdout("usage: %s <type> </path/to/plugin>", argv[0]);
return 1;
@@ -2192,20 +2246,38 @@ int main(int argc, char* argv[])
CarlaString filenameCheck(filename);
filenameCheck.toLower();

bool openLib = false;
bool openLib;
lib_t handle = nullptr;

switch (type)
{
case PLUGIN_LADSPA:
case PLUGIN_DSSI:
// only available as single binary
openLib = true;
break;

case PLUGIN_VST2:
#ifdef CARLA_OS_MAC
// bundle on macOS
openLib = false;
#else
// single binary on all else
openLib = true;
#endif
break;
case PLUGIN_VST3:
#ifdef CARLA_OS_WIN
// either file or bundle on Windows
openLib = water::File(filename).existsAsFile();
#else
// bundle on all else
openLib = false;
#endif
break;

default:
openLib = false;
break;
}

@@ -2239,6 +2311,18 @@ int main(int argc, char* argv[])
# endif
#endif

// ---------------------------------------------------------------------------------------------------------------
// Initialize pipe

if (argc == 7)
{
gPipe = new DiscoveryPipe;

if (! gPipe->initPipeClient(argv))
return 1;
}


// ---------------------------------------------------------------------------------------------------------------

if (openLib)
@@ -2300,10 +2384,9 @@ int main(int argc, char* argv[])
break;
}
#endif
#ifdef USING_JUCE
// some macOS plugins have not been yet ported to arm64, re-run them in x86_64 mode if discovery fails
bool retryJucePlugin = false;
#endif
bool retryAsX64lugin = false;

switch (type)
{
@@ -2323,17 +2406,17 @@ int main(int argc, char* argv[])

case PLUGIN_VST2:
#if defined(USING_JUCE) && JUCE_PLUGINHOST_VST
retryJucePlugin = do_juce_check(filename, "VST2", doInit);
retryAsX64lugin = do_juce_check(filename, "VST2", doInit);
#else
do_vst2_check(handle, filename, doInit);
retryAsX64lugin = do_vst2_check(handle, filename, doInit);
#endif
break;

case PLUGIN_VST3:
#if defined(USING_JUCE) && JUCE_PLUGINHOST_VST3
retryJucePlugin = do_juce_check(filename, "VST3", doInit);
retryAsX64lugin = do_juce_check(filename, "VST3", doInit);
#else
do_vst3_check(handle, filename, doInit);
retryAsX64lugin = do_vst3_check(handle, filename, doInit);
#endif
break;

@@ -2361,9 +2444,12 @@ int main(int argc, char* argv[])
break;
}

#if defined(CARLA_OS_MAC) && defined(USING_JUCE) && defined(__aarch64__)
if (retryJucePlugin)
if (openLib && handle != nullptr)
lib_close(handle);

if (retryAsX64lugin)
{
#if defined(CARLA_OS_MAC) && defined(__aarch64__)
DISCOVERY_OUT("warning", "No plugins found while scanning in arm64 mode, will try x86_64 now");

cpu_type_t pref = CPU_TYPE_X86_64;
@@ -2372,7 +2458,7 @@ int main(int argc, char* argv[])
posix_spawnattr_t attr;
posix_spawnattr_init(&attr);
CARLA_SAFE_ASSERT_RETURN(posix_spawnattr_setbinpref_np(&attr, 1, &pref, nullptr) == 0, 1);
CARLA_SAFE_ASSERT_RETURN(posix_spawn(&pid, argv[0], nullptr, &attr, argv, nullptr) == 0, 1);
CARLA_SAFE_ASSERT_RETURN(posix_spawn(&pid, argv[0], nullptr, &attr, (char* const*)argv, nullptr) == 0, 1);
posix_spawnattr_destroy(&attr);

if (pid > 0)
@@ -2380,11 +2466,10 @@ int main(int argc, char* argv[])
int status;
waitpid(pid, &status, 0);
}
#endif
}
#endif

if (openLib && handle != nullptr)
lib_close(handle);
gPipe = nullptr;

// ---------------------------------------------------------------------------------------------------------------

@@ -2398,11 +2483,6 @@ int main(int argc, char* argv[])
#endif

return 0;

#ifdef USING_JUCE
// might be unused
(void)retryJucePlugin;
#endif
}

// -------------------------------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------

Loading…
Cancel
Save