| @@ -0,0 +1,501 @@ | |||||
| /* | |||||
| * Carla Backend | |||||
| * Copyright (C) 2012 Filipe Coelho <falktx@falktx.com> | |||||
| * | |||||
| * This program is free software; you can redistribute it and/or modify | |||||
| * it under the terms of the GNU General Public License as 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_engine.h" | |||||
| #include "carla_plugin.h" | |||||
| #include "DistrhoPlugin.h" | |||||
| CARLA_BACKEND_START_NAMESPACE | |||||
| // ----------------------------------------- | |||||
| // Parameters | |||||
| static const unsigned char paramMap[] = { | |||||
| 0x01, 0x02, 0x03, 0x04, 0x05, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, | |||||
| 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, | |||||
| 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, | |||||
| 0x50, 0x51, 0x52, 0x53, 0x54, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F | |||||
| }; | |||||
| static const unsigned int paramVolume = 5; | |||||
| static const unsigned int paramBalance = 6; | |||||
| static const unsigned int paramPan = 8; | |||||
| static const unsigned int paramCount = sizeof(paramMap); | |||||
| static const unsigned int programCount = 128; | |||||
| // ----------------------------------------- | |||||
| class CarlaEnginePlugin : public CarlaEngine, | |||||
| public DISTRHO::Plugin | |||||
| { | |||||
| public: | |||||
| short idZyn; | |||||
| CarlaEnginePlugin() | |||||
| : CarlaEngine(), | |||||
| DISTRHO::Plugin(paramCount, programCount, 0) | |||||
| { | |||||
| qDebug("CarlaEnginePlugin::CarlaEnginePlugin()"); | |||||
| // init parameters | |||||
| for (unsigned int i=0; i < paramCount; i++) | |||||
| paramBuffers[i] = 0.0f; | |||||
| paramBuffers[paramVolume] = 100.0f; | |||||
| paramBuffers[paramBalance] = 63.5f; | |||||
| paramBuffers[paramPan] = 63.5f; | |||||
| memcpy(prevParamBuffers, paramBuffers, sizeof(float)*paramCount); | |||||
| // set-up engine | |||||
| carlaOptions.forceStereo = true; | |||||
| carlaOptions.processMode = PROCESS_MODE_CONTINUOUS_RACK; | |||||
| carlaOptions.preferPluginBridges = false; | |||||
| carlaOptions.preferUiBridges = false; | |||||
| init("Carla"); | |||||
| // Force thread start so we get some OSC usage | |||||
| // (liblo locks otherwise) | |||||
| //startCheckThread(); | |||||
| // testing | |||||
| idZyn = addPlugin(PLUGIN_DSSI, "/usr/lib/dssi/sineshaper.so", nullptr, "ll-sineshaper"); | |||||
| } | |||||
| ~CarlaEnginePlugin() | |||||
| { | |||||
| qDebug("CarlaEnginePlugin::~CarlaEnginePlugin()"); | |||||
| removeAllPlugins(); | |||||
| close(); | |||||
| } | |||||
| // ------------------------------------- | |||||
| // CarlaEngine virtual calls | |||||
| bool init(const char* const clientName) | |||||
| { | |||||
| qDebug("CarlaEnginePlugin::init(\"%s\")", clientName); | |||||
| bufferSize = d_bufferSize(); | |||||
| sampleRate = d_sampleRate(); | |||||
| name = strdup(clientName); | |||||
| CarlaEngine::init(name); | |||||
| return true; | |||||
| } | |||||
| bool close() | |||||
| { | |||||
| qDebug("CarlaEnginePlugin::close()"); | |||||
| CarlaEngine::close(); | |||||
| if (name) | |||||
| { | |||||
| free((void*)name); | |||||
| name = nullptr; | |||||
| } | |||||
| return true; | |||||
| } | |||||
| bool isOffline() | |||||
| { | |||||
| return false; | |||||
| } | |||||
| bool isRunning() | |||||
| { | |||||
| return true; | |||||
| } | |||||
| CarlaEngineClient* addClient(CarlaPlugin* const plugin) | |||||
| { | |||||
| CarlaEngineClientNativeHandle handle; | |||||
| handle.type = CarlaEngineTypeRtAudio; | |||||
| return new CarlaEngineClient(handle); | |||||
| Q_UNUSED(plugin); | |||||
| } | |||||
| protected: | |||||
| // --------------------------------------------- | |||||
| // DISTRHO Plugin Information | |||||
| const char* d_label() | |||||
| { | |||||
| return "Carla"; | |||||
| } | |||||
| const char* d_maker() | |||||
| { | |||||
| return "falkTX"; | |||||
| } | |||||
| const char* d_license() | |||||
| { | |||||
| return "GPL v2+"; | |||||
| } | |||||
| uint32_t d_version() | |||||
| { | |||||
| return 0x0500; | |||||
| } | |||||
| long d_uniqueId() | |||||
| { | |||||
| return d_cconst('C', 'r', 'l', 'a'); | |||||
| } | |||||
| // --------------------------------------------- | |||||
| // DISTRHO Plugin Init | |||||
| void d_initParameter(uint32_t index, DISTRHO::Parameter& parameter) | |||||
| { | |||||
| if (index >= paramCount) | |||||
| return; | |||||
| parameter.hints = DISTRHO::PARAMETER_IS_AUTOMABLE; | |||||
| parameter.ranges.def = 0.0f; | |||||
| parameter.ranges.min = 0.0f; | |||||
| parameter.ranges.max = 127.0f; | |||||
| if (index == paramVolume) | |||||
| parameter.ranges.def = 100.0f; | |||||
| else if (index == paramBalance) | |||||
| parameter.ranges.def = 63.5f; | |||||
| else if (index == paramPan) | |||||
| parameter.ranges.def = 63.5f; | |||||
| switch (paramMap[index]) | |||||
| { | |||||
| case 0x01: | |||||
| parameter.name = "0x01 Modulation"; | |||||
| break; | |||||
| case 0x02: | |||||
| parameter.name = "0x02 Breath"; | |||||
| break; | |||||
| case 0x03: | |||||
| parameter.name = "0x03 (Undefined)"; | |||||
| break; | |||||
| case 0x04: | |||||
| parameter.name = "0x04 Foot"; | |||||
| break; | |||||
| case 0x05: | |||||
| parameter.name = "0x05 Portamento"; | |||||
| break; | |||||
| case 0x07: | |||||
| parameter.name = "0x07 Volume"; | |||||
| break; | |||||
| case 0x08: | |||||
| parameter.name = "0x08 Balance"; | |||||
| break; | |||||
| case 0x09: | |||||
| parameter.name = "0x09 (Undefined)"; | |||||
| break; | |||||
| case 0x0A: | |||||
| parameter.name = "0x0A Pan"; | |||||
| break; | |||||
| case 0x0B: | |||||
| parameter.name = "0x0B Expression"; | |||||
| break; | |||||
| case 0x0C: | |||||
| parameter.name = "0x0C FX Control 1"; | |||||
| break; | |||||
| case 0x0D: | |||||
| parameter.name = "0x0D FX Control 2"; | |||||
| break; | |||||
| case 0x0E: | |||||
| parameter.name = "0x0E (Undefined)"; | |||||
| break; | |||||
| case 0x0F: | |||||
| parameter.name = "0x0F (Undefined)"; | |||||
| break; | |||||
| case 0x10: | |||||
| parameter.name = "0x10 General Purpose 1"; | |||||
| break; | |||||
| case 0x11: | |||||
| parameter.name = "0x11 General Purpose 2"; | |||||
| break; | |||||
| case 0x12: | |||||
| parameter.name = "0x12 General Purpose 3"; | |||||
| break; | |||||
| case 0x13: | |||||
| parameter.name = "0x13 General Purpose 4"; | |||||
| break; | |||||
| case 0x14: | |||||
| parameter.name = "0x14 (Undefined)"; | |||||
| break; | |||||
| case 0x15: | |||||
| parameter.name = "0x15 (Undefined)"; | |||||
| break; | |||||
| case 0x16: | |||||
| parameter.name = "0x16 (Undefined)"; | |||||
| break; | |||||
| case 0x17: | |||||
| parameter.name = "0x17 (Undefined)"; | |||||
| break; | |||||
| case 0x18: | |||||
| parameter.name = "0x18 (Undefined)"; | |||||
| break; | |||||
| case 0x19: | |||||
| parameter.name = "0x19 (Undefined)"; | |||||
| break; | |||||
| case 0x1A: | |||||
| parameter.name = "0x1A (Undefined)"; | |||||
| break; | |||||
| case 0x1B: | |||||
| parameter.name = "0x1B (Undefined)"; | |||||
| break; | |||||
| case 0x1C: | |||||
| parameter.name = "0x1C (Undefined)"; | |||||
| break; | |||||
| case 0x1D: | |||||
| parameter.name = "0x1D (Undefined)"; | |||||
| break; | |||||
| case 0x1E: | |||||
| parameter.name = "0x1E (Undefined)"; | |||||
| break; | |||||
| case 0x1F: | |||||
| parameter.name = "0x1F (Undefined)"; | |||||
| break; | |||||
| case 0x46: | |||||
| parameter.name = "0x46 Control 1 [Variation]"; | |||||
| break; | |||||
| case 0x47: | |||||
| parameter.name = "0x47 Control 2 [Timbre]"; | |||||
| break; | |||||
| case 0x48: | |||||
| parameter.name = "0x48 Control 3 [Release]"; | |||||
| break; | |||||
| case 0x49: | |||||
| parameter.name = "0x49 Control 4 [Attack]"; | |||||
| break; | |||||
| case 0x4A: | |||||
| parameter.name = "0x4A Control 5 [Brightness]"; | |||||
| break; | |||||
| case 0x4B: | |||||
| parameter.name = "0x4B Control 6 [Decay]"; | |||||
| break; | |||||
| case 0x4C: | |||||
| parameter.name = "0x4C Control 7 [Vib Rate]"; | |||||
| break; | |||||
| case 0x4D: | |||||
| parameter.name = "0x4D Control 8 [Vib Depth]"; | |||||
| break; | |||||
| case 0x4E: | |||||
| parameter.name = "0x4E Control 9 [Vib Delay]"; | |||||
| break; | |||||
| case 0x4F: | |||||
| parameter.name = "0x4F Control 10 [Undefined]"; | |||||
| break; | |||||
| case 0x50: | |||||
| parameter.name = "0x50 General Purpose 5"; | |||||
| break; | |||||
| case 0x51: | |||||
| parameter.name = "0x51 General Purpose 6"; | |||||
| break; | |||||
| case 0x52: | |||||
| parameter.name = "0x52 General Purpose 7"; | |||||
| break; | |||||
| case 0x53: | |||||
| parameter.name = "0x53 General Purpose 8"; | |||||
| break; | |||||
| case 0x54: | |||||
| parameter.name = "0x54 Portamento Control"; | |||||
| break; | |||||
| case 0x5B: | |||||
| parameter.name = "0x5B FX 1 Depth [Reverb]"; | |||||
| break; | |||||
| case 0x5C: | |||||
| parameter.name = "0x5C FX 2 Depth [Tremolo]"; | |||||
| break; | |||||
| case 0x5D: | |||||
| parameter.name = "0x5D FX 3 Depth [Chorus]"; | |||||
| break; | |||||
| case 0x5E: | |||||
| parameter.name = "0x5E FX 4 Depth [Detune]"; | |||||
| break; | |||||
| case 0x5F: | |||||
| parameter.name = "0x5F FX 5 Depth [Phaser]"; | |||||
| break; | |||||
| } | |||||
| } | |||||
| void d_initProgramName(uint32_t index, d_string& programName) | |||||
| { | |||||
| programName = "Program #" + d_string(index); | |||||
| } | |||||
| void d_initStateKey(uint32_t index, d_string& stateKey) | |||||
| { | |||||
| Q_UNUSED(index); | |||||
| Q_UNUSED(stateKey); | |||||
| } | |||||
| // --------------------------------------------- | |||||
| // DISTRHO Plugin Internal data | |||||
| float d_parameterValue(uint32_t index) | |||||
| { | |||||
| if (index >= paramCount) | |||||
| return 0.0f; | |||||
| return paramBuffers[index]; | |||||
| } | |||||
| void d_setParameterValue(uint32_t index, float value) | |||||
| { | |||||
| if (index >= paramCount) | |||||
| return; | |||||
| paramBuffers[index] = value; | |||||
| } | |||||
| void d_setProgram(uint32_t index) | |||||
| { | |||||
| if (index >= programCount) | |||||
| return; | |||||
| if (maxPluginNumber() == 0) | |||||
| return; | |||||
| if (CarlaPlugin* const plugin = getPlugin(0)) | |||||
| { | |||||
| if (index > plugin->programCount()) | |||||
| plugin->setProgram(index, true, true, false, true); | |||||
| } | |||||
| } | |||||
| void d_setState(const char* key, const char* value) | |||||
| { | |||||
| Q_UNUSED(key); | |||||
| Q_UNUSED(value); | |||||
| } | |||||
| // --------------------------------------------- | |||||
| // DISTRHO Plugin Process | |||||
| void d_activate() | |||||
| { | |||||
| //#if 0 | |||||
| for (unsigned short i=0, max=maxPluginNumber(); i < max; i++) | |||||
| { | |||||
| CarlaPlugin* const plugin = getPluginUnchecked(i); | |||||
| if (plugin && plugin->enabled()) | |||||
| plugin->setActive(true, true, false); | |||||
| } | |||||
| //#endif | |||||
| memcpy(prevParamBuffers, paramBuffers, sizeof(float)*paramCount); | |||||
| } | |||||
| void d_deactivate() | |||||
| { | |||||
| //#if 0 | |||||
| for (unsigned short i=0, max=maxPluginNumber(); i < max; i++) | |||||
| { | |||||
| CarlaPlugin* const plugin = getPluginUnchecked(i); | |||||
| if (plugin && plugin->enabled()) | |||||
| plugin->setActive(false, true, false); | |||||
| } | |||||
| //#endif | |||||
| } | |||||
| void d_run(const float** inputs, float** outputs, uint32_t frames, uint32_t midiEventCount, const DISTRHO::MidiEvent* midiEvents) | |||||
| { | |||||
| if (maxPluginNumber() == 0) | |||||
| return; | |||||
| // create audio buffers | |||||
| float* inBuf[2] = { (float*)inputs[0], (float*)inputs[1] }; | |||||
| float* outBuf[2] = { outputs[0], outputs[1] }; | |||||
| // initialize control input | |||||
| memset(rackControlEventsIn, 0, sizeof(CarlaEngineControlEvent)*MAX_ENGINE_CONTROL_EVENTS); | |||||
| { | |||||
| uint32_t carlaEventIndex = 0; | |||||
| for (unsigned int i=0; i < paramCount; i++) | |||||
| { | |||||
| if (prevParamBuffers[i] == paramBuffers[i]) | |||||
| continue; | |||||
| CarlaEngineControlEvent* const carlaEvent = &rackControlEventsIn[carlaEventIndex++]; | |||||
| carlaEvent->type = CarlaEngineEventControlChange; | |||||
| carlaEvent->controller = paramMap[i]; | |||||
| carlaEvent->value = paramBuffers[i]/127; | |||||
| } | |||||
| } | |||||
| memcpy(prevParamBuffers, paramBuffers, sizeof(float)*paramCount); | |||||
| // initialize midi input | |||||
| memset(rackMidiEventsIn, 0, sizeof(CarlaEngineMidiEvent)*MAX_ENGINE_MIDI_EVENTS); | |||||
| { | |||||
| const DISTRHO::MidiEvent* event; | |||||
| for (uint32_t i=0, j=0; j < midiEventCount; j++) | |||||
| { | |||||
| if (i == MAX_ENGINE_MIDI_EVENTS) | |||||
| break; | |||||
| event = &midiEvents[j]; | |||||
| rackMidiEventsIn[i].time = event->frame; | |||||
| rackMidiEventsIn[i].size = 3; | |||||
| memcpy(rackMidiEventsIn[i].data, event->buffer, 3); | |||||
| i += 1; | |||||
| } | |||||
| } | |||||
| processRack(inBuf, outBuf, frames); | |||||
| } | |||||
| // --------------------------------------------- | |||||
| // Callbacks | |||||
| void d_bufferSizeChanged(uint32_t newBufferSize) | |||||
| { | |||||
| bufferSizeChanged(newBufferSize); | |||||
| } | |||||
| // --------------------------------------------- | |||||
| private: | |||||
| float paramBuffers[paramCount]; | |||||
| float prevParamBuffers[paramCount]; | |||||
| }; | |||||
| CARLA_BACKEND_END_NAMESPACE | |||||
| // ------------------------------------------------- | |||||
| START_NAMESPACE_DISTRHO | |||||
| Plugin* createPlugin() | |||||
| { | |||||
| return new CarlaBackend::CarlaEnginePlugin(); | |||||
| } | |||||
| END_NAMESPACE_DISTRHO | |||||
| #include "DistrhoPluginMain.cpp" | |||||