diff --git a/c++/carla-backend/carla_native.cpp b/c++/carla-backend/carla_native.cpp new file mode 100644 index 0000000..8827d4d --- /dev/null +++ b/c++/carla-backend/carla_native.cpp @@ -0,0 +1,267 @@ +/* + * Carla Backend + * Copyright (C) 2012 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 COPYING file + */ + +#include "carla_plugin.h" +#include "plugins/carla_native.h" + +CARLA_BACKEND_START_NAMESPACE + +class NativePluginScopedInitiliazer +{ +public: + NativePluginScopedInitiliazer() + { + } + + ~NativePluginScopedInitiliazer() + { + for (size_t i=0; i < descriptors.size(); i++) + { + const PluginDescriptor* const desc = descriptors[i]; + + if (desc->_fini) + desc->_fini((struct _PluginDescriptor*)desc); + } + + descriptors.clear(); + } + + void initializeIfNeeded(const PluginDescriptor* const desc) + { + if (descriptors.empty() || std::find(descriptors.begin(), descriptors.end(), desc) == descriptors.end()) + { + if (desc->_init) + desc->_init((struct _PluginDescriptor*)desc); + + descriptors.push_back(desc); + } + } + +private: + std::vector descriptors; +}; + +static NativePluginScopedInitiliazer scopedInitliazer; + +class NativePlugin : public CarlaPlugin +{ +public: + NativePlugin(CarlaEngine* const engine, const unsigned short id) + : CarlaPlugin(engine, id) + { + qDebug("NativePlugin::NativePlugin()"); + + m_type = PLUGIN_NONE; + + descriptor = nullptr; + handle = nullptr; + } + + ~NativePlugin() + { + qDebug("NativePlugin::~NativePlugin()"); + + if (handle) + pass(); + } + + // ------------------------------------------------------------------- + // Information (base) + + PluginCategory category() + { + Q_ASSERT(descriptor); + + if (descriptor) + return (PluginCategory)descriptor->category; + + return getPluginCategoryFromName(m_name); + } + + // ------------------------------------------------------------------- + // Information (per-plugin data) + + double getParameterValue(const uint32_t parameterId) + { + Q_ASSERT(descriptor); + Q_ASSERT(parameterId < param.count); + + //return descriptor->get_parameter_value(); + return 0.0; + } + + void getLabel(char* const strBuf) + { + Q_ASSERT(descriptor); + + if (descriptor && descriptor->label) + strncpy(strBuf, descriptor->label, STR_MAX); + else + CarlaPlugin::getLabel(strBuf); + } + + void getMaker(char* const strBuf) + { + Q_ASSERT(descriptor); + + //if (descriptor && descriptor->maker) + // strncpy(strBuf, descriptor->maker, STR_MAX); + //else + CarlaPlugin::getMaker(strBuf); + } + + void getCopyright(char* const strBuf) + { + Q_ASSERT(descriptor); + + //if (descriptor && descriptor->copyright) + // strncpy(strBuf, descriptor->copyright, STR_MAX); + //else + CarlaPlugin::getCopyright(strBuf); + } + + void getRealName(char* const strBuf) + { + Q_ASSERT(descriptor); + + if (descriptor && descriptor->name) + strncpy(strBuf, descriptor->name, STR_MAX); + else + CarlaPlugin::getRealName(strBuf); + } + + void getParameterName(const uint32_t parameterId, char* const strBuf) + { + Q_ASSERT(descriptor); + Q_ASSERT(parameterId < param.count); + + int32_t rindex = param.data[parameterId].rindex; + + if (descriptor && rindex < (int32_t)descriptor->portCount) + strncpy(strBuf, descriptor->ports[rindex].name, STR_MAX); + else + CarlaPlugin::getParameterName(parameterId, strBuf); + } + + // ------------------------------------------------------------------- + + static size_t getPluginCount() + { + return pluginDescriptors.size(); + } + + static void registerPlugin(const PluginDescriptor* desc) + { + pluginDescriptors.push_back(desc); + } + + // ------------------------------------------------------------------- + + bool init(const char* const name, const char* const label) + { + // --------------------------------------------------------------- + // get plugin + + for (size_t i=0; i < pluginDescriptors.size(); i++) + { + descriptor = pluginDescriptors[i]; + + if (! descriptor) + break; + if (strcmp(descriptor->label, label) == 0) + break; + + descriptor = nullptr; + } + + if (! descriptor) + { + setLastError("Invalid internal plugin"); + return false; + } + + scopedInitliazer.initializeIfNeeded(descriptor); + + // --------------------------------------------------------------- + // get info + + if (name) + m_name = x_engine->getUniqueName(name); + else + m_name = x_engine->getUniqueName(descriptor->name); + + // --------------------------------------------------------------- + // register client + + x_client = x_engine->addClient(this); + + if (! x_client->isOk()) + { + setLastError("Failed to register plugin client"); + return false; + } + + return true; + } + +private: + const PluginDescriptor* descriptor; + PluginHandle handle; + + static std::vector pluginDescriptors; +}; + +std::vector NativePlugin::pluginDescriptors; + +CarlaPlugin* CarlaPlugin::newNative(const initializer& init) +{ + qDebug("CarlaPlugin::newNative(%p, \"%s\", \"%s\", \"%s\")", init.engine, init.filename, init.name, init.label); + + short id = init.engine->getNewPluginId(); + + if (id < 0 || id > CarlaEngine::maxPluginNumber()) + { + setLastError("Maximum number of plugins reached"); + return nullptr; + } + + NativePlugin* const plugin = new NativePlugin(init.engine, id); + + if (! plugin->init(init.name, init.label)) + { + delete plugin; + return nullptr; + } + + plugin->reload(); + plugin->registerToOsc(); + + return plugin; +} + +size_t CarlaPlugin::getNativePluginCount() +{ + return NativePlugin::getPluginCount(); +} + +CARLA_BACKEND_END_NAMESPACE + +void carla_register_native_plugin(const PluginDescriptor* desc) +{ + printf("contructing plugin, THERE \"%s\"\n", desc->name); + CarlaBackend::NativePlugin::registerPlugin(desc); +} diff --git a/c++/carla-backend/plugins/bypass.c b/c++/carla-backend/plugins/bypass.c new file mode 100644 index 0000000..7589db5 --- /dev/null +++ b/c++/carla-backend/plugins/bypass.c @@ -0,0 +1,65 @@ +/* + * Carla Native Plugins + * Copyright (C) 2012 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 COPYING file + */ + +#include "carla_native.h" + +#include + +enum ByPassPorts { + PORT_IN, + PORT_OUT, + PORT_MAX +}; + +struct ByPassInstance { +}; + +void bypass_init(struct _PluginDescriptor* _this_) +{ + _this_->portCount = PORT_MAX; + _this_->ports = malloc(sizeof(PluginPort) * PORT_MAX); + + _this_->ports[PORT_IN].type = PORT_TYPE_AUDIO; + _this_->ports[PORT_IN].hints = 0; + _this_->ports[PORT_IN].name = "in"; + + + _this_->ports[PORT_OUT].type = PORT_TYPE_AUDIO; + _this_->ports[PORT_OUT].hints = PORT_HINT_IS_OUTPUT; + _this_->ports[PORT_OUT].name = "out"; +} + +void bypass_fini(struct _PluginDescriptor* _this_) +{ + free(_this_->ports); + + _this_->portCount = 0; + _this_->ports = NULL; +} + +static PluginDescriptor bypassDesc = { + .category = PLUGIN_CATEGORY_NONE, + .name = "ByPass", + .label = "bypass", + .portCount = 0, + .ports = NULL, + ._handle = NULL, + ._init = NULL, + ._fini = NULL +}; + +CARLA_REGISTER_NATIVE_PLUGIN(bypass, bypassDesc) diff --git a/c++/carla-backend/plugins/carla_native.h b/c++/carla-backend/plugins/carla_native.h new file mode 100644 index 0000000..a30096c --- /dev/null +++ b/c++/carla-backend/plugins/carla_native.h @@ -0,0 +1,185 @@ +/* + * Carla Native Plugin API + * Copyright (C) 2012 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 COPYING file + */ + +#ifndef CARLA_NATIVE_H +#define CARLA_NATIVE_H + +#ifdef __cplusplus +extern "C" { +#else +#include +#endif + +#include +#include + +typedef void* PluginHandle; + +const uint32_t PLUGIN_IS_SYNTH = 1 << 0; +const uint32_t PLUGIN_HAS_GUI = 1 << 1; +const uint32_t PLUGIN_USES_SINGLE_THREAD = 1 << 2; + +const uint32_t PORT_HINT_IS_OUTPUT = 1 << 0; +const uint32_t PORT_HINT_IS_ENABLED = 1 << 1; +const uint32_t PORT_HINT_IS_AUTOMABLE = 1 << 2; +const uint32_t PORT_HINT_IS_BOOLEAN = 1 << 3; +const uint32_t PORT_HINT_IS_INTEGER = 1 << 4; +const uint32_t PORT_HINT_IS_LOGARITHMIC = 1 << 5; +const uint32_t PORT_HINT_USES_SAMPLE_RATE = 1 << 6; +const uint32_t PORT_HINT_USES_SCALEPOINTS = 1 << 7; +const uint32_t PORT_HINT_USES_CUSTOM_TEXT = 1 << 8; + +typedef enum _PluginCategory { + PLUGIN_CATEGORY_NONE = 0, //!< Null plugin category. + PLUGIN_CATEGORY_SYNTH = 1, //!< A synthesizer or generator. + PLUGIN_CATEGORY_DELAY = 2, //!< A delay or reverberator. + PLUGIN_CATEGORY_EQ = 3, //!< An equalizer. + PLUGIN_CATEGORY_FILTER = 4, //!< A filter. + PLUGIN_CATEGORY_DYNAMICS = 5, //!< A 'dynamic' plugin (amplifier, compressor, gate, etc). + PLUGIN_CATEGORY_MODULATOR = 6, //!< A 'modulator' plugin (chorus, flanger, phaser, etc). + PLUGIN_CATEGORY_UTILITY = 7, //!< An 'utility' plugin (analyzer, converter, mixer, etc). + PLUGIN_CATEGORY_OTHER = 8 //!< Misc plugin (used to check if the plugin has a category). +} PluginCategory; + +typedef enum _PortType { + PORT_TYPE_NULL = 0, + PORT_TYPE_AUDIO = 1, + PORT_TYPE_MIDI = 2, + PORT_TYPE_PARAMETER = 3 +} PortType; + +typedef struct _ParameterRanges { + double def; + double min; + double max; + double step; + double stepSmall; + double stepLarge; +} ParameterRanges; + +typedef struct _MidiEvent { + uint32_t time; + uint8_t size; + uint8_t data[4]; +} MidiEvent; + +typedef struct _MidiProgram { + uint32_t bank; + uint32_t program; + const char* name; +} MidiProgram; + +typedef struct _TimeInfoBBT { + int32_t bar; + int32_t beat; + int32_t tick; + double bar_start_tick; + float beats_per_bar; + float beat_type; + double ticks_per_beat; + double beats_per_minute; +} TimeInfoBBT; + +typedef struct _TimeInfo { + bool playing; + uint32_t frame; + uint32_t time; + uint32_t valid; + TimeInfoBBT bbt; +} TimeInfo; + +typedef struct _PluginPortScalePoint { + const char* label; + double value; +} PluginPortScalePoint; + +typedef struct _PluginPort { + PortType type; + uint32_t hints; + const char* name; + + uint32_t scalePointCount; + PluginPortScalePoint* scalePoints; +} PluginPort; + +typedef struct _PluginDescriptor { + PluginCategory category; + uint32_t hints; + const char* name; + const char* label; + const char* maker; + const char* copyright; + + uint32_t portCount; + PluginPort* ports; + + uint32_t midiProgramCount; + MidiProgram* midiPrograms; + + PluginHandle (*instantiate)(struct _PluginDescriptor* _this_); + void (*activate)(PluginHandle handle); + void (*deactivate)(PluginHandle handle); + void (*cleanup)(PluginHandle handle); + + void (*get_parameter_ranges)(PluginHandle handle, uint32_t index, ParameterRanges* ranges); + double (*get_parameter_value)(PluginHandle handle, uint32_t index); + const char* (*get_parameter_text)(PluginHandle handle, uint32_t index); + const char* (*get_parameter_unit)(PluginHandle handle, uint32_t index); + + void (*set_parameter_value)(PluginHandle handle, uint32_t index, double value); + void (*set_midi_program)(PluginHandle handle, uint32_t bank, uint32_t program); + void (*set_custom_data)(PluginHandle handle, const char* key, const char* value); + + void (*show_gui)(PluginHandle handle, bool show); + void (*idle_gui)(PluginHandle handle); + + // TODO - ui_set_* + + void (*process)(PluginHandle handle, float** inBuffer, float** outBuffer, uint32_t frames, uint32_t midiEventCount, MidiEvent* midiEvents); + // TODO - midi stuff^ + + PluginHandle _handle; + void (*_init)(struct _PluginDescriptor* _this_); + void (*_fini)(struct _PluginDescriptor* _this_); +} PluginDescriptor; + +// ----------------------------------------------------------------------- + +void carla_register_native_plugin(const PluginDescriptor* desc); + +#define CARLA_NATIVE_PARAMETER_RANGES_INIT { 0.0, 0.0, 1.0, 0.01, 0.0001, 0.1 } + +#define CARLA_NATIVE_PLUGIN_INIT { \ + PLUGIN_CATEGORY_NONE, 0, NULL, NULL, NULL, NULL, \ + 0, NULL, 0, NULL, \ + NULL, NULL, NULL, NULL, \ + NULL, NULL, NULL, NULL, \ + NULL, NULL, NULL, \ + NULL, NULL, \ + NULL, \ + NULL, NULL, NULL \ + } + +#define CARLA_REGISTER_NATIVE_PLUGIN(label, desc) \ + void carla_register_native_plugin_##label () __attribute__((constructor)); \ + void carla_register_native_plugin_##label () { carla_register_native_plugin(&desc); } + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif // CARLA_NATIVE_H diff --git a/c++/carla-backend/plugins/carla_nativemm.h b/c++/carla-backend/plugins/carla_nativemm.h new file mode 100644 index 0000000..806827d --- /dev/null +++ b/c++/carla-backend/plugins/carla_nativemm.h @@ -0,0 +1,412 @@ +/* + * Carla Native Plugin API + * Copyright (C) 2012 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 COPYING file + */ + +#ifndef CARLA_NATIVE_MM_H +#define CARLA_NATIVE_MM_H + +#include "carla_native.h" +#include "carla_includes.h" + +class PluginDescriptorClass { +public: + PluginDescriptorClass() + { + desc.category = PLUGIN_CATEGORY_NONE; + desc.hints = 0; + desc.name = nullptr; + desc.label = nullptr; + desc.maker = nullptr; + desc.copyright = nullptr; + + desc.portCount = 0; + desc.ports = nullptr; + + desc.midiProgramCount = 0; + desc.midiPrograms = nullptr; + + desc.instantiate = _instantiate; + desc.activate = _activate; + desc.deactivate = _deactivate; + desc.cleanup = _cleanup; + + desc.get_parameter_ranges = _get_parameter_ranges; + desc.get_parameter_value = _get_parameter_value; + desc.get_parameter_text = _get_parameter_text; + desc.get_parameter_unit = _get_parameter_unit; + + desc.set_parameter_value = _set_parameter_value; + desc.set_midi_program = _set_midi_program; + desc.set_custom_data = _set_custom_data; + + desc.show_gui = _show_gui; + desc.idle_gui = _idle_gui; + + desc.process = _process; + + desc._handle = this; + desc._init = _init; + desc._fini = _fini; + } + + PluginDescriptorClass(PluginDescriptorClass* that) + { + desc.category = that->desc.category; + desc.hints = that->desc.hints; + desc.name = that->desc.name; + desc.label = that->desc.label; + desc.maker = that->desc.maker; + desc.copyright = that->desc.copyright; + + desc.portCount = that->desc.portCount; + desc.ports = that->desc.ports; + + desc.midiProgramCount = that->desc.midiProgramCount; + desc.midiPrograms = that->desc.midiPrograms; + + desc.instantiate = _instantiate; + desc.activate = _activate; + desc.deactivate = _deactivate; + desc.cleanup = _cleanup; + + desc.get_parameter_ranges = _get_parameter_ranges; + desc.get_parameter_value = _get_parameter_value; + desc.get_parameter_text = _get_parameter_text; + desc.get_parameter_unit = _get_parameter_unit; + + desc.set_parameter_value = _set_parameter_value; + desc.set_midi_program = _set_midi_program; + desc.set_custom_data = _set_custom_data; + + desc.show_gui = _show_gui; + desc.idle_gui = _idle_gui; + + desc.process = _process; + + desc._handle = this; + desc._init = _init; + desc._fini = _fini; + } + + virtual ~PluginDescriptorClass() + { + } + + PluginDescriptor* descriptorInit() + { + desc.category = getCategory(); + desc.hints = getHints(); + desc.name = getName(); + desc.label = getLabel(); + desc.maker = getMaker(); + desc.copyright = getCopyright(); + return &desc; + } + + // ------------------------------------------------------------------- + +protected: + virtual PluginDescriptorClass* createMe() = 0; + virtual void deleteMe() = 0; + + virtual PluginCategory getCategory() + { + return PLUGIN_CATEGORY_NONE; + } + + virtual uint32_t getHints() + { + return 0; + } + + virtual const char* getName() + { + return nullptr; + } + + virtual const char* getLabel() + { + return nullptr; + } + + virtual const char* getMaker() + { + return nullptr; + } + + virtual const char* getCopyright() + { + return nullptr; + } + + // ------------------------------------------------------------------- + + virtual uint32_t getPortCount() + { + return 0; + } + + virtual PortType getPortType(uint32_t index) + { + Q_ASSERT(index < getPortCount()); + + return PORT_TYPE_NULL; + } + + virtual uint32_t getPortHints(uint32_t index) + { + Q_ASSERT(index < getPortCount()); + + return 0; + } + + virtual const char* getPortName(uint32_t index) + { + Q_ASSERT(index < getPortCount()); + + return nullptr; + } + + virtual void getParameterRanges(uint32_t index, ParameterRanges* ranges) + { + Q_ASSERT(index < getPortCount()); + Q_ASSERT(ranges); + } + + virtual double getParameterValue(uint32_t index) + { + Q_ASSERT(index < getPortCount()); + + return 0.0; + } + + virtual const char* getParameterText(uint32_t index) + { + Q_ASSERT(index < getPortCount()); + + return nullptr; + } + + virtual const char* getParameterUnit(uint32_t index) + { + Q_ASSERT(index < getPortCount()); + + return nullptr; + } + + // ------------------------------------------------------------------- + + virtual uint32_t getMidiProgramCount() + { + return 0; + } + + virtual void getMidiProgram(uint32_t index, MidiProgram* midiProgram) + { + Q_ASSERT(index < getMidiProgramCount()); + Q_ASSERT(midiProgram); + } + + // ------------------------------------------------------------------- + + virtual void setParameterValue(uint32_t index, double value) + { + Q_ASSERT(index < getPortCount()); + Q_UNUSED(value); + } + + virtual void setMidiProgram(uint32_t bank, uint32_t program) + { + Q_ASSERT(program < 128); + Q_UNUSED(bank); + } + + virtual void setCustomData(const char* key, const char* value) + { + Q_ASSERT(key); + Q_ASSERT(value); + } + + // ------------------------------------------------------------------- + + virtual void activate() + { + } + + virtual void deactivate() + { + } + + // ------------------------------------------------------------------- + + virtual void showGui(bool show) + { + Q_UNUSED(show); + } + + virtual void idleGui() + { + } + + // ------------------------------------------------------------------- + + virtual void process(float** inBuffer, float** outBuffer, const uint32_t frames, uint32_t midiEventCount, MidiEvent* midiEvents) + { + Q_ASSERT(inBuffer); + Q_ASSERT(outBuffer); + Q_ASSERT(midiEvents); + + Q_UNUSED(frames); + Q_UNUSED(midiEventCount); + } + + // ------------------------------------------------------------------- + +private: + PluginDescriptor desc; + + static PluginHandle _instantiate(struct _PluginDescriptor* _this_) + { + return ((PluginDescriptorClass*)_this_->_handle)->createMe(); + } + + static void _activate(PluginHandle handle) + { + ((PluginDescriptorClass*)handle)->activate(); + } + + static void _deactivate(PluginHandle handle) + { + ((PluginDescriptorClass*)handle)->deactivate(); + } + + static void _cleanup(PluginHandle handle) + { + ((PluginDescriptorClass*)handle)->deleteMe(); + } + + static void _get_parameter_ranges(PluginHandle handle, uint32_t index, ParameterRanges* ranges) + { + ((PluginDescriptorClass*)handle)->getParameterRanges(index, ranges); + } + + static double _get_parameter_value(PluginHandle handle, uint32_t index) + { + return ((PluginDescriptorClass*)handle)->getParameterValue(index); + } + + static const char* _get_parameter_text(PluginHandle handle, uint32_t index) + { + return ((PluginDescriptorClass*)handle)->getParameterText(index); + } + + static const char* _get_parameter_unit(PluginHandle handle, uint32_t index) + { + return ((PluginDescriptorClass*)handle)->getParameterUnit(index); + } + + static void _set_parameter_value(PluginHandle handle, uint32_t index, double value) + { + return ((PluginDescriptorClass*)handle)->setParameterValue(index, value); + } + + static void _set_midi_program(PluginHandle handle, uint32_t bank, uint32_t program) + { + return ((PluginDescriptorClass*)handle)->setMidiProgram(bank, program); + } + + static void _set_custom_data(PluginHandle handle, const char* key, const char* value) + { + return ((PluginDescriptorClass*)handle)->setCustomData(key, value); + } + + static void _show_gui(PluginHandle handle, bool show) + { + return ((PluginDescriptorClass*)handle)->showGui(show); + } + + static void _idle_gui(PluginHandle handle) + { + return ((PluginDescriptorClass*)handle)->idleGui(); + } + + static void _process(PluginHandle handle, float** inBuffer, float** outBuffer, const uint32_t frames, uint32_t midiEventCount, MidiEvent* midiEvents) + { + return ((PluginDescriptorClass*)handle)->process(inBuffer, outBuffer, frames, midiEventCount, midiEvents); + } + + static void _init(PluginDescriptor* const _this_) + { + ((PluginDescriptorClass*)_this_->_handle)->handleInit(); + } + + static void _fini(PluginDescriptor* const _this_) + { + ((PluginDescriptorClass*)_this_->_handle)->handleFini(); + } + + void handleInit() + { + desc.portCount = getPortCount(); + + if (desc.portCount > 0) + { + desc.ports = new PluginPort [desc.portCount]; + + for (uint32_t i=0; i < desc.portCount; i++) + { + PluginPort* const port = &desc.ports[i]; + + port->type = getPortType(i); + port->hints = getPortHints(i); + port->name = getPortName(i); + } + } + + desc.midiProgramCount = getMidiProgramCount(); + + if (desc.midiProgramCount > 0) + { + desc.midiPrograms = new MidiProgram [desc.midiProgramCount]; + + for (uint32_t i=0; i < desc.midiProgramCount; i++) + getMidiProgram(i, &desc.midiPrograms[i]); + } + } + + void handleFini() + { + if (desc.midiProgramCount > 0 && desc.midiPrograms) + delete[] desc.midiPrograms; + + desc.midiProgramCount = 0; + desc.midiPrograms = nullptr; + + if (desc.portCount > 0 && desc.ports) + delete[] desc.ports; + + desc.portCount = 0; + desc.ports = nullptr; + } +}; + +// ----------------------------------------------------------------------- + +#define CARLA_REGISTER_NATIVE_PLUGIN_MM(label, descMM) \ + void carla_register_native_plugin_##label () __attribute__((constructor)); \ + void carla_register_native_plugin_##label () { carla_register_native_plugin(descMM.descriptorInit()); } + +#endif // CARLA_NATIVE_MM_H diff --git a/c++/carla-backend/plugins/midi-split.cpp b/c++/carla-backend/plugins/midi-split.cpp new file mode 100644 index 0000000..eed91ae --- /dev/null +++ b/c++/carla-backend/plugins/midi-split.cpp @@ -0,0 +1,189 @@ +/* + * Carla Native Plugins + * Copyright (C) 2012 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 COPYING file + */ + +#include "carla_nativemm.h" + +#include + +class MidiSplitPlugin : public PluginDescriptorClass +{ +public: + MidiSplitPlugin() : PluginDescriptorClass() + { + } + + MidiSplitPlugin(PluginDescriptorClass* that) : PluginDescriptorClass(that) + { + } + + ~MidiSplitPlugin() + { + } + + // ------------------------------------------------------------------- + +protected: + PluginDescriptorClass* createMe() + { + return new MidiSplitPlugin(this); + } + + void deleteMe() + { + delete this; + } + + // ------------------------------------------------------------------- + + PluginCategory getCategory() + { + return PLUGIN_CATEGORY_UTILITY; + } + + uint32_t getHints() + { + return 0; + } + + const char* getName() + { + return "MIDI Split"; + } + + const char* getLabel() + { + return "midiSplit"; + } + + const char* getMaker() + { + return "falkTX"; + } + + const char* getCopyright() + { + return "GNU GPL v2+"; + } + + // ------------------------------------------------------------------- + + uint32_t getPortCount() + { + return PORT_MAX; + } + + PortType getPortType(uint32_t) + { + return PORT_TYPE_MIDI; + } + + uint32_t getPortHints(uint32_t index) + { + return (index == 0) ? 0 : PORT_HINT_IS_OUTPUT; + } + + const char* getPortName(const uint32_t index) + { + switch (index) + { + case PORT_INPUT: + return "input"; + case PORT_OUTPUT_1: + return "output-01"; + case PORT_OUTPUT_2: + return "output-02"; + case PORT_OUTPUT_3: + return "output-03"; + case PORT_OUTPUT_4: + return "output-04"; + case PORT_OUTPUT_5: + return "output-05"; + case PORT_OUTPUT_6: + return "output-06"; + case PORT_OUTPUT_7: + return "output-07"; + case PORT_OUTPUT_8: + return "output-08"; + case PORT_OUTPUT_9: + return "output-09"; + case PORT_OUTPUT_10: + return "output-10"; + case PORT_OUTPUT_11: + return "output-11"; + case PORT_OUTPUT_12: + return "output-12"; + case PORT_OUTPUT_13: + return "output-13"; + case PORT_OUTPUT_14: + return "output-14"; + case PORT_OUTPUT_15: + return "output-15"; + case PORT_OUTPUT_16: + return "output-16"; + default: + return ""; + } + } + + // ------------------------------------------------------------------- + + void activate() + { + memset(events, 0, sizeof(MidiEvent) * MAX_MIDI_EVENTS); + } + + // ------------------------------------------------------------------- + + void process(float** inBuffer, float** outBuffer, const uint32_t frames, uint32_t midiEventCount, MidiEvent* midiEvents) + { + Q_UNUSED(inBuffer); + Q_UNUSED(outBuffer); + Q_UNUSED(frames); + } + + // ------------------------------------------------------------------- + +private: + enum Ports { + PORT_INPUT = 0, + PORT_OUTPUT_1, + PORT_OUTPUT_2, + PORT_OUTPUT_3, + PORT_OUTPUT_4, + PORT_OUTPUT_5, + PORT_OUTPUT_6, + PORT_OUTPUT_7, + PORT_OUTPUT_8, + PORT_OUTPUT_9, + PORT_OUTPUT_10, + PORT_OUTPUT_11, + PORT_OUTPUT_12, + PORT_OUTPUT_13, + PORT_OUTPUT_14, + PORT_OUTPUT_15, + PORT_OUTPUT_16, + PORT_MAX + }; + + static const unsigned short MAX_MIDI_EVENTS = 512; + + MidiEvent events[MAX_MIDI_EVENTS]; +}; + +static MidiSplitPlugin midiSplitPlugin; + +CARLA_REGISTER_NATIVE_PLUGIN_MM(midiSplit, midiSplitPlugin)