diff --git a/source/backend/CarlaNative.h b/source/backend/CarlaNative.h index 24318cb75..6b629cb84 100644 --- a/source/backend/CarlaNative.h +++ b/source/backend/CarlaNative.h @@ -211,6 +211,9 @@ void carla_register_native_plugin_midiThrough(); void carla_register_native_plugin_midiTranspose(); void carla_register_native_plugin_nekofilter(); +// Carla +void carla_register_native_plugin_carla(); + #ifdef WANT_AUDIOFILE // AudioFile void carla_register_native_plugin_audiofile(); diff --git a/source/backend/CarlaPlugin.hpp b/source/backend/CarlaPlugin.hpp index 012854e78..fd3c59f01 100644 --- a/source/backend/CarlaPlugin.hpp +++ b/source/backend/CarlaPlugin.hpp @@ -192,12 +192,12 @@ public: /*! * Get the number of audio inputs. */ - virtual uint32_t audioInCount() const; + uint32_t audioInCount() const; /*! * Get the number of audio outputs. */ - virtual uint32_t audioOutCount() const; + uint32_t audioOutCount() const; /*! * Get the number of MIDI inputs. @@ -280,7 +280,7 @@ public: * * \see setCustomData() */ - const CustomData& customData(const size_t index) const; + const CustomData& customData(const uint32_t index) const; /*! * Get the complete plugin chunk data into \a dataPtr. diff --git a/source/backend/native/Makefile b/source/backend/native/Makefile index 5cd1ca535..a97b6ae4c 100644 --- a/source/backend/native/Makefile +++ b/source/backend/native/Makefile @@ -14,6 +14,9 @@ LINK_FLAGS += $(shell pkg-config --libs QtCore QtGui) # -------------------------------------------------------------- +CARLA_CXX_FLAGS = $(BUILD_CXX_FLAGS) +CARLA_CXX_FLAGS += -I../engine + ifeq ($(HAVE_AF_DEPS),true) AF_C_FLAGS = $(BUILD_C_FLAGS) AF_C_FLAGS += $(shell pkg-config --cflags libavcodec libavformat libavutil sndfile) @@ -59,6 +62,10 @@ OBJS += \ nekofilter.c.o endif +# Carla +OBJS += \ + carla.cpp.o + # AudioFile ifeq ($(HAVE_AF_DEPS),true) OBJS += \ @@ -171,6 +178,9 @@ $(STATIC): $(OBJS) audiofile.c.o: audiofile.c $(CC) $< $(AF_C_FLAGS) -c -o $@ +carla.cpp.o: carla.cpp + $(CXX) $< $(CARLA_CXX_FLAGS) -c -o $@ + distrho-3bandeq.cpp.o: distrho-3bandeq.cpp 3bandeq/DistrhoArtwork3BandEQ.cpp 3bandeq/DistrhoPlugin3BandEQ.cpp 3bandeq/DistrhoUI3BandEQ.cpp distrho/DistrhoPluginCarla.cpp $(CXX) $< $(GL_CXX_FLAGS) -I3bandeq -DDISTRHO_NAMESPACE=DISTRHO_3BandEQ -c -o $@ diff --git a/source/backend/native/carla.cpp b/source/backend/native/carla.cpp new file mode 100644 index 000000000..7fadf46b6 --- /dev/null +++ b/source/backend/native/carla.cpp @@ -0,0 +1,233 @@ +/* + * Carla Native Plugins + * Copyright (C) 2013 Filipe Coelho + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * For a full copy of the GNU General Public License see the GPL.txt file + */ + +#include "CarlaNative.hpp" + +#include "CarlaEngine.hpp" +#include "CarlaEngineInternal.hpp" + +CARLA_BACKEND_START_NAMESPACE + +// ----------------------------------------------------------------------- + +class CarlaEngineNative : public CarlaEngine, + public PluginDescriptorClass +{ +public: + CarlaEngineNative(const HostDescriptor* const host) + : CarlaEngine(), + PluginDescriptorClass(host) + { + carla_debug("CarlaEngineNative::CarlaEngineNative()"); + + // set-up engine + fOptions.processMode = PROCESS_MODE_CONTINUOUS_RACK; + fOptions.transportMode = TRANSPORT_MODE_INTERNAL; + fOptions.forceStereo = true; + fOptions.preferPluginBridges = false; + fOptions.preferUiBridges = false; + init("Carla"); + } + + ~CarlaEngineNative() + { + carla_debug("CarlaEngineNative::~CarlaEngineNative()"); + + setAboutToClose(); + removeAllPlugins(); + close(); + } + + // ------------------------------------- + // CarlaEngine virtual calls + + bool init(const char* const clientName) + { + carla_debug("CarlaEngineNative::init(\"%s\")", clientName); + + fBufferSize = CarlaEngine::getBufferSize(); + fSampleRate = CarlaEngine::getSampleRate(); + + CarlaEngine::init(clientName); + return true; + } + + bool close() + { + carla_debug("CarlaEngineNative::close()"); + CarlaEngine::close(); + + return true; + } + + bool isRunning() const + { + return true; + } + + bool isOffline() const + { + return false; + } + + EngineType type() const + { + return kEngineTypePlugin; + } + +protected: + // ------------------------------------------------------------------- + // Plugin parameter calls + + uint32_t getParameterCount() + { + if (kData->curPluginCount == 0 || kData->plugins == nullptr) + return 0; + + CarlaPlugin* const plugin(kData->plugins[0].plugin); + + if (plugin == nullptr || ! plugin->enabled()) + return 0; + + return kData->plugins[0].plugin->parameterCount(); + } + + const Parameter* getParameterInfo(const uint32_t index) + { + if (index >= getParameterCount()) + return nullptr; + + CarlaPlugin* const plugin(kData->plugins[0].plugin); + + if (plugin == nullptr || ! plugin->enabled()) + return nullptr; + + static ::Parameter param; + static char strBufName[STR_MAX+1]; + static char strBufUnit[STR_MAX+1]; + + const ParameterData& paramData(plugin->parameterData(index)); + const ParameterRanges& paramRanges(plugin->parameterRanges(index)); + + plugin->getParameterName(index, strBufName); + plugin->getParameterUnit(index, strBufUnit); + + int hints = 0x0; + + if (paramData.hints & PARAMETER_IS_BOOLEAN) + hints |= ::PARAMETER_IS_BOOLEAN; + if (paramData.hints & PARAMETER_IS_INTEGER) + hints |= ::PARAMETER_IS_INTEGER; + if (paramData.hints & PARAMETER_IS_LOGARITHMIC) + hints |= ::PARAMETER_IS_LOGARITHMIC; + if (paramData.hints & PARAMETER_IS_AUTOMABLE) + hints |= ::PARAMETER_IS_AUTOMABLE; + if (paramData.hints & PARAMETER_USES_SAMPLERATE) + hints |= ::PARAMETER_USES_SAMPLE_RATE; + if (paramData.hints & PARAMETER_USES_SCALEPOINTS) + hints |= ::PARAMETER_USES_SCALEPOINTS; + if (paramData.hints & PARAMETER_USES_CUSTOM_TEXT) + hints |= ::PARAMETER_USES_CUSTOM_TEXT; + + if (paramData.type == PARAMETER_INPUT || paramData.type == PARAMETER_OUTPUT) + { + if (paramData.hints & PARAMETER_IS_ENABLED) + hints |= ::PARAMETER_IS_ENABLED; + if (paramData.type == PARAMETER_OUTPUT) + hints |= ::PARAMETER_IS_OUTPUT; + } + + param.hints = (::ParameterHints)hints; + param.name = strBufName; + param.unit = strBufUnit; + param.ranges.def = paramRanges.def; + param.ranges.min = paramRanges.min; + param.ranges.max = paramRanges.max; + param.ranges.step = paramRanges.step; + param.ranges.stepSmall = paramRanges.stepSmall; + param.ranges.stepLarge = paramRanges.stepLarge; + param.scalePointCount = 0; // TODO + param.scalePoints = nullptr; + + return ¶m; + } + + float getParameterValue(const uint32_t index) + { + if (index >= getParameterCount()) + return 0.0f; + + CarlaPlugin* const plugin(kData->plugins[0].plugin); + + if (plugin == nullptr || ! plugin->enabled()) + return 0.0f; + + return plugin->getParameterValue(index); + } + + // ------------------------------------------------------------------- + // Plugin process calls + + void activate() + { + } + + void deactivate() + { + } + + void process(float**, float**, const uint32_t frames, const uint32_t midiEventCount, const MidiEvent* const midiEvents) + { + } + +private: + + PluginDescriptorClassEND(CarlaEngineNative) + CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineNative) +}; + +// ----------------------------------------------------------------------- + +static const PluginDescriptor carlaDesc = { + /* category */ ::PLUGIN_CATEGORY_OTHER, + /* hints */ /*static_cast<::PluginCategory>(*/::PLUGIN_IS_SYNTH/*)*/, + /* audioIns */ 2, + /* audioOuts */ 2, + /* midiIns */ 1, + /* midiOuts */ 1, + /* paramIns */ 0, + /* paramOuts */ 0, + /* name */ "Carla", + /* label */ "carla", + /* maker */ "falkTX", + /* copyright */ "GNU GPL v2+", + PluginDescriptorFILL(CarlaEngineNative) +}; + +// ----------------------------------------------------------------------- + +CARLA_BACKEND_END_NAMESPACE + +// ----------------------------------------------------------------------- + +void carla_register_native_plugin_carla() +{ + CARLA_BACKEND_USE_NAMESPACE + carla_register_native_plugin(&carlaDesc); +} + +// ----------------------------------------------------------------------- diff --git a/source/backend/plugin/CarlaPlugin.cpp b/source/backend/plugin/CarlaPlugin.cpp index 470964efa..57d634c4c 100644 --- a/source/backend/plugin/CarlaPlugin.cpp +++ b/source/backend/plugin/CarlaPlugin.cpp @@ -248,7 +248,7 @@ const MidiProgramData& CarlaPlugin::midiProgramData(const uint32_t index) const return (index < kData->midiprog.count) ? kData->midiprog.data[index] : kMidiProgramDataNull; } -const CustomData& CarlaPlugin::customData(const size_t index) const +const CustomData& CarlaPlugin::customData(const uint32_t index) const { CARLA_ASSERT(index < kData->custom.count()); @@ -258,6 +258,7 @@ const CustomData& CarlaPlugin::customData(const size_t index) const int32_t CarlaPlugin::chunkData(void** const dataPtr) { CARLA_ASSERT(dataPtr != nullptr); + CARLA_ASSERT(false); // this should never happen return 0; // unused @@ -269,12 +270,14 @@ int32_t CarlaPlugin::chunkData(void** const dataPtr) unsigned int CarlaPlugin::availableOptions() { + CARLA_ASSERT(false); // this should never happen return 0x0; } float CarlaPlugin::getParameterValue(const uint32_t parameterId) { CARLA_ASSERT(parameterId < parameterCount()); + CARLA_ASSERT(false); // this should never happen return 0.0f; // unused @@ -285,6 +288,7 @@ float CarlaPlugin::getParameterScalePointValue(const uint32_t parameterId, const { CARLA_ASSERT(parameterId < parameterCount()); CARLA_ASSERT(scalePointId < parameterScalePointCount(parameterId)); + CARLA_ASSERT(false); // this should never happen return 0.0f; // unused @@ -294,28 +298,28 @@ float CarlaPlugin::getParameterScalePointValue(const uint32_t parameterId, const void CarlaPlugin::getLabel(char* const strBuf) { - *strBuf = 0; + *strBuf = '\0'; } void CarlaPlugin::getMaker(char* const strBuf) { - *strBuf = 0; + *strBuf = '\0'; } void CarlaPlugin::getCopyright(char* const strBuf) { - *strBuf = 0; + *strBuf = '\0'; } void CarlaPlugin::getRealName(char* const strBuf) { - *strBuf = 0; + *strBuf = '\0'; } void CarlaPlugin::getParameterName(const uint32_t parameterId, char* const strBuf) { CARLA_ASSERT(parameterId < parameterCount()); - *strBuf = 0; + *strBuf = '\0'; return; // unused @@ -325,7 +329,7 @@ void CarlaPlugin::getParameterName(const uint32_t parameterId, char* const strBu void CarlaPlugin::getParameterSymbol(const uint32_t parameterId, char* const strBuf) { CARLA_ASSERT(parameterId < parameterCount()); - *strBuf = 0; + *strBuf = '\0'; return; // unused @@ -335,7 +339,7 @@ void CarlaPlugin::getParameterSymbol(const uint32_t parameterId, char* const str void CarlaPlugin::getParameterText(const uint32_t parameterId, char* const strBuf) { CARLA_ASSERT(parameterId < parameterCount()); - *strBuf = 0; + *strBuf = '\0'; return; // unused @@ -345,7 +349,7 @@ void CarlaPlugin::getParameterText(const uint32_t parameterId, char* const strBu void CarlaPlugin::getParameterUnit(const uint32_t parameterId, char* const strBuf) { CARLA_ASSERT(parameterId < parameterCount()); - *strBuf = 0; + *strBuf = '\0'; return; // unused @@ -356,7 +360,7 @@ void CarlaPlugin::getParameterScalePointLabel(const uint32_t parameterId, const { CARLA_ASSERT(parameterId < parameterCount()); CARLA_ASSERT(scalePointId < parameterScalePointCount(parameterId)); - *strBuf = 0; + *strBuf = '\0'; return; // unused @@ -372,7 +376,7 @@ void CarlaPlugin::getProgramName(const uint32_t index, char* const strBuf) if (index < kData->prog.count && kData->prog.names[index]) std::strncpy(strBuf, kData->prog.names[index], STR_MAX); else - *strBuf = 0; + *strBuf = '\0'; } void CarlaPlugin::getMidiProgramName(const uint32_t index, char* const strBuf) @@ -383,7 +387,7 @@ void CarlaPlugin::getMidiProgramName(const uint32_t index, char* const strBuf) if (index < kData->midiprog.count && kData->midiprog.data[index].name) std::strncpy(strBuf, kData->midiprog.data[index].name, STR_MAX); else - *strBuf = 0; + *strBuf = '\0'; } void CarlaPlugin::getParameterCountInfo(uint32_t* const ins, uint32_t* const outs, uint32_t* const total) @@ -478,6 +482,26 @@ const SaveState& CarlaPlugin::getSaveState() saveState.panning = kData->postProc.panning; saveState.ctrlChannel = kData->ctrlChannel; + // ---------------------------- + // Chunk + + if (fOptions & PLUGIN_OPTION_USE_CHUNKS) + { + void* data = nullptr; + const int32_t dataSize(chunkData(&data)); + + if (data != nullptr && dataSize >= 4) + { + CarlaString chunkStr; + chunkStr.importBinaryAsBase64((const uint8_t*)data, static_cast(dataSize)); + + saveState.chunk = carla_strdup(chunkStr); + + // Don't save anything else if using chunks + return saveState; + } + } + // ---------------------------- // Current Program @@ -492,7 +516,8 @@ const SaveState& CarlaPlugin::getSaveState() if (kData->midiprog.current >= 0) { - const MidiProgramData& mpData = kData->midiprog.getCurrent(); + const MidiProgramData& mpData(kData->midiprog.getCurrent()); + saveState.currentMidiBank = mpData.bank; saveState.currentMidiProgram = mpData.program; } @@ -500,16 +525,16 @@ const SaveState& CarlaPlugin::getSaveState() // ---------------------------- // Parameters - float sampleRate = kData->engine->getSampleRate(); + const float sampleRate(kData->engine->getSampleRate()); for (uint32_t i=0, count=kData->param.count; i < count; i++) { - const ParameterData& paramData = kData->param.data[i]; + const ParameterData& paramData(kData->param.data[i]); if ((paramData.hints & PARAMETER_IS_AUTOMABLE) == 0) continue; - StateParameter* stateParameter(new StateParameter); + StateParameter* stateParameter(new StateParameter()); stateParameter->index = paramData.index; stateParameter->midiCC = paramData.midiCC; @@ -539,7 +564,7 @@ const SaveState& CarlaPlugin::getSaveState() if (cData.type == nullptr) continue; - StateCustomData* stateCustomData(new StateCustomData); + StateCustomData* stateCustomData(new StateCustomData()); stateCustomData->type = carla_strdup(cData.type); stateCustomData->key = carla_strdup(cData.key); @@ -548,23 +573,6 @@ const SaveState& CarlaPlugin::getSaveState() saveState.customData.push_back(stateCustomData); } - // ---------------------------- - // Chunk - - if (fOptions & PLUGIN_OPTION_USE_CHUNKS) - { - void* data = nullptr; - const int32_t dataSize = chunkData(&data); - - if (data != nullptr && dataSize >= 4) - { - CarlaString chunkStr; - chunkStr.importBinaryAsBase64((const uint8_t*)data, static_cast(dataSize)); - - saveState.chunk = carla_strdup(chunkStr); - } - } - return saveState; } @@ -635,10 +643,6 @@ void CarlaPlugin::loadSaveState(const SaveState& saveState) uint32_t index; const char* symbol; - ParamSymbol() - : index(0), - symbol(nullptr) {} - ParamSymbol(uint32_t index_, const char* symbol_) : index(index_), symbol(carla_strdup(symbol_)) {} @@ -651,9 +655,13 @@ void CarlaPlugin::loadSaveState(const SaveState& saveState) symbol = nullptr; } } + + ParamSymbol() = delete; + ParamSymbol(ParamSymbol&) = delete; + ParamSymbol(const ParamSymbol&) = delete; }; - QVector paramSymbols; + QVector paramSymbols; if (type() == PLUGIN_LADSPA || type() == PLUGIN_LV2) { @@ -661,9 +669,9 @@ void CarlaPlugin::loadSaveState(const SaveState& saveState) { getParameterSymbol(i, strBuf); - if (*strBuf != 0) + if (*strBuf != '\0') { - ParamSymbol paramSymbol(i, strBuf); + ParamSymbol* const paramSymbol(new ParamSymbol(i, strBuf)); paramSymbols.append(paramSymbol); } } @@ -672,11 +680,11 @@ void CarlaPlugin::loadSaveState(const SaveState& saveState) // --------------------------------------------------------------------- // Part 4b - set parameter values (carefully) - float sampleRate = kData->engine->getSampleRate(); + const float sampleRate(kData->engine->getSampleRate()); for (auto it = saveState.parameters.begin(); it != saveState.parameters.end(); ++it) { - StateParameter* stateParameter = *it; + StateParameter* const stateParameter(*it); int32_t index = -1; @@ -685,11 +693,11 @@ void CarlaPlugin::loadSaveState(const SaveState& saveState) // Try to set by symbol, otherwise use index if (stateParameter->symbol != nullptr && *stateParameter->symbol != 0) { - foreach (const ParamSymbol& paramSymbol, paramSymbols) + foreach (const ParamSymbol* paramSymbol, paramSymbols) { - if (std::strcmp(stateParameter->symbol, paramSymbol.symbol) == 0) + if (std::strcmp(stateParameter->symbol, paramSymbol->symbol) == 0) { - index = paramSymbol.index; + index = paramSymbol->index; break; } } @@ -704,11 +712,11 @@ void CarlaPlugin::loadSaveState(const SaveState& saveState) // Symbol only if (stateParameter->symbol != nullptr && *stateParameter->symbol != 0) { - foreach (const ParamSymbol& paramSymbol, paramSymbols) + foreach (const ParamSymbol* paramSymbol, paramSymbols) { - if (std::strcmp(stateParameter->symbol, paramSymbol.symbol) == 0) + if (std::strcmp(stateParameter->symbol, paramSymbol->symbol) == 0) { - index = paramSymbol.index; + index = paramSymbol->index; break; } } @@ -739,8 +747,13 @@ void CarlaPlugin::loadSaveState(const SaveState& saveState) } // clear - foreach (ParamSymbol paramSymbol, paramSymbols) - paramSymbol.free(); + foreach (ParamSymbol* paramSymbol, paramSymbols) + { + paramSymbol->free(); + delete paramSymbol; + } + + paramSymbols.clear(); // --------------------------------------------------------------------- // Part 5 - set chunk data @@ -822,17 +835,6 @@ bool CarlaPlugin::loadStateFromFile(const char* const filename) void CarlaPlugin::setId(const unsigned int id) { fId = id; - - if (kData->engine->getProccessMode() == PROCESS_MODE_CONTINUOUS_RACK) - { - CARLA_ASSERT(id < MAX_RACK_PLUGINS); - - if (id >= MAX_RACK_PLUGINS || kData->ctrlChannel == static_cast(id)) - return; - - kData->ctrlChannel = id; - kData->engine->callback(CALLBACK_PARAMETER_VALUE_CHANGED, fId, PARAMETER_CTRL_CHANNEL, 0, id, nullptr); - } } void CarlaPlugin::setOption(const unsigned int option, const bool yesNo) diff --git a/source/backend/plugin/NativePlugin.cpp b/source/backend/plugin/NativePlugin.cpp index 4d1a712b9..f4c5b4d7a 100644 --- a/source/backend/plugin/NativePlugin.cpp +++ b/source/backend/plugin/NativePlugin.cpp @@ -36,6 +36,9 @@ void carla_register_all_plugins() //carla_register_native_plugin_nekofilter(); // needs UI stuff #endif + // Carla + carla_register_native_plugin_carla(); + #ifdef WANT_AUDIOFILE // AudioFile carla_register_native_plugin_audiofile(); @@ -712,6 +715,7 @@ public: if (params > 0) { kData->param.createNew(params); + carla_stdout("HAS %i PARAMS", params); } const uint portNameSize = kData->engine->maxPortNameSize(); @@ -831,6 +835,11 @@ public: { const ::Parameter* const paramInfo = fDescriptor->get_parameter_info(fHandle, j); + CARLA_ASSERT(paramInfo != nullptr); + + if (paramInfo == nullptr) + continue; + kData->param.data[j].index = j; kData->param.data[j].rindex = j; kData->param.data[j].hints = 0x0;