diff --git a/source/backend/CarlaHost.h b/source/backend/CarlaHost.h
index b57711547..989ffa169 100644
--- a/source/backend/CarlaHost.h
+++ b/source/backend/CarlaHost.h
@@ -142,82 +142,6 @@ typedef struct _CarlaPluginInfo {
} CarlaPluginInfo;
-/*!
- * Information about a cached plugin.
- * @see carla_get_cached_plugin_info()
- */
-typedef struct _CarlaCachedPluginInfo {
- /*!
- * Plugin category.
- */
- PluginCategory category;
-
- /*!
- * Plugin hints.
- * @see PluginHints
- */
- uint hints;
-
- /*!
- * Number of audio inputs.
- */
- uint32_t audioIns;
-
- /*!
- * Number of audio outputs.
- */
- uint32_t audioOuts;
-
- /*!
- * Number of MIDI inputs.
- */
- uint32_t midiIns;
-
- /*!
- * Number of MIDI outputs.
- */
- uint32_t midiOuts;
-
- /*!
- * Number of input parameters.
- */
- uint32_t parameterIns;
-
- /*!
- * Number of output parameters.
- */
- uint32_t parameterOuts;
-
- /*!
- * Plugin name.
- */
- const char* name;
-
- /*!
- * Plugin label.
- */
- const char* label;
-
- /*!
- * Plugin author/maker.
- */
- const char* maker;
-
- /*!
- * Plugin copyright/license.
- */
- const char* copyright;
-
-#ifdef __cplusplus
- /*!
- * C++ constructor.
- */
- CARLA_API _CarlaCachedPluginInfo() noexcept;
- CARLA_DECLARE_NON_COPY_STRUCT(_CarlaCachedPluginInfo)
-#endif
-
-} CarlaCachedPluginInfo;
-
/*!
* Port count information, used for Audio and MIDI ports and parameters.
* @see carla_get_audio_port_count_info()
@@ -347,26 +271,6 @@ typedef struct _CarlaTransportInfo {
/* ------------------------------------------------------------------------------------------------------------
* Carla Host API (C functions) */
-/*!
- * Get the complete license text of used third-party code and features.
- * Returned string is in basic html format.
- */
-CARLA_EXPORT const char* carla_get_complete_license_text();
-
-/*!
- * Get the juce version used in the current Carla build.
- */
-CARLA_EXPORT const char* carla_get_juce_version();
-
-/*!
- * Get all the supported file extensions in carla_load_file().
- * Returned string uses this syntax:
- * @code
- * "*.ext1;*.ext2;*.ext3"
- * @endcode
- */
-CARLA_EXPORT const char* carla_get_supported_file_extensions();
-
/*!
* Get how many engine drivers are available.
*/
@@ -391,18 +295,6 @@ CARLA_EXPORT const char* const* carla_get_engine_driver_device_names(uint index)
*/
CARLA_EXPORT const EngineDriverDeviceInfo* carla_get_engine_driver_device_info(uint index, const char* name);
-/*!
- * Get how many cached plugins are available.
- * Internal, LV2 and AU plugin formats are cached and need to be discovered via this function.
- * Do not call this for any other plugin formats.
- */
-CARLA_EXPORT uint carla_get_cached_plugin_count(PluginType ptype, const char* pluginPath);
-
-/*!
- * Get information about a cached plugin.
- */
-CARLA_EXPORT const CarlaCachedPluginInfo* carla_get_cached_plugin_info(PluginType ptype, uint index);
-
#ifdef __cplusplus
/*!
* Get the currently used engine, maybe be NULL.
@@ -995,12 +887,12 @@ CARLA_EXPORT const char* carla_get_host_osc_url_tcp();
CARLA_EXPORT const char* carla_get_host_osc_url_udp();
/*!
- * Get the current carla library filename.
+ * Get the absolute filename of this carla library.
*/
CARLA_EXPORT const char* carla_get_library_filename();
/*!
- * Get the folder where the current use carla library resides.
+ * Get the folder where this carla library resides.
*/
CARLA_EXPORT const char* carla_get_library_folder();
diff --git a/source/backend/CarlaHostCommon.cpp b/source/backend/CarlaHostCommon.cpp
index e3f544bf1..65547a378 100644
--- a/source/backend/CarlaHostCommon.cpp
+++ b/source/backend/CarlaHostCommon.cpp
@@ -16,19 +16,8 @@
*/
#include "CarlaHost.h"
-#include "CarlaNative.h"
-#include "CarlaLv2Utils.hpp"
-#include "CarlaPlugin.hpp"
-#include "CarlaString.hpp"
-
-#include "juce_audio_formats.h"
-
-#ifdef CARLA_OS_MAC
-# include "juce_audio_processors.h"
-using juce::AudioUnitPluginFormat;
-using juce::StringArray;
-#endif
+#include "juce_core.h"
namespace CB = CarlaBackend;
@@ -72,20 +61,6 @@ _CarlaPluginInfo::~_CarlaPluginInfo() noexcept
delete[] copyright;
}
-_CarlaCachedPluginInfo::_CarlaCachedPluginInfo() noexcept
- : category(CB::PLUGIN_CATEGORY_NONE),
- hints(0x0),
- audioIns(0),
- audioOuts(0),
- midiIns(0),
- midiOuts(0),
- parameterIns(0),
- parameterOuts(0),
- name(gNullCharPtr),
- label(gNullCharPtr),
- maker(gNullCharPtr),
- copyright(gNullCharPtr) {}
-
_CarlaParameterInfo::_CarlaParameterInfo() noexcept
: name(gNullCharPtr),
symbol(gNullCharPtr),
@@ -122,592 +97,6 @@ _CarlaTransportInfo::_CarlaTransportInfo() noexcept
// -------------------------------------------------------------------------------------------------------------------
-const char* carla_get_complete_license_text()
-{
- carla_debug("carla_get_complete_license_text()");
-
- static CarlaString retText;
-
- if (retText.isEmpty())
- {
- retText =
- "
This current Carla build is using the following features and 3rd-party code:
"
- ""
-
- // Plugin formats
- "- LADSPA plugin support
"
- "- DSSI plugin support
"
- "- LV2 plugin support
"
-#ifdef VESTIGE_HEADER
- "- VST2 plugin support using VeSTige header by Javier Serrano Polo
"
-#else
- "- VST2 plugin support using official VST SDK 2.4 [1]
"
-#endif
-#if defined(CARLA_OS_MAC) || defined(CARLA_OS_WIN)
- "- VST3 plugin support using official VST SDK 3.6 [1]
"
-#endif
-#ifdef CARLA_OS_MAC
- "- AU plugin support
"
-#endif
-
- // Sample kit libraries
-#ifdef HAVE_FLUIDSYNTH
- "- FluidSynth library for SF2 support
"
-#endif
-#ifdef HAVE_LINUXSAMPLER
- "- LinuxSampler library for GIG and SFZ support [2]
"
-#endif
-
- // Internal plugins
- "- NekoFilter plugin code based on lv2fil by Nedko Arnaudov and Fons Adriaensen
"
-#ifdef WANT_ZYNADDSUBFX
- "- ZynAddSubFX plugin code
"
-#endif
-
- // misc libs
- "- base64 utilities based on code by Ren\u00E9 Nyffenegger
"
-#ifdef CARLA_OS_MAC
- "- sem_timedwait for Mac OS by Keith Shortridge
"
-#endif
- "- liblo library for OSC support
"
- "- rtmempool library by Nedko Arnaudov"
- "
- serd, sord, sratom and lilv libraries for LV2 discovery
"
-#if ! (defined(CARLA_OS_MAC) || defined(CARLA_OS_WIN))
- "- RtAudio and RtMidi libraries for extra Audio and MIDI support
"
-#endif
-
- // end
- "
"
-
- ""
-#if defined(CARLA_OS_MAC) || defined(CARLA_OS_WIN) || ! defined(VESTIGE_HEADER)
- // Required by VST SDK
- " [1] Trademark of Steinberg Media Technologies GmbH.
"
-#endif
-#ifdef HAVE_LINUXSAMPLER
- // LinuxSampler GPL exception
- " [2] Using LinuxSampler code in commercial hardware or software products is not allowed without prior written authorization by the authors."
-#endif
- "
"
- ;
- }
-
- return retText;
-}
-
-const char* carla_get_juce_version()
-{
- carla_debug("carla_get_juce_version()");
-
- static CarlaString retVersion;
-
- if (retVersion.isEmpty())
- {
- if (const char* const version = juce::SystemStats::getJUCEVersion().toRawUTF8())
- retVersion = version+6;
- else
- retVersion = "3.0";
- }
-
- return retVersion;
-}
-
-const char* carla_get_supported_file_extensions()
-{
- carla_debug("carla_get_supported_file_extensions()");
-
- static CarlaString retText;
-
- if (retText.isEmpty())
- {
- retText =
- // Base types
- "*.carxp;*.carxs"
- // MIDI files
- ";*.mid;*.midi"
-#ifdef HAVE_FLUIDSYNTH
- // fluidsynth (sf2)
- ";*.sf2"
-#endif
-#ifdef HAVE_LINUXSAMPLER
- // linuxsampler (gig and sfz)
- ";*.gig;*.sfz"
-#endif
-#ifdef WANT_ZYNADDSUBFX
- // zynaddsubfx presets
- ";*.xmz;*.xiz"
-#endif
- ;
-
-#ifndef BUILD_BRIDGE
- // Audio files
- {
- using namespace juce;
-
- AudioFormatManager afm;
- afm.registerBasicFormats();
-
- String juceFormats;
-
- for (AudioFormat **it=afm.begin(), **end=afm.end(); it != end; ++it)
- {
- const StringArray& exts((*it)->getFileExtensions());
-
- for (String *eit=exts.begin(), *eend=exts.end(); eit != eend; ++eit)
- juceFormats += String(";*" + (*eit)).toRawUTF8();
- }
-
- retText += juceFormats.toRawUTF8();
- }
-#endif
- }
-
- return retText;
-}
-
-// -------------------------------------------------------------------------------------------------------------------
-
-#ifdef CARLA_OS_MAC
-static StringArray gCachedAuPluginResults;
-#endif
-
-uint carla_get_cached_plugin_count(PluginType ptype, const char* pluginPath)
-{
- CARLA_SAFE_ASSERT_RETURN(ptype == CB::PLUGIN_INTERNAL || ptype == CB::PLUGIN_LV2 || ptype == CB::PLUGIN_AU, 0);
- carla_debug("carla_get_cached_plugin_count(%i:%s)", ptype, CB::PluginType2Str(ptype));
-
- switch (ptype)
- {
- case CB::PLUGIN_INTERNAL: {
-#ifndef BUILD_BRIDGE
- return static_cast(CarlaPlugin::getNativePluginCount());
-#else
- return 0;
-#endif
- }
-
- case CB::PLUGIN_LV2: {
- Lv2WorldClass& lv2World(Lv2WorldClass::getInstance());
- lv2World.initIfNeeded(pluginPath);
- return lv2World.getPluginCount();
- }
-
- case CB::PLUGIN_AU: {
-#ifdef CARLA_OS_MAC
- static bool initiated = false;
-
- if (initiated)
- return static_cast(gCachedAuPluginResults.size());
-
- initiated = true;
- AudioUnitPluginFormat auFormat;
- gCachedAuPluginResults = auFormat.searchPathsForPlugins(juce::FileSearchPath(), false);
-
- return static_cast(gCachedAuPluginResults.size());
-#else
- return 0;
-#endif
- }
-
- default:
- return 0;
- }
-}
-
-const CarlaCachedPluginInfo* carla_get_cached_plugin_info(PluginType ptype, uint index)
-{
- carla_debug("carla_get_cached_plugin_info(%i:%s, %i)", ptype, CB::PluginType2Str(ptype), index);
-
- static CarlaCachedPluginInfo info;
-
- switch (ptype)
- {
- case CB::PLUGIN_INTERNAL: {
-#ifndef BUILD_BRIDGE
- const NativePluginDescriptor* const desc(CarlaPlugin::getNativePluginDescriptor(index));
- CARLA_SAFE_ASSERT_BREAK(desc != nullptr);
-
- info.category = static_cast(desc->category);
- info.hints = 0x0;
-
- if (desc->hints & NATIVE_PLUGIN_IS_RTSAFE)
- info.hints |= CB::PLUGIN_IS_RTSAFE;
- if (desc->hints & NATIVE_PLUGIN_IS_SYNTH)
- info.hints |= CB::PLUGIN_IS_SYNTH;
- if (desc->hints & NATIVE_PLUGIN_HAS_UI)
- info.hints |= CB::PLUGIN_HAS_CUSTOM_UI;
- if (desc->hints & NATIVE_PLUGIN_NEEDS_FIXED_BUFFERS)
- info.hints |= CB::PLUGIN_NEEDS_FIXED_BUFFERS;
- if (desc->hints & NATIVE_PLUGIN_NEEDS_SINGLE_THREAD)
- info.hints |= CB::PLUGIN_NEEDS_SINGLE_THREAD;
-
- info.audioIns = desc->audioIns;
- info.audioOuts = desc->audioOuts;
- info.midiIns = desc->midiIns;
- info.midiOuts = desc->midiOuts;
- info.parameterIns = desc->paramIns;
- info.parameterOuts = desc->paramOuts;
- info.name = desc->name;
- info.label = desc->label;
- info.maker = desc->maker;
- info.copyright = desc->copyright;
- return &info;
-#else
- break;
-#endif
- }
-
- case CB::PLUGIN_LV2: {
- Lv2WorldClass& lv2World(Lv2WorldClass::getInstance());
-
- const LilvPlugin* const cPlugin(lv2World.getPluginFromIndex(index));
- CARLA_SAFE_ASSERT_BREAK(cPlugin != nullptr);
-
- Lilv::Plugin lilvPlugin(cPlugin);
- CARLA_SAFE_ASSERT_BREAK(lilvPlugin.get_uri().is_uri());
-
- carla_stdout("Filling info for LV2 with URI '%s'", lilvPlugin.get_uri().as_uri());
-
- // features
- info.hints = 0x0;
-
- if (lilvPlugin.get_uis().size() > 0 || lilvPlugin.get_modgui_resources_directory().as_uri() != nullptr)
- info.hints |= CB::PLUGIN_HAS_CUSTOM_UI;
-
- {
- Lilv::Nodes lilvFeatureNodes(lilvPlugin.get_supported_features());
-
- LILV_FOREACH(nodes, it, lilvFeatureNodes)
- {
- Lilv::Node lilvFeatureNode(lilvFeatureNodes.get(it));
- const char* const featureURI(lilvFeatureNode.as_uri());
- CARLA_SAFE_ASSERT_CONTINUE(featureURI != nullptr);
-
- if (std::strcmp(featureURI, LV2_CORE__hardRTCapable) == 0)
- info.hints |= CB::PLUGIN_IS_RTSAFE;
- }
-
- lilv_nodes_free(const_cast(lilvFeatureNodes.me));
- }
-
- // category
- info.category = CB::PLUGIN_CATEGORY_NONE;
-
- {
- Lilv::Nodes typeNodes(lilvPlugin.get_value(lv2World.rdf_type));
-
- if (typeNodes.size() > 0)
- {
- if (typeNodes.contains(lv2World.class_allpass))
- info.category = CB::PLUGIN_CATEGORY_FILTER;
- if (typeNodes.contains(lv2World.class_amplifier))
- info.category = CB::PLUGIN_CATEGORY_DYNAMICS;
- if (typeNodes.contains(lv2World.class_analyzer))
- info.category = CB::PLUGIN_CATEGORY_UTILITY;
- if (typeNodes.contains(lv2World.class_bandpass))
- info.category = CB::PLUGIN_CATEGORY_FILTER;
- if (typeNodes.contains(lv2World.class_chorus))
- info.category = CB::PLUGIN_CATEGORY_MODULATOR;
- if (typeNodes.contains(lv2World.class_comb))
- info.category = CB::PLUGIN_CATEGORY_FILTER;
- if (typeNodes.contains(lv2World.class_compressor))
- info.category = CB::PLUGIN_CATEGORY_DYNAMICS;
- if (typeNodes.contains(lv2World.class_constant))
- info.category = CB::PLUGIN_CATEGORY_OTHER;
- if (typeNodes.contains(lv2World.class_converter))
- info.category = CB::PLUGIN_CATEGORY_UTILITY;
- if (typeNodes.contains(lv2World.class_delay))
- info.category = CB::PLUGIN_CATEGORY_DELAY;
- if (typeNodes.contains(lv2World.class_distortion))
- info.category = CB::PLUGIN_CATEGORY_DISTORTION;
- if (typeNodes.contains(lv2World.class_dynamics))
- info.category = CB::PLUGIN_CATEGORY_DYNAMICS;
- if (typeNodes.contains(lv2World.class_eq))
- info.category = CB::PLUGIN_CATEGORY_EQ;
- if (typeNodes.contains(lv2World.class_envelope))
- info.category = CB::PLUGIN_CATEGORY_DYNAMICS;
- if (typeNodes.contains(lv2World.class_expander))
- info.category = CB::PLUGIN_CATEGORY_DYNAMICS;
- if (typeNodes.contains(lv2World.class_filter))
- info.category = CB::PLUGIN_CATEGORY_FILTER;
- if (typeNodes.contains(lv2World.class_flanger))
- info.category = CB::PLUGIN_CATEGORY_MODULATOR;
- if (typeNodes.contains(lv2World.class_function))
- info.category = CB::PLUGIN_CATEGORY_UTILITY;
- if (typeNodes.contains(lv2World.class_gate))
- info.category = CB::PLUGIN_CATEGORY_DYNAMICS;
- if (typeNodes.contains(lv2World.class_generator))
- info.category = CB::PLUGIN_CATEGORY_OTHER;
- if (typeNodes.contains(lv2World.class_highpass))
- info.category = CB::PLUGIN_CATEGORY_FILTER;
- if (typeNodes.contains(lv2World.class_limiter))
- info.category = CB::PLUGIN_CATEGORY_DYNAMICS;
- if (typeNodes.contains(lv2World.class_lowpass))
- info.category = CB::PLUGIN_CATEGORY_FILTER;
- if (typeNodes.contains(lv2World.class_mixer))
- info.category = CB::PLUGIN_CATEGORY_UTILITY;
- if (typeNodes.contains(lv2World.class_modulator))
- info.category = CB::PLUGIN_CATEGORY_MODULATOR;
- if (typeNodes.contains(lv2World.class_multiEQ))
- info.category = CB::PLUGIN_CATEGORY_EQ;
- if (typeNodes.contains(lv2World.class_oscillator))
- info.category = CB::PLUGIN_CATEGORY_OTHER;
- if (typeNodes.contains(lv2World.class_paraEQ))
- info.category = CB::PLUGIN_CATEGORY_EQ;
- if (typeNodes.contains(lv2World.class_phaser))
- info.category = CB::PLUGIN_CATEGORY_MODULATOR;
- if (typeNodes.contains(lv2World.class_pitch))
- info.category = CB::PLUGIN_CATEGORY_OTHER;
- if (typeNodes.contains(lv2World.class_reverb))
- info.category = CB::PLUGIN_CATEGORY_DELAY;
- if (typeNodes.contains(lv2World.class_simulator))
- info.category = CB::PLUGIN_CATEGORY_OTHER;
- if (typeNodes.contains(lv2World.class_spatial))
- info.category = CB::PLUGIN_CATEGORY_OTHER;
- if (typeNodes.contains(lv2World.class_spectral))
- info.category = CB::PLUGIN_CATEGORY_OTHER;
- if (typeNodes.contains(lv2World.class_utility))
- info.category = CB::PLUGIN_CATEGORY_UTILITY;
- if (typeNodes.contains(lv2World.class_waveshaper))
- info.category = CB::PLUGIN_CATEGORY_DISTORTION;
- if (typeNodes.contains(lv2World.class_instrument))
- {
- info.category = CB::PLUGIN_CATEGORY_SYNTH;
- info.hints |= CB::PLUGIN_IS_SYNTH;
- }
- }
-
- lilv_nodes_free(const_cast(typeNodes.me));
- }
-
- // number data
- info.audioIns = 0;
- info.audioOuts = 0;
- info.midiIns = 0;
- info.midiOuts = 0;
- info.parameterIns = 0;
- info.parameterOuts = 0;
-
- for (uint i=0, count=lilvPlugin.get_num_ports(); i(supportNodes.me));
- }
- else if (lilvPort.is_a(lv2World.port_event))
- {
- if (lilvPort.supports_event(lv2World.midi_event))
- {
- if (isInput)
- ++(info.midiIns);
- else
- ++(info.midiOuts);
- }
- }
- else if (lilvPort.is_a(lv2World.port_midi))
- {
- if (isInput)
- ++(info.midiIns);
- else
- ++(info.midiOuts);
- }
- }
-
- // text data
- static CarlaString suri, sname, smaker, slicense;
- suri.clear(); sname.clear(); smaker.clear(); slicense.clear();
-
- suri = lilvPlugin.get_uri().as_uri();
-
- if (const char* const name = lilvPlugin.get_name().as_string())
- sname = name;
- else
- sname.clear();
-
- if (const char* const author = lilvPlugin.get_author_name().as_string())
- smaker = author;
- else
- smaker.clear();
-
- Lilv::Nodes licenseNodes(lilvPlugin.get_value(lv2World.doap_license));
-
- if (licenseNodes.size() > 0)
- {
- if (const char* const license = licenseNodes.get_first().as_string())
- slicense = license;
- }
-
- lilv_nodes_free(const_cast(licenseNodes.me));
-
- info.name = sname;
- info.label = suri;
- info.maker = smaker;
- info.copyright = slicense;
-
- return &info;
- }
-
- case CB::PLUGIN_AU: {
-#ifdef CARLA_OS_MAC
- const int indexi(static_cast(index));
- CARLA_SAFE_ASSERT_BREAK(indexi < gCachedAuPluginResults.size());
-
- using namespace juce;
-
- String pluginId(gCachedAuPluginResults[indexi]);
- OwnedArray results;
-
- AudioUnitPluginFormat auFormat;
- auFormat.findAllTypesForFile(results, pluginId);
- CARLA_SAFE_ASSERT_BREAK(results.size() > 0);
- CARLA_SAFE_ASSERT(results.size() == 1);
-
- PluginDescription* const desc(results[0]);
- CARLA_SAFE_ASSERT_BREAK(desc != nullptr);
-
- info.category = CB::getPluginCategoryFromName(desc->category.toRawUTF8());
- info.hints = 0x0;
-
- if (desc->isInstrument)
- info.hints |= CB::PLUGIN_IS_SYNTH;
- if (true)
- info.hints |= CB::PLUGIN_HAS_CUSTOM_UI;
-
- info.audioIns = static_cast(desc->numInputChannels);
- info.audioOuts = static_cast(desc->numOutputChannels);
- info.midiIns = desc->isInstrument ? 1 : 0;
- info.midiOuts = 0;
- info.parameterIns = 0;
- info.parameterOuts = 0;
-
- static CarlaString sname, slabel, smaker;
-
- sname = desc->name.toRawUTF8();
- slabel = desc->fileOrIdentifier.toRawUTF8();
- smaker = desc->manufacturerName.toRawUTF8();
-
- info.name = sname;
- info.label = slabel;
- info.maker = smaker;
- info.copyright = gNullCharPtr;
-
- return &info;
-#else
- break;
-#endif
- }
-
- default:
- break;
- }
-
- info.category = CB::PLUGIN_CATEGORY_NONE;
- info.hints = 0x0;
- info.audioIns = 0;
- info.audioOuts = 0;
- info.midiIns = 0;
- info.midiOuts = 0;
- info.parameterIns = 0;
- info.parameterOuts = 0;
- info.name = gNullCharPtr;
- info.label = gNullCharPtr;
- info.maker = gNullCharPtr;
- info.copyright = gNullCharPtr;
- return &info;
-}
-
-// -------------------------------------------------------------------------------------------------------------------
-
const char* carla_get_library_filename()
{
carla_debug("carla_get_library_filename()");
diff --git a/source/backend/CarlaPlugin.hpp b/source/backend/CarlaPlugin.hpp
index 27ad8357a..a93f0dbe6 100644
--- a/source/backend/CarlaPlugin.hpp
+++ b/source/backend/CarlaPlugin.hpp
@@ -889,9 +889,6 @@ public:
const int64_t uniqueId;
};
- static std::size_t getNativePluginCount() noexcept;
- static const NativePluginDescriptor* getNativePluginDescriptor(const std::size_t index) noexcept;
-
static CarlaPlugin* newNative(const Initializer& init);
static CarlaPlugin* newBridge(const Initializer& init, const BinaryType btype, const PluginType ptype, const char* const bridgeBinary);
diff --git a/source/backend/CarlaUtils.cpp b/source/backend/CarlaUtils.cpp
index bb8e543de..86620b76f 100644
--- a/source/backend/CarlaUtils.cpp
+++ b/source/backend/CarlaUtils.cpp
@@ -17,48 +17,779 @@
#include "CarlaUtils.h"
+#include "CarlaNative.h"
+
+#include "CarlaBackendUtils.hpp"
+#include "CarlaLv2Utils.hpp"
#include "CarlaPipeUtils.hpp"
#include "CarlaThread.hpp"
+#include "LinkedList.hpp"
+
+#include "juce_audio_formats.h"
+
+#ifdef CARLA_OS_MAC
+# include "juce_audio_processors.h"
+#endif
-#include "juce_core.h"
+namespace CB = CarlaBackend;
+
+static const char* const gNullCharPtr = "";
+
+#ifdef CARLA_OS_MAC
+static juce::StringArray gCachedAuPluginResults;
+#endif
// -------------------------------------------------------------------------------------------------------------------
-const char* carla_get_library_filename()
+_CarlaCachedPluginInfo::_CarlaCachedPluginInfo() noexcept
+ : category(CB::PLUGIN_CATEGORY_NONE),
+ hints(0x0),
+ audioIns(0),
+ audioOuts(0),
+ midiIns(0),
+ midiOuts(0),
+ parameterIns(0),
+ parameterOuts(0),
+ name(gNullCharPtr),
+ label(gNullCharPtr),
+ maker(gNullCharPtr),
+ copyright(gNullCharPtr) {}
+
+// -------------------------------------------------------------------------------------------------------------------
+
+static const NativePluginDescriptor carlaRackDesc = {
+ /* category */ NATIVE_PLUGIN_CATEGORY_OTHER,
+ /* hints */ static_cast(NATIVE_PLUGIN_IS_SYNTH
+ |NATIVE_PLUGIN_HAS_UI
+ |NATIVE_PLUGIN_NEEDS_FIXED_BUFFERS
+ |NATIVE_PLUGIN_NEEDS_SINGLE_THREAD
+ |NATIVE_PLUGIN_USES_STATE
+ |NATIVE_PLUGIN_USES_TIME),
+ /* supports */ static_cast(NATIVE_PLUGIN_SUPPORTS_EVERYTHING),
+ /* audioIns */ 2,
+ /* audioOuts */ 2,
+ /* midiIns */ 1,
+ /* midiOuts */ 1,
+ /* paramIns */ 0,
+ /* paramOuts */ 0,
+ /* name */ "Carla-Rack",
+ /* label */ "carlarack",
+ /* maker */ "falkTX",
+ /* copyright */ "GNU GPL v2+",
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr,
+};
+
+static const NativePluginDescriptor carlaPatchbayDesc = {
+ /* category */ NATIVE_PLUGIN_CATEGORY_OTHER,
+ /* hints */ static_cast(NATIVE_PLUGIN_IS_SYNTH
+ |NATIVE_PLUGIN_HAS_UI
+ |NATIVE_PLUGIN_NEEDS_FIXED_BUFFERS
+ |NATIVE_PLUGIN_NEEDS_SINGLE_THREAD
+ |NATIVE_PLUGIN_USES_STATE
+ |NATIVE_PLUGIN_USES_TIME),
+ /* supports */ static_cast(NATIVE_PLUGIN_SUPPORTS_EVERYTHING),
+ /* audioIns */ 2,
+ /* audioOuts */ 2,
+ /* midiIns */ 1,
+ /* midiOuts */ 1,
+ /* paramIns */ 0,
+ /* paramOuts */ 0,
+ /* name */ "Carla-Patchbay",
+ /* label */ "carlapatchbay",
+ /* maker */ "falkTX",
+ /* copyright */ "GNU GPL v2+",
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr,
+};
+
+static const NativePluginDescriptor carlaPatchbay3sDesc = {
+ /* category */ NATIVE_PLUGIN_CATEGORY_OTHER,
+ /* hints */ static_cast(NATIVE_PLUGIN_IS_SYNTH
+ |NATIVE_PLUGIN_HAS_UI
+ |NATIVE_PLUGIN_NEEDS_FIXED_BUFFERS
+ |NATIVE_PLUGIN_NEEDS_SINGLE_THREAD
+ |NATIVE_PLUGIN_USES_STATE
+ |NATIVE_PLUGIN_USES_TIME),
+ /* supports */ static_cast(NATIVE_PLUGIN_SUPPORTS_EVERYTHING),
+ /* audioIns */ 3,
+ /* audioOuts */ 2,
+ /* midiIns */ 1,
+ /* midiOuts */ 1,
+ /* paramIns */ 0,
+ /* paramOuts */ 0,
+ /* name */ "Carla-Patchbay (sidechain)",
+ /* label */ "carlapatchbay3s",
+ /* maker */ "falkTX",
+ /* copyright */ "GNU GPL v2+",
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr,
+};
+
+static const NativePluginDescriptor carlaPatchbay16Desc = {
+ /* category */ NATIVE_PLUGIN_CATEGORY_OTHER,
+ /* hints */ static_cast(NATIVE_PLUGIN_IS_SYNTH
+ |NATIVE_PLUGIN_HAS_UI
+ |NATIVE_PLUGIN_NEEDS_FIXED_BUFFERS
+ |NATIVE_PLUGIN_NEEDS_SINGLE_THREAD
+ |NATIVE_PLUGIN_USES_STATE
+ |NATIVE_PLUGIN_USES_TIME),
+ /* supports */ static_cast(NATIVE_PLUGIN_SUPPORTS_EVERYTHING),
+ /* audioIns */ 16,
+ /* audioOuts */ 16,
+ /* midiIns */ 1,
+ /* midiOuts */ 1,
+ /* paramIns */ 0,
+ /* paramOuts */ 0,
+ /* name */ "Carla-Patchbay (16chan)",
+ /* label */ "carlapatchbay16",
+ /* maker */ "falkTX",
+ /* copyright */ "GNU GPL v2+",
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr,
+};
+
+static const NativePluginDescriptor carlaPatchbay32Desc = {
+ /* category */ NATIVE_PLUGIN_CATEGORY_OTHER,
+ /* hints */ static_cast(NATIVE_PLUGIN_IS_SYNTH
+ |NATIVE_PLUGIN_HAS_UI
+ |NATIVE_PLUGIN_NEEDS_FIXED_BUFFERS
+ |NATIVE_PLUGIN_NEEDS_SINGLE_THREAD
+ |NATIVE_PLUGIN_USES_STATE
+ |NATIVE_PLUGIN_USES_TIME),
+ /* supports */ static_cast(NATIVE_PLUGIN_SUPPORTS_EVERYTHING),
+ /* audioIns */ 32,
+ /* audioOuts */ 32,
+ /* midiIns */ 1,
+ /* midiOuts */ 1,
+ /* paramIns */ 0,
+ /* paramOuts */ 0,
+ /* name */ "Carla-Patchbay (32chan)",
+ /* label */ "carlapatchbay32",
+ /* maker */ "falkTX",
+ /* copyright */ "GNU GPL v2+",
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr,
+};
+
+static LinkedList gPluginDescriptors;
+
+static const
+struct ScopedInitializer {
+ ScopedInitializer()
+ {
+ carla_register_all_plugins();
+ }
+
+ ~ScopedInitializer()
+ {
+ gPluginDescriptors.clear();
+ }
+} _si;
+
+// -------------------------------------------------------------------------------------------------------------------
+
+CARLA_EXTERN_C
+void carla_register_native_plugin_carla();
+
+void carla_register_native_plugin_carla()
{
- carla_debug("carla_get_library_filename()");
+ gPluginDescriptors.append(&carlaRackDesc);
+ gPluginDescriptors.append(&carlaPatchbayDesc);
+ gPluginDescriptors.append(&carlaPatchbay3sDesc);
+ gPluginDescriptors.append(&carlaPatchbay16Desc);
+ gPluginDescriptors.append(&carlaPatchbay32Desc);
+}
- static CarlaString ret;
+void carla_register_native_plugin(const NativePluginDescriptor* desc)
+{
+ gPluginDescriptors.append(desc);
+}
- if (ret.isEmpty())
+// -------------------------------------------------------------------------------------------------------------------
+
+const char* carla_get_complete_license_text()
+{
+ carla_debug("carla_get_complete_license_text()");
+
+ static CarlaString retText;
+
+ if (retText.isEmpty())
{
- using juce::File;
- ret = File(File::getSpecialLocation(File::currentExecutableFile)).getFullPathName().toRawUTF8();
+ retText =
+ "This current Carla build is using the following features and 3rd-party code:
"
+ ""
+
+ // Plugin formats
+ "- LADSPA plugin support
"
+ "- DSSI plugin support
"
+ "- LV2 plugin support
"
+#ifdef VESTIGE_HEADER
+ "- VST2 plugin support using VeSTige header by Javier Serrano Polo
"
+#else
+ "- VST2 plugin support using official VST SDK 2.4 [1]
"
+#endif
+#if defined(CARLA_OS_MAC) || defined(CARLA_OS_WIN)
+ "- VST3 plugin support using official VST SDK 3.6 [1]
"
+#endif
+#ifdef CARLA_OS_MAC
+ "- AU plugin support
"
+#endif
+
+ // Sample kit libraries
+#ifdef HAVE_FLUIDSYNTH
+ "- FluidSynth library for SF2 support
"
+#endif
+#ifdef HAVE_LINUXSAMPLER
+ "- LinuxSampler library for GIG and SFZ support [2]
"
+#endif
+
+ // Internal plugins
+ "- NekoFilter plugin code based on lv2fil by Nedko Arnaudov and Fons Adriaensen
"
+#ifdef WANT_ZYNADDSUBFX
+ "- ZynAddSubFX plugin code
"
+#endif
+
+ // misc libs
+ "- base64 utilities based on code by Ren\u00E9 Nyffenegger
"
+#ifdef CARLA_OS_MAC
+ "- sem_timedwait for Mac OS by Keith Shortridge
"
+#endif
+ "- liblo library for OSC support
"
+ "- rtmempool library by Nedko Arnaudov"
+ "
- serd, sord, sratom and lilv libraries for LV2 discovery
"
+#if ! (defined(CARLA_OS_MAC) || defined(CARLA_OS_WIN))
+ "- RtAudio and RtMidi libraries for extra Audio and MIDI support
"
+#endif
+
+ // end
+ "
"
+
+ ""
+#if defined(CARLA_OS_MAC) || defined(CARLA_OS_WIN) || ! defined(VESTIGE_HEADER)
+ // Required by VST SDK
+ " [1] Trademark of Steinberg Media Technologies GmbH.
"
+#endif
+#ifdef HAVE_LINUXSAMPLER
+ // LinuxSampler GPL exception
+ " [2] Using LinuxSampler code in commercial hardware or software products is not allowed without prior written authorization by the authors."
+#endif
+ "
"
+ ;
}
- return ret;
+ return retText;
}
-const char* carla_get_library_folder()
+const char* carla_get_juce_version()
{
- carla_debug("carla_get_library_folder()");
+ carla_debug("carla_get_juce_version()");
- static CarlaString ret;
+ static CarlaString retVersion;
- if (ret.isEmpty())
+ if (retVersion.isEmpty())
{
- using juce::File;
- ret = File(File::getSpecialLocation(File::currentExecutableFile).getParentDirectory()).getFullPathName().toRawUTF8();
+ if (const char* const version = juce::SystemStats::getJUCEVersion().toRawUTF8())
+ retVersion = version+6;
+ else
+ retVersion = "3.0";
}
- return ret;
+ return retVersion;
+}
+
+const char* carla_get_supported_file_extensions()
+{
+ carla_debug("carla_get_supported_file_extensions()");
+
+ static CarlaString retText;
+
+ if (retText.isEmpty())
+ {
+ retText =
+ // Base types
+ "*.carxp;*.carxs"
+ // MIDI files
+ ";*.mid;*.midi"
+#ifdef HAVE_FLUIDSYNTH
+ // fluidsynth (sf2)
+ ";*.sf2"
+#endif
+#ifdef HAVE_LINUXSAMPLER
+ // linuxsampler (gig and sfz)
+ ";*.gig;*.sfz"
+#endif
+#ifdef WANT_ZYNADDSUBFX
+ // zynaddsubfx presets
+ ";*.xmz;*.xiz"
+#endif
+ ;
+
+ // Audio files
+ {
+ using namespace juce;
+
+ AudioFormatManager afm;
+ afm.registerBasicFormats();
+
+ String juceFormats;
+
+ for (AudioFormat **it=afm.begin(), **end=afm.end(); it != end; ++it)
+ {
+ const StringArray& exts((*it)->getFileExtensions());
+
+ for (String *eit=exts.begin(), *eend=exts.end(); eit != eend; ++eit)
+ juceFormats += String(";*" + (*eit)).toRawUTF8();
+ }
+
+ retText += juceFormats.toRawUTF8();
+ }
+ }
+
+ return retText;
}
// -------------------------------------------------------------------------------------------------------------------
-void carla_set_locale_C()
+uint carla_get_cached_plugin_count(CB::PluginType ptype, const char* pluginPath)
{
- ::setlocale(LC_NUMERIC, "C");
+ CARLA_SAFE_ASSERT_RETURN(ptype == CB::PLUGIN_INTERNAL || ptype == CB::PLUGIN_LV2 || ptype == CB::PLUGIN_AU, 0);
+ carla_debug("carla_get_cached_plugin_count(%i:%s)", ptype, CB::PluginType2Str(ptype));
+
+ switch (ptype)
+ {
+ case CB::PLUGIN_INTERNAL: {
+ return static_cast(gPluginDescriptors.count());
+ }
+
+ case CB::PLUGIN_LV2: {
+ Lv2WorldClass& lv2World(Lv2WorldClass::getInstance());
+ lv2World.initIfNeeded(pluginPath);
+ return lv2World.getPluginCount();
+ }
+
+ case CB::PLUGIN_AU: {
+#ifdef CARLA_OS_MAC
+ static bool initiated = false;
+
+ if (initiated)
+ return static_cast(gCachedAuPluginResults.size());
+
+ using namespace juce;
+
+ initiated = true;
+ AudioUnitPluginFormat auFormat;
+ gCachedAuPluginResults = auFormat.searchPathsForPlugins(juce::FileSearchPath(), false);
+
+ return static_cast(gCachedAuPluginResults.size());
+#else
+ return 0;
+#endif
+ }
+
+ default:
+ return 0;
+ }
+}
+
+const CarlaCachedPluginInfo* carla_get_cached_plugin_info(CB::PluginType ptype, uint index)
+{
+ carla_debug("carla_get_cached_plugin_info(%i:%s, %i)", ptype, CB::PluginType2Str(ptype), index);
+
+ static CarlaCachedPluginInfo info;
+
+ switch (ptype)
+ {
+ case CB::PLUGIN_INTERNAL: {
+ const NativePluginDescriptor* const desc(gPluginDescriptors.getAt(index, nullptr));
+ CARLA_SAFE_ASSERT_BREAK(desc != nullptr);
+
+ info.category = static_cast(desc->category);
+ info.hints = 0x0;
+
+ if (desc->hints & NATIVE_PLUGIN_IS_RTSAFE)
+ info.hints |= CB::PLUGIN_IS_RTSAFE;
+ if (desc->hints & NATIVE_PLUGIN_IS_SYNTH)
+ info.hints |= CB::PLUGIN_IS_SYNTH;
+ if (desc->hints & NATIVE_PLUGIN_HAS_UI)
+ info.hints |= CB::PLUGIN_HAS_CUSTOM_UI;
+ if (desc->hints & NATIVE_PLUGIN_NEEDS_FIXED_BUFFERS)
+ info.hints |= CB::PLUGIN_NEEDS_FIXED_BUFFERS;
+ if (desc->hints & NATIVE_PLUGIN_NEEDS_SINGLE_THREAD)
+ info.hints |= CB::PLUGIN_NEEDS_SINGLE_THREAD;
+
+ info.audioIns = desc->audioIns;
+ info.audioOuts = desc->audioOuts;
+ info.midiIns = desc->midiIns;
+ info.midiOuts = desc->midiOuts;
+ info.parameterIns = desc->paramIns;
+ info.parameterOuts = desc->paramOuts;
+ info.name = desc->name;
+ info.label = desc->label;
+ info.maker = desc->maker;
+ info.copyright = desc->copyright;
+ return &info;
+ }
+
+ case CB::PLUGIN_LV2: {
+ Lv2WorldClass& lv2World(Lv2WorldClass::getInstance());
+
+ const LilvPlugin* const cPlugin(lv2World.getPluginFromIndex(index));
+ CARLA_SAFE_ASSERT_BREAK(cPlugin != nullptr);
+
+ Lilv::Plugin lilvPlugin(cPlugin);
+ CARLA_SAFE_ASSERT_BREAK(lilvPlugin.get_uri().is_uri());
+
+ carla_stdout("Filling info for LV2 with URI '%s'", lilvPlugin.get_uri().as_uri());
+
+ // features
+ info.hints = 0x0;
+
+#if 0
+ if (lilvPlugin.get_uis().size() > 0 || lilvPlugin.get_modgui_resources_directory().as_uri() != nullptr)
+ info.hints |= CB::PLUGIN_HAS_CUSTOM_UI;
+#endif
+
+ {
+ Lilv::Nodes lilvFeatureNodes(lilvPlugin.get_supported_features());
+
+ LILV_FOREACH(nodes, it, lilvFeatureNodes)
+ {
+ Lilv::Node lilvFeatureNode(lilvFeatureNodes.get(it));
+ const char* const featureURI(lilvFeatureNode.as_uri());
+ CARLA_SAFE_ASSERT_CONTINUE(featureURI != nullptr);
+
+ if (std::strcmp(featureURI, LV2_CORE__hardRTCapable) == 0)
+ info.hints |= CB::PLUGIN_IS_RTSAFE;
+ }
+
+ lilv_nodes_free(const_cast(lilvFeatureNodes.me));
+ }
+
+ // category
+ info.category = CB::PLUGIN_CATEGORY_NONE;
+
+ {
+ Lilv::Nodes typeNodes(lilvPlugin.get_value(lv2World.rdf_type));
+
+ if (typeNodes.size() > 0)
+ {
+ if (typeNodes.contains(lv2World.class_allpass))
+ info.category = CB::PLUGIN_CATEGORY_FILTER;
+ if (typeNodes.contains(lv2World.class_amplifier))
+ info.category = CB::PLUGIN_CATEGORY_DYNAMICS;
+ if (typeNodes.contains(lv2World.class_analyzer))
+ info.category = CB::PLUGIN_CATEGORY_UTILITY;
+ if (typeNodes.contains(lv2World.class_bandpass))
+ info.category = CB::PLUGIN_CATEGORY_FILTER;
+ if (typeNodes.contains(lv2World.class_chorus))
+ info.category = CB::PLUGIN_CATEGORY_MODULATOR;
+ if (typeNodes.contains(lv2World.class_comb))
+ info.category = CB::PLUGIN_CATEGORY_FILTER;
+ if (typeNodes.contains(lv2World.class_compressor))
+ info.category = CB::PLUGIN_CATEGORY_DYNAMICS;
+ if (typeNodes.contains(lv2World.class_constant))
+ info.category = CB::PLUGIN_CATEGORY_OTHER;
+ if (typeNodes.contains(lv2World.class_converter))
+ info.category = CB::PLUGIN_CATEGORY_UTILITY;
+ if (typeNodes.contains(lv2World.class_delay))
+ info.category = CB::PLUGIN_CATEGORY_DELAY;
+ if (typeNodes.contains(lv2World.class_distortion))
+ info.category = CB::PLUGIN_CATEGORY_DISTORTION;
+ if (typeNodes.contains(lv2World.class_dynamics))
+ info.category = CB::PLUGIN_CATEGORY_DYNAMICS;
+ if (typeNodes.contains(lv2World.class_eq))
+ info.category = CB::PLUGIN_CATEGORY_EQ;
+ if (typeNodes.contains(lv2World.class_envelope))
+ info.category = CB::PLUGIN_CATEGORY_DYNAMICS;
+ if (typeNodes.contains(lv2World.class_expander))
+ info.category = CB::PLUGIN_CATEGORY_DYNAMICS;
+ if (typeNodes.contains(lv2World.class_filter))
+ info.category = CB::PLUGIN_CATEGORY_FILTER;
+ if (typeNodes.contains(lv2World.class_flanger))
+ info.category = CB::PLUGIN_CATEGORY_MODULATOR;
+ if (typeNodes.contains(lv2World.class_function))
+ info.category = CB::PLUGIN_CATEGORY_UTILITY;
+ if (typeNodes.contains(lv2World.class_gate))
+ info.category = CB::PLUGIN_CATEGORY_DYNAMICS;
+ if (typeNodes.contains(lv2World.class_generator))
+ info.category = CB::PLUGIN_CATEGORY_OTHER;
+ if (typeNodes.contains(lv2World.class_highpass))
+ info.category = CB::PLUGIN_CATEGORY_FILTER;
+ if (typeNodes.contains(lv2World.class_limiter))
+ info.category = CB::PLUGIN_CATEGORY_DYNAMICS;
+ if (typeNodes.contains(lv2World.class_lowpass))
+ info.category = CB::PLUGIN_CATEGORY_FILTER;
+ if (typeNodes.contains(lv2World.class_mixer))
+ info.category = CB::PLUGIN_CATEGORY_UTILITY;
+ if (typeNodes.contains(lv2World.class_modulator))
+ info.category = CB::PLUGIN_CATEGORY_MODULATOR;
+ if (typeNodes.contains(lv2World.class_multiEQ))
+ info.category = CB::PLUGIN_CATEGORY_EQ;
+ if (typeNodes.contains(lv2World.class_oscillator))
+ info.category = CB::PLUGIN_CATEGORY_OTHER;
+ if (typeNodes.contains(lv2World.class_paraEQ))
+ info.category = CB::PLUGIN_CATEGORY_EQ;
+ if (typeNodes.contains(lv2World.class_phaser))
+ info.category = CB::PLUGIN_CATEGORY_MODULATOR;
+ if (typeNodes.contains(lv2World.class_pitch))
+ info.category = CB::PLUGIN_CATEGORY_OTHER;
+ if (typeNodes.contains(lv2World.class_reverb))
+ info.category = CB::PLUGIN_CATEGORY_DELAY;
+ if (typeNodes.contains(lv2World.class_simulator))
+ info.category = CB::PLUGIN_CATEGORY_OTHER;
+ if (typeNodes.contains(lv2World.class_spatial))
+ info.category = CB::PLUGIN_CATEGORY_OTHER;
+ if (typeNodes.contains(lv2World.class_spectral))
+ info.category = CB::PLUGIN_CATEGORY_OTHER;
+ if (typeNodes.contains(lv2World.class_utility))
+ info.category = CB::PLUGIN_CATEGORY_UTILITY;
+ if (typeNodes.contains(lv2World.class_waveshaper))
+ info.category = CB::PLUGIN_CATEGORY_DISTORTION;
+ if (typeNodes.contains(lv2World.class_instrument))
+ {
+ info.category = CB::PLUGIN_CATEGORY_SYNTH;
+ info.hints |= CB::PLUGIN_IS_SYNTH;
+ }
+ }
+
+ lilv_nodes_free(const_cast(typeNodes.me));
+ }
+
+ // number data
+ info.audioIns = 0;
+ info.audioOuts = 0;
+ info.midiIns = 0;
+ info.midiOuts = 0;
+ info.parameterIns = 0;
+ info.parameterOuts = 0;
+
+ for (uint i=0, count=lilvPlugin.get_num_ports(); i(supportNodes.me));
+ }
+ else if (lilvPort.is_a(lv2World.port_event))
+ {
+ if (lilvPort.supports_event(lv2World.midi_event))
+ {
+ if (isInput)
+ ++(info.midiIns);
+ else
+ ++(info.midiOuts);
+ }
+ }
+ else if (lilvPort.is_a(lv2World.port_midi))
+ {
+ if (isInput)
+ ++(info.midiIns);
+ else
+ ++(info.midiOuts);
+ }
+ }
+
+ // text data
+ static CarlaString suri, sname, smaker, slicense;
+ suri.clear(); sname.clear(); smaker.clear(); slicense.clear();
+
+ suri = lilvPlugin.get_uri().as_uri();
+
+ if (const char* const name = lilvPlugin.get_name().as_string())
+ sname = name;
+ else
+ sname.clear();
+
+ if (const char* const author = lilvPlugin.get_author_name().as_string())
+ smaker = author;
+ else
+ smaker.clear();
+
+ Lilv::Nodes licenseNodes(lilvPlugin.get_value(lv2World.doap_license));
+
+ if (licenseNodes.size() > 0)
+ {
+ if (const char* const license = licenseNodes.get_first().as_string())
+ slicense = license;
+ }
+
+ lilv_nodes_free(const_cast(licenseNodes.me));
+
+ info.name = sname;
+ info.label = suri;
+ info.maker = smaker;
+ info.copyright = slicense;
+
+ return &info;
+ }
+
+ case CB::PLUGIN_AU: {
+#ifdef CARLA_OS_MAC
+ const int indexi(static_cast(index));
+ CARLA_SAFE_ASSERT_BREAK(indexi < gCachedAuPluginResults.size());
+
+ using namespace juce;
+
+ String pluginId(gCachedAuPluginResults[indexi]);
+ OwnedArray results;
+
+ AudioUnitPluginFormat auFormat;
+ auFormat.findAllTypesForFile(results, pluginId);
+ CARLA_SAFE_ASSERT_BREAK(results.size() > 0);
+ CARLA_SAFE_ASSERT(results.size() == 1);
+
+ PluginDescription* const desc(results[0]);
+ CARLA_SAFE_ASSERT_BREAK(desc != nullptr);
+
+ info.category = CB::getPluginCategoryFromName(desc->category.toRawUTF8());
+ info.hints = 0x0;
+
+ if (desc->isInstrument)
+ info.hints |= CB::PLUGIN_IS_SYNTH;
+ if (true)
+ info.hints |= CB::PLUGIN_HAS_CUSTOM_UI;
+
+ info.audioIns = static_cast(desc->numInputChannels);
+ info.audioOuts = static_cast(desc->numOutputChannels);
+ info.midiIns = desc->isInstrument ? 1 : 0;
+ info.midiOuts = 0;
+ info.parameterIns = 0;
+ info.parameterOuts = 0;
+
+ static CarlaString sname, slabel, smaker;
+
+ sname = desc->name.toRawUTF8();
+ slabel = desc->fileOrIdentifier.toRawUTF8();
+ smaker = desc->manufacturerName.toRawUTF8();
+
+ info.name = sname;
+ info.label = slabel;
+ info.maker = smaker;
+ info.copyright = gNullCharPtr;
+
+ return &info;
+#else
+ break;
+#endif
+ }
+
+ default:
+ break;
+ }
+
+ info.category = CB::PLUGIN_CATEGORY_NONE;
+ info.hints = 0x0;
+ info.audioIns = 0;
+ info.audioOuts = 0;
+ info.midiIns = 0;
+ info.midiOuts = 0;
+ info.parameterIns = 0;
+ info.parameterOuts = 0;
+ info.name = gNullCharPtr;
+ info.label = gNullCharPtr;
+ info.maker = gNullCharPtr;
+ info.copyright = gNullCharPtr;
+ return &info;
}
// -------------------------------------------------------------------------------------------------------------------
@@ -202,6 +933,38 @@ void carla_pipe_client_destroy(CarlaPipeClientHandle handle)
// -------------------------------------------------------------------------------------------------------------------
+const char* carla_get_library_filename()
+{
+ carla_debug("carla_get_library_filename()");
+
+ static CarlaString ret;
+
+ if (ret.isEmpty())
+ {
+ using juce::File;
+ ret = File(File::getSpecialLocation(File::currentExecutableFile)).getFullPathName().toRawUTF8();
+ }
+
+ return ret;
+}
+
+const char* carla_get_library_folder()
+{
+ carla_debug("carla_get_library_folder()");
+
+ static CarlaString ret;
+
+ if (ret.isEmpty())
+ {
+ using juce::File;
+ ret = File(File::getSpecialLocation(File::currentExecutableFile).getParentDirectory()).getFullPathName().toRawUTF8();
+ }
+
+ return ret;
+}
+
+// -------------------------------------------------------------------------------------------------------------------
+
#include "CarlaPipeUtils.cpp"
// -------------------------------------------------------------------------------------------------------------------
diff --git a/source/backend/CarlaUtils.h b/source/backend/CarlaUtils.h
index 1aec97be2..5c0f29665 100644
--- a/source/backend/CarlaUtils.h
+++ b/source/backend/CarlaUtils.h
@@ -18,7 +18,12 @@
#ifndef CARLA_UTILS_H_INCLUDED
#define CARLA_UTILS_H_INCLUDED
-#include "CarlaDefines.h"
+#include "CarlaBackend.h"
+
+#ifdef __cplusplus
+using CarlaBackend::PluginCategory;
+using CarlaBackend::PluginType;
+#endif
/*!
* @defgroup CarlaUtilsAPI Carla Utils API
@@ -40,25 +45,127 @@ typedef void* CarlaPipeClientHandle;
typedef void (*CarlaPipeCallbackFunc)(void* ptr, const char* msg);
/*!
- * Get the current carla library filename.
+ * Information about a cached plugin.
+ * @see carla_get_cached_plugin_info()
*/
-CARLA_EXPORT const char* carla_get_library_filename();
+typedef struct _CarlaCachedPluginInfo {
+ /*!
+ * Plugin category.
+ */
+ PluginCategory category;
+
+ /*!
+ * Plugin hints.
+ * @see PluginHints
+ */
+ uint hints;
+
+ /*!
+ * Number of audio inputs.
+ */
+ uint32_t audioIns;
+
+ /*!
+ * Number of audio outputs.
+ */
+ uint32_t audioOuts;
+
+ /*!
+ * Number of MIDI inputs.
+ */
+ uint32_t midiIns;
+
+ /*!
+ * Number of MIDI outputs.
+ */
+ uint32_t midiOuts;
+
+ /*!
+ * Number of input parameters.
+ */
+ uint32_t parameterIns;
+
+ /*!
+ * Number of output parameters.
+ */
+ uint32_t parameterOuts;
+
+ /*!
+ * Plugin name.
+ */
+ const char* name;
+
+ /*!
+ * Plugin label.
+ */
+ const char* label;
+
+ /*!
+ * Plugin author/maker.
+ */
+ const char* maker;
+
+ /*!
+ * Plugin copyright/license.
+ */
+ const char* copyright;
+
+#ifdef __cplusplus
+ /*!
+ * C++ constructor.
+ */
+ CARLA_API _CarlaCachedPluginInfo() noexcept;
+ CARLA_DECLARE_NON_COPY_STRUCT(_CarlaCachedPluginInfo)
+#endif
+
+} CarlaCachedPluginInfo;
+
+/* ------------------------------------------------------------------------------------------------------------
+ * get stuff */
/*!
- * Get the folder where the current use carla library resides.
+ * Get the complete license text of used third-party code and features.
+ * Returned string is in basic html format.
*/
-CARLA_EXPORT const char* carla_get_library_folder();
+CARLA_EXPORT const char* carla_get_complete_license_text();
/*!
- * TODO.
+ * Get the juce version used in the current Carla build.
*/
-CARLA_EXPORT void carla_set_locale_C();
+CARLA_EXPORT const char* carla_get_juce_version();
/*!
- * Get the juce version used in the current Carla build.
+ * Get all the supported file extensions in carla_load_file().
+ * Returned string uses this syntax:
+ * @code
+ * "*.ext1;*.ext2;*.ext3"
+ * @endcode
+ */
+CARLA_EXPORT const char* carla_get_supported_file_extensions();
+
+/*!
+ * Get how many cached plugins are available.
+ * Internal, LV2 and AU plugin formats are cached and need to be discovered via this function.
+ * Do not call this for any other plugin formats.
+ */
+CARLA_EXPORT uint carla_get_cached_plugin_count(PluginType ptype, const char* pluginPath);
+
+/*!
+ * Get information about a cached plugin.
+ */
+CARLA_EXPORT const CarlaCachedPluginInfo* carla_get_cached_plugin_info(PluginType ptype, uint index);
+
+/* ------------------------------------------------------------------------------------------------------------
+ * set stuff */
+
+/*!
+ * Set the current process name to @a name.
*/
CARLA_EXPORT void carla_set_process_name(const char* name);
+/* ------------------------------------------------------------------------------------------------------------
+ * pipes */
+
/*!
* TODO.
*/
@@ -114,6 +221,21 @@ CARLA_EXPORT bool carla_pipe_client_flush_and_unlock(CarlaPipeClientHandle handl
*/
CARLA_EXPORT void carla_pipe_client_destroy(CarlaPipeClientHandle handle);
+/* ------------------------------------------------------------------------------------------------------------
+ * info about current library */
+
+/*!
+ * Get the absolute filename of this carla library.
+ */
+CARLA_EXPORT const char* carla_get_library_filename();
+
+/*!
+ * Get the folder where this carla library resides.
+ */
+CARLA_EXPORT const char* carla_get_library_folder();
+
+// -------------------------------------------------------------------------------------------------------------------
+
/** @} */
#endif /* CARLA_UTILS_H_INCLUDED */
diff --git a/source/backend/Makefile b/source/backend/Makefile
index 1c3f6048b..b4cf348c9 100644
--- a/source/backend/Makefile
+++ b/source/backend/Makefile
@@ -45,7 +45,11 @@ STANDALONE_LIBS += $(MODULEDIR)/rtaudio.a
STANDALONE_LIBS += $(MODULEDIR)/rtmidi.a
endif
-UTILS_LIBS = $(MODULEDIR)/juce_core.a
+UTILS_LIBS = $(MODULEDIR)/juce_audio_basics.a
+UTILS_LIBS += $(MODULEDIR)/juce_audio_formats.a
+UTILS_LIBS += $(MODULEDIR)/juce_core.a
+UTILS_LIBS += $(MODULEDIR)/lilv.a
+UTILS_LIBS += $(MODULEDIR)/native-plugins.a
# ----------------------------------------------------------------------------------------------------------------------------
@@ -89,10 +93,11 @@ ifeq ($(UNIX),true)
STANDALONE_LINK_FLAGS += -lmagic
endif
-UTILS_LINK_FLAGS = $(JUCE_CORE_LIBS)
-ifeq ($(UNIX),true)
-UTILS_LINK_FLAGS += -lpthread
-endif
+UTILS_LINK_FLAGS = $(JUCE_AUDIO_BASICS_LIBS)
+UTILS_LINK_FLAGS += $(JUCE_AUDIO_FORMATS_LIBS)
+UTILS_LINK_FLAGS += $(JUCE_CORE_LIBS)
+UTILS_LINK_FLAGS += $(LILV_LIBS)
+UTILS_LINK_FLAGS += $(NATIVE_PLUGINS_LIBS)
# ----------------------------------------------------------------------------------------------------------------------------
diff --git a/source/backend/engine/CarlaEngineNative.cpp b/source/backend/engine/CarlaEngineNative.cpp
index f569e38a9..d23cda0d8 100644
--- a/source/backend/engine/CarlaEngineNative.cpp
+++ b/source/backend/engine/CarlaEngineNative.cpp
@@ -31,6 +31,7 @@
#include "CarlaStateUtils.hpp"
#include "CarlaExternalUI.hpp"
+#include "CarlaHost.h"
#include "CarlaNative.hpp"
#include "juce_audio_basics.h"
@@ -973,15 +974,6 @@ protected:
const CarlaMutexLocker cml(fUiServer.getPipeLock());
- fUiServer.writeAndFixMessage("complete-license");
- fUiServer.writeAndFixMessage(carla_get_complete_license_text());
-
- fUiServer.writeAndFixMessage("juce-version");
- fUiServer.writeAndFixMessage(carla_get_juce_version());
-
- fUiServer.writeAndFixMessage("file-exts");
- fUiServer.writeAndFixMessage(carla_get_supported_file_extensions());
-
fUiServer.writeAndFixMessage("max-plugin-number");
std::sprintf(fTmpBuf, "%i\n", pData->maxPluginNumber);
fUiServer.writeMessage(fTmpBuf);
diff --git a/source/backend/plugin/CarlaPluginNative.cpp b/source/backend/plugin/CarlaPluginNative.cpp
index e1699f053..98995c8f0 100644
--- a/source/backend/plugin/CarlaPluginNative.cpp
+++ b/source/backend/plugin/CarlaPluginNative.cpp
@@ -26,7 +26,15 @@
using juce::String;
using juce::StringArray;
-// -----------------------------------------------------
+// -----------------------------------------------------------------------
+
+CARLA_EXTERN_C
+std::size_t carla_getNativePluginCount();
+
+CARLA_EXTERN_C
+const NativePluginDescriptor* carla_getNativePluginDescriptor(const std::size_t index);
+
+// -----------------------------------------------------------------------
static LinkedList gPluginDescriptors;
@@ -35,6 +43,16 @@ void carla_register_native_plugin(const NativePluginDescriptor* desc)
gPluginDescriptors.append(desc);
}
+std::size_t carla_getNativePluginCount()
+{
+ return gPluginDescriptors.count();
+}
+
+const NativePluginDescriptor* carla_getNativePluginDescriptor(const std::size_t index)
+{
+ return gPluginDescriptors.getAt(index, nullptr);
+}
+
// -----------------------------------------------------
CARLA_BACKEND_START_NAMESPACE
@@ -123,7 +141,7 @@ struct ScopedInitializer {
carla_register_all_plugins();
}
- ~ScopedInitializer()
+ ~ScopedInitializer() noexcept
{
gPluginDescriptors.clear();
}
@@ -2201,20 +2219,6 @@ protected:
// -------------------------------------------------------------------
public:
- static size_t getPluginCount() noexcept
- {
- return gPluginDescriptors.count();
- }
-
- static const NativePluginDescriptor* getPluginDescriptor(const size_t index) noexcept
- {
- CARLA_SAFE_ASSERT_RETURN(index < gPluginDescriptors.count(), nullptr);
-
- return gPluginDescriptors.getAt(index, nullptr);
- }
-
- // -------------------------------------------------------------------
-
void* getNativeHandle() const noexcept override
{
return fHandle;
@@ -2435,18 +2439,6 @@ private:
// -----------------------------------------------------------------------
-std::size_t CarlaPlugin::getNativePluginCount() noexcept
-{
- return CarlaPluginNative::getPluginCount();
-}
-
-const NativePluginDescriptor* CarlaPlugin::getNativePluginDescriptor(const std::size_t index) noexcept
-{
- return CarlaPluginNative::getPluginDescriptor(index);
-}
-
-// -----------------------------------------------------------------------
-
CarlaPlugin* CarlaPlugin::newNative(const Initializer& init)
{
carla_debug("CarlaPlugin::newNative({%p, \"%s\", \"%s\", \"%s\", " P_INT64 "})", init.engine, init.filename, init.name, init.label, init.uniqueId);
diff --git a/source/carla_backend.py b/source/carla_backend.py
index e81e7b442..ffd40b604 100644
--- a/source/carla_backend.py
+++ b/source/carla_backend.py
@@ -1060,48 +1060,6 @@ class CarlaPluginInfo(Structure):
("uniqueId", c_int64)
]
-# Information about an internal Carla plugin.
-# @see carla_get_cached_plugin_info()
-class CarlaCachedPluginInfo(Structure):
- _fields_ = [
- # Plugin category.
- ("category", c_enum),
-
- # Plugin hints.
- # @see PluginHints
- ("hints", c_uint),
-
- # Number of audio inputs.
- ("audioIns", c_uint32),
-
- # Number of audio outputs.
- ("audioOuts", c_uint32),
-
- # Number of MIDI inputs.
- ("midiIns", c_uint32),
-
- # Number of MIDI outputs.
- ("midiOuts", c_uint32),
-
- # Number of input parameters.
- ("parameterIns", c_uint32),
-
- # Number of output parameters.
- ("parameterOuts", c_uint32),
-
- # Plugin name.
- ("name", c_char_p),
-
- # Plugin label.
- ("label", c_char_p),
-
- # Plugin author/maker.
- ("maker", c_char_p),
-
- # Plugin copyright/license.
- ("copyright", c_char_p)
- ]
-
# Port count information, used for Audio and MIDI ports and parameters.
# @see carla_get_audio_port_count_info()
# @see carla_get_midi_port_count_info()
@@ -1186,22 +1144,6 @@ PyCarlaPluginInfo = {
'uniqueId': 0
}
-# @see CarlaCachedPluginInfo
-PyCarlaCachedPluginInfo = {
- 'category': PLUGIN_CATEGORY_NONE,
- 'hints': 0x0,
- 'audioIns': 0,
- 'audioOuts': 0,
- 'midiIns': 0,
- 'midiOuts': 0,
- 'parameterIns': 0,
- 'parameterOuts': 0,
- 'name': "",
- 'label': "",
- 'maker': "",
- 'copyright': ""
-}
-
# @see CarlaPortCountInfo
PyCarlaPortCountInfo = {
'ins': 0,
@@ -1299,26 +1241,6 @@ class CarlaHostMeta(object):
keyrm = "%s=" % key
self.msvcrt._putenv(keyrm.encode("utf-8"))
- # Get the complete license text of used third-party code and features.
- # Returned string is in basic html format.
- @abstractmethod
- def get_complete_license_text(self):
- raise NotImplementedError
-
- # Get the juce version used in the current Carla build.
- @abstractmethod
- def get_juce_version(self):
- raise NotImplementedError
-
- # Get all the supported file extensions in carla_load_file().
- # Returned string uses this syntax:
- # @code
- # "*.ext1;*.ext2;*.ext3"
- # @endcode
- @abstractmethod
- def get_supported_file_extensions(self):
- raise NotImplementedError
-
# Get how many engine drivers are available.
@abstractmethod
def get_engine_driver_count(self):
@@ -1343,16 +1265,6 @@ class CarlaHostMeta(object):
def get_engine_driver_device_info(self, index, name):
raise NotImplementedError
- # Get how many internal plugins are available.
- @abstractmethod
- def get_cached_plugin_count(self, ptype, pluginPath):
- raise NotImplementedError
-
- # Get information about a cached plugin.
- @abstractmethod
- def get_cached_plugin_info(self, ptype, index):
- raise NotImplementedError
-
# Initialize the engine.
# Make sure to call carla_engine_idle() at regular intervals afterwards.
# @param driverName Driver to use
@@ -1925,53 +1837,6 @@ class CarlaHostNull(CarlaHostMeta):
self.fEngineCallback = None
self.fEngineRunning = False
- def get_complete_license_text(self):
- text = (
- "This current Carla build is using the following features and 3rd-party code:
"
- ""
-
- # Plugin formats
- "- LADSPA plugin support
"
- "- DSSI plugin support
"
- "- LV2 plugin support
"
- "- VST2 plugin support using official VST SDK 2.4 [1]
"
- "- VST3 plugin support using official VST SDK 3.6 [1]
"
- "- AU plugin support
"
-
- # Sample kit libraries
- "- FluidSynth library for SF2 support
"
- "- LinuxSampler library for GIG and SFZ support [2]
"
-
- # Internal plugins
- "- NekoFilter plugin code based on lv2fil by Nedko Arnaudov and Fons Adriaensen
"
- "- ZynAddSubFX plugin code
"
-
- # misc libs
- "- base64 utilities based on code by Ren\u00E9 Nyffenegger
"
- "- sem_timedwait for Mac OS by Keith Shortridge
"
- "- liblo library for OSC support
"
- "- rtmempool library by Nedko Arnaudov"
- "
- serd, sord, sratom and lilv libraries for LV2 discovery
"
- "- RtAudio and RtMidi libraries for extra Audio and MIDI support
"
-
- # end
- "
"
-
- ""
- # Required by VST SDK
- " [1] Trademark of Steinberg Media Technologies GmbH.
"
- # LinuxSampler GPL exception
- " [2] Using LinuxSampler code in commercial hardware or software products is not allowed without prior written authorization by the authors."
- "
"
- )
- return text
-
- def get_juce_version(self):
- return "3.0"
-
- def get_supported_file_extensions(self):
- return "*.carxp;*.carxs;*.mid;*.midi;*.sf2;*.gig;*.sfz;*.xmz;*.xiz"
-
def get_engine_driver_count(self):
return 0
@@ -1984,12 +1849,6 @@ class CarlaHostNull(CarlaHostMeta):
def get_engine_driver_device_info(self, index, name):
return PyEngineDriverDeviceInfo
- def get_cached_plugin_count(self, ptype, pluginPath):
- return 0
-
- def get_cached_plugin_info(self, ptype, index):
- return PyCarlaCachedPluginInfo
-
def engine_init(self, driverName, clientName):
self.fEngineRunning = True
if self.fEngineCallback is not None:
@@ -2251,15 +2110,6 @@ class CarlaHostDLL(CarlaHostMeta):
self.lib = cdll.LoadLibrary(libName)
- self.lib.carla_get_complete_license_text.argtypes = None
- self.lib.carla_get_complete_license_text.restype = c_char_p
-
- self.lib.carla_get_juce_version.argtypes = None
- self.lib.carla_get_juce_version.restype = c_char_p
-
- self.lib.carla_get_supported_file_extensions.argtypes = None
- self.lib.carla_get_supported_file_extensions.restype = c_char_p
-
self.lib.carla_get_engine_driver_count.argtypes = None
self.lib.carla_get_engine_driver_count.restype = c_uint
@@ -2272,12 +2122,6 @@ class CarlaHostDLL(CarlaHostMeta):
self.lib.carla_get_engine_driver_device_info.argtypes = [c_uint, c_char_p]
self.lib.carla_get_engine_driver_device_info.restype = POINTER(EngineDriverDeviceInfo)
- self.lib.carla_get_cached_plugin_count.argtypes = [c_enum, c_char_p]
- self.lib.carla_get_cached_plugin_count.restype = c_uint
-
- self.lib.carla_get_cached_plugin_info.argtypes = [c_enum, c_uint]
- self.lib.carla_get_cached_plugin_info.restype = POINTER(CarlaCachedPluginInfo)
-
self.lib.carla_engine_init.argtypes = [c_char_p, c_char_p]
self.lib.carla_engine_init.restype = c_bool
@@ -2523,15 +2367,6 @@ class CarlaHostDLL(CarlaHostMeta):
# --------------------------------------------------------------------------------------------------------
- def get_complete_license_text(self):
- return charPtrToString(self.lib.carla_get_complete_license_text())
-
- def get_juce_version(self):
- return charPtrToString(self.lib.carla_get_juce_version())
-
- def get_supported_file_extensions(self):
- return charPtrToString(self.lib.carla_get_supported_file_extensions())
-
def get_engine_driver_count(self):
return int(self.lib.carla_get_engine_driver_count())
@@ -2544,12 +2379,6 @@ class CarlaHostDLL(CarlaHostMeta):
def get_engine_driver_device_info(self, index, name):
return structToDict(self.lib.carla_get_engine_driver_device_info(index, name.encode("utf-8")).contents)
- def get_cached_plugin_count(self, ptype, pluginPath):
- return int(self.lib.carla_get_cached_plugin_count(ptype, pluginPath.encode("utf-8")))
-
- def get_cached_plugin_info(self, ptype, index):
- return structToDict(self.lib.carla_get_cached_plugin_info(ptype, index).contents)
-
def engine_init(self, driverName, clientName):
return bool(self.lib.carla_engine_init(driverName.encode("utf-8"), clientName.encode("utf-8")))
@@ -2836,11 +2665,8 @@ class CarlaHostPlugin(CarlaHostMeta):
self.processModeForced = True
# text data to return when requested
- self.fCompleteLicenseText = ""
- self.fJuceVersion = ""
- self.fSupportedFileExts = ""
- self.fMaxPluginNumber = 0
- self.fLastError = ""
+ self.fMaxPluginNumber = 0
+ self.fLastError = ""
# plugin info
self.fPluginsInfo = []
@@ -2876,15 +2702,6 @@ class CarlaHostPlugin(CarlaHostMeta):
# --------------------------------------------------------------------------------------------------------
- def get_complete_license_text(self):
- return self.fCompleteLicenseText
-
- def get_juce_version(self):
- return self.fJuceVersion
-
- def get_supported_file_extensions(self):
- return self.fSupportedFileExts
-
def get_engine_driver_count(self):
return 1
@@ -2897,12 +2714,6 @@ class CarlaHostPlugin(CarlaHostMeta):
def get_engine_driver_device_info(self, index, name):
return PyEngineDriverDeviceInfo
- def get_cached_plugin_count(self, ptype, pluginPath):
- return 0
-
- def get_cached_plugin_info(self, ptype, index):
- return PyCarlaCachedPluginInfo
-
def set_engine_callback(self, func):
return # TODO
@@ -3143,12 +2954,6 @@ class CarlaHostPlugin(CarlaHostMeta):
# --------------------------------------------------------------------------------------------------------
- def _set_info(self, license, juceversion, fileexts, maxnum):
- self.fCompleteLicenseText = license
- self.fJuceVersion = juceversion
- self.fSupportedFileExts = fileexts
- self.fMaxPluginNumber = maxnum
-
def _set_transport(self, playing, frame, bar, beat, tick, bpm):
self.fTransportInfo = {
"playing": playing,
diff --git a/source/carla_database.py b/source/carla_database.py
index 5ce407b37..14ef20bd7 100755
--- a/source/carla_database.py
+++ b/source/carla_database.py
@@ -1482,9 +1482,9 @@ class PluginDatabaseW(QDialog):
AU_PATH = splitter.join(toList(settings.value(CARLA_KEY_PATHS_AU, CARLA_DEFAULT_AU_PATH)))
del settings
- internalCountNew = self.host.get_cached_plugin_count(PLUGIN_INTERNAL, "")
- lv2CountNew = self.host.get_cached_plugin_count(PLUGIN_LV2, LV2_PATH)
- auCountNew = self.host.get_cached_plugin_count(PLUGIN_AU, AU_PATH)
+ internalCountNew = gCarla.utils.get_cached_plugin_count(PLUGIN_INTERNAL, "")
+ lv2CountNew = gCarla.utils.get_cached_plugin_count(PLUGIN_LV2, LV2_PATH)
+ auCountNew = gCarla.utils.get_cached_plugin_count(PLUGIN_AU, AU_PATH)
if internalCountNew != internalCount or (len(internalPlugins) > 0 and
len(internalPlugins[0]) > 0 and
@@ -1492,7 +1492,7 @@ class PluginDatabaseW(QDialog):
internalPlugins = []
for i in range(internalCountNew):
- descInfo = self.host.get_cached_plugin_info(PLUGIN_INTERNAL, i)
+ descInfo = gCarla.utils.get_cached_plugin_info(PLUGIN_INTERNAL, i)
plugins = checkPluginCached(descInfo, PLUGIN_INTERNAL)
if plugins:
@@ -1506,7 +1506,7 @@ class PluginDatabaseW(QDialog):
lv2Plugins = []
for i in range(lv2CountNew):
- descInfo = self.host.get_cached_plugin_info(PLUGIN_LV2, i)
+ descInfo = gCarla.utils.get_cached_plugin_info(PLUGIN_LV2, i)
plugins = checkPluginCached(descInfo, PLUGIN_LV2)
if plugins:
@@ -1520,7 +1520,7 @@ class PluginDatabaseW(QDialog):
auPlugins = []
for i in range(auCountNew):
- descInfo = self.host.get_cached_plugin_info(PLUGIN_AU, i)
+ descInfo = gCarla.utils.get_cached_plugin_info(PLUGIN_AU, i)
plugins = checkPluginCached(descInfo, PLUGIN_AU)
if plugins:
diff --git a/source/carla_host.py b/source/carla_host.py
index 3f7340a34..65244d7c1 100644
--- a/source/carla_host.py
+++ b/source/carla_host.py
@@ -207,7 +207,7 @@ class HostWindow(QMainWindow):
self.fDirModel = QFileSystemModel(self)
self.fDirModel.setRootPath(HOME)
- self.fDirModel.setNameFilters(host.get_supported_file_extensions().split(";"))
+ self.fDirModel.setNameFilters(gCarla.utils.get_supported_file_extensions().split(";"))
self.ui.fileTreeView.setModel(self.fDirModel)
self.ui.fileTreeView.setRootIndex(self.fDirModel.index(HOME))
@@ -1328,7 +1328,7 @@ class HostWindow(QMainWindow):
@pyqtSlot()
def slot_aboutJuce(self):
- JuceAboutW(self, self.host).exec_()
+ JuceAboutW(self).exec_()
@pyqtSlot()
def slot_aboutQt(self):
diff --git a/source/carla_utils.py b/source/carla_utils.py
index 91627336b..0eb5d72e5 100644
--- a/source/carla_utils.py
+++ b/source/carla_utils.py
@@ -88,11 +88,72 @@ def getPluginTypeFromString(stype):
return PLUGIN_NONE
# ------------------------------------------------------------------------------------------------------------
-# Carla Pipe stuff
+# Carla Utils API (C stuff)
CarlaPipeClientHandle = c_void_p
CarlaPipeCallbackFunc = CFUNCTYPE(None, c_void_p, c_char_p)
+# Information about an internal Carla plugin.
+# @see carla_get_cached_plugin_info()
+class CarlaCachedPluginInfo(Structure):
+ _fields_ = [
+ # Plugin category.
+ ("category", c_enum),
+
+ # Plugin hints.
+ # @see PluginHints
+ ("hints", c_uint),
+
+ # Number of audio inputs.
+ ("audioIns", c_uint32),
+
+ # Number of audio outputs.
+ ("audioOuts", c_uint32),
+
+ # Number of MIDI inputs.
+ ("midiIns", c_uint32),
+
+ # Number of MIDI outputs.
+ ("midiOuts", c_uint32),
+
+ # Number of input parameters.
+ ("parameterIns", c_uint32),
+
+ # Number of output parameters.
+ ("parameterOuts", c_uint32),
+
+ # Plugin name.
+ ("name", c_char_p),
+
+ # Plugin label.
+ ("label", c_char_p),
+
+ # Plugin author/maker.
+ ("maker", c_char_p),
+
+ # Plugin copyright/license.
+ ("copyright", c_char_p)
+ ]
+
+# ------------------------------------------------------------------------------------------------------------
+# Carla Utils API (Python compatible stuff)
+
+# @see CarlaCachedPluginInfo
+PyCarlaCachedPluginInfo = {
+ 'category': PLUGIN_CATEGORY_NONE,
+ 'hints': 0x0,
+ 'audioIns': 0,
+ 'audioOuts': 0,
+ 'midiIns': 0,
+ 'midiOuts': 0,
+ 'parameterIns': 0,
+ 'parameterOuts': 0,
+ 'name': "",
+ 'label': "",
+ 'maker': "",
+ 'copyright': ""
+}
+
# ------------------------------------------------------------------------------------------------------------
# Carla Utils object using a DLL
@@ -102,14 +163,20 @@ class CarlaUtils(object):
self.lib = cdll.LoadLibrary(filename)
- self.lib.carla_get_library_filename.argtypes = None
- self.lib.carla_get_library_filename.restype = c_char_p
+ self.lib.carla_get_complete_license_text.argtypes = None
+ self.lib.carla_get_complete_license_text.restype = c_char_p
- self.lib.carla_get_library_folder.argtypes = None
- self.lib.carla_get_library_folder.restype = c_char_p
+ self.lib.carla_get_juce_version.argtypes = None
+ self.lib.carla_get_juce_version.restype = c_char_p
- self.lib.carla_set_locale_C.argtypes = None
- self.lib.carla_set_locale_C.restype = None
+ self.lib.carla_get_supported_file_extensions.argtypes = None
+ self.lib.carla_get_supported_file_extensions.restype = c_char_p
+
+ self.lib.carla_get_cached_plugin_count.argtypes = [c_enum, c_char_p]
+ self.lib.carla_get_cached_plugin_count.restype = c_uint
+
+ self.lib.carla_get_cached_plugin_info.argtypes = [c_enum, c_uint]
+ self.lib.carla_get_cached_plugin_info.restype = POINTER(CarlaCachedPluginInfo)
self.lib.carla_set_process_name.argtypes = [c_char_p]
self.lib.carla_set_process_name.restype = None
@@ -149,14 +216,30 @@ class CarlaUtils(object):
# --------------------------------------------------------------------------------------------------------
- def get_library_filename(self):
- return charPtrToString(self.lib.carla_get_library_filename())
-
- def get_library_folder(self):
- return charPtrToString(self.lib.carla_get_library_folder())
-
- def set_locale_C(self):
- self.lib.carla_set_locale_C()
+ # Get the complete license text of used third-party code and features.
+ # Returned string is in basic html format.
+ def get_complete_license_text(self):
+ return charPtrToString(self.lib.carla_get_complete_license_text())
+
+ # Get the juce version used in the current Carla build.
+ def get_juce_version(self):
+ return charPtrToString(self.lib.carla_get_juce_version())
+
+ # Get all the supported file extensions in carla_load_file().
+ # Returned string uses this syntax:
+ # @code
+ # "*.ext1;*.ext2;*.ext3"
+ # @endcode
+ def get_supported_file_extensions(self):
+ return charPtrToString(self.lib.carla_get_supported_file_extensions())
+
+ # Get how many internal plugins are available.
+ def get_cached_plugin_count(self, ptype, pluginPath):
+ return int(self.lib.carla_get_cached_plugin_count(ptype, pluginPath.encode("utf-8")))
+
+ # Get information about a cached plugin.
+ def get_cached_plugin_info(self, ptype, index):
+ return structToDict(self.lib.carla_get_cached_plugin_info(ptype, index).contents)
def set_process_name(self, name):
self.lib.carla_set_process_name(name.encode("utf-8"))
diff --git a/source/carla_widgets.py b/source/carla_widgets.py
index ce9b0c787..4061bf6bc 100755
--- a/source/carla_widgets.py
+++ b/source/carla_widgets.py
@@ -87,7 +87,7 @@ class CarlaAboutW(QDialog):
elif host.isPlugin:
self.ui.tabWidget.removeTab(2)
- self.ui.l_extended.setText(host.get_complete_license_text())
+ self.ui.l_extended.setText(gCarla.utils.get_complete_license_text())
if host.is_engine_running() and not (host.isControl or host.isPlugin):
self.ui.le_osc_url_tcp.setText(host.get_host_osc_url_tcp())
@@ -172,16 +172,12 @@ class CarlaAboutW(QDialog):
# JUCE About dialog
class JuceAboutW(QDialog):
- def __init__(self, parent, host):
+ def __init__(self, parent):
QDialog.__init__(self, parent)
self.ui = ui_carla_about_juce.Ui_JuceAboutW()
self.ui.setupUi(self)
- if False:
- # kdevelop likes this :)
- host = CarlaHostMeta()
-
- self.ui.l_text2.setText(self.tr("This program uses JUCE version %s." % host.get_juce_version()))
+ self.ui.l_text2.setText(self.tr("This program uses JUCE version %s." % gCarla.utils.get_juce_version()))
self.adjustSize()
self.setFixedSize(self.size())
diff --git a/source/plugin/carla-base.cpp b/source/plugin/carla-base.cpp
index 313aee79d..5d28f5900 100644
--- a/source/plugin/carla-base.cpp
+++ b/source/plugin/carla-base.cpp
@@ -33,6 +33,14 @@
using CarlaBackend::CarlaPlugin;
+// -----------------------------------------------------------------------
+
+CARLA_EXTERN_C
+std::size_t carla_getNativePluginCount();
+
+CARLA_EXTERN_C
+const NativePluginDescriptor* carla_getNativePluginDescriptor(const std::size_t index);
+
// -----------------------------------------------------------------------
// Plugin List
@@ -49,9 +57,9 @@ struct PluginListManager {
#endif
descs()
{
- for (size_t i=0, count = CarlaPlugin::getNativePluginCount(); i < count; ++i)
+ for (std::size_t i=0, count = carla_getNativePluginCount(); i < count; ++i)
{
- const NativePluginDescriptor* const desc(CarlaPlugin::getNativePluginDescriptor(i));
+ const NativePluginDescriptor* const desc(carla_getNativePluginDescriptor(i));
// Open/Save not possible in plugins
if (desc->hints & NATIVE_PLUGIN_NEEDS_UI_OPEN_SAVE)
diff --git a/source/utils/CarlaBackendUtils.hpp b/source/utils/CarlaBackendUtils.hpp
index b31659a67..8783aa421 100644
--- a/source/utils/CarlaBackendUtils.hpp
+++ b/source/utils/CarlaBackendUtils.hpp
@@ -19,7 +19,6 @@
#define CARLA_BACKEND_UTILS_HPP_INCLUDED
#include "CarlaBackend.h"
-#include "CarlaHost.h"
#include "CarlaString.hpp"
CARLA_BACKEND_START_NAMESPACE
diff --git a/source/widgets/racklistwidget.py b/source/widgets/racklistwidget.py
index d32330a4e..5e4b28673 100644
--- a/source/widgets/racklistwidget.py
+++ b/source/widgets/racklistwidget.py
@@ -134,7 +134,16 @@ class RackListWidget(QListWidget):
host = CarlaHostMeta()
self.host = host
- self.fSupportedExtensions = []
+ exts = gCarla.utils.get_supported_file_extensions().split(";")
+
+ exts.append(".dll")
+
+ if MACOS:
+ exts.append(".dylib")
+ if not WINDOWS:
+ exts.append(".so")
+
+ self.fSupportedExtensions = tuple(i.replace("*","") for i in exts)
self.fWasLastDragValid = False
self.setMinimumWidth(640)
@@ -162,17 +171,6 @@ class RackListWidget(QListWidget):
def setHost(self, host):
self.host = host
- exts = host.get_supported_file_extensions().split(";")
-
- exts.append(".dll")
-
- if MACOS:
- exts.append(".dylib")
- if not WINDOWS:
- exts.append(".so")
-
- self.fSupportedExtensions = tuple(i.replace("*","") for i in exts)
-
# --------------------------------------------------------------------------------------------------------
def isDragUrlValid(self, url):