| 
							- /*
 -  * DISTRHO Cardinal Plugin
 -  * Copyright (C) 2021-2022 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 3 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 LICENSE file.
 -  */
 - 
 - #include "lv2plugin.hpp"
 - 
 - #include "src/lv2/buf-size.h"
 - #include "src/lv2/options.h"
 - 
 - #include "DistrhoUtils.hpp"
 - 
 - #include <time.h>
 - #include <sys/time.h>
 - 
 - namespace rack {
 - 
 - static thread_local Context* threadContext = nullptr;
 - 
 - Context* contextGet() {
 -     DISTRHO_SAFE_ASSERT(threadContext != nullptr);
 -     return threadContext;
 - }
 - 
 - #ifdef ARCH_MAC
 - __attribute__((optnone))
 - #endif
 - void contextSet(Context* context) {
 -     threadContext = context;
 - }
 - 
 - namespace random {
 - 
 - Xoroshiro128Plus& local() {
 -     static Xoroshiro128Plus rng;
 -     return rng;
 - }
 - 
 - } // namespace random
 - 
 - }
 - 
 - struct PluginLv2 {
 -     Context context;
 -     engine::Module* module;
 -     int frameCount = 0;
 -     int numInputs, numOutputs, numParams, numLights;
 -     void** ports;
 - 
 -     PluginLv2(double sr)
 -     {
 -         rack::random::Xoroshiro128Plus& rng(rack::random::local());
 - 
 -         if (! rng.isSeeded())
 -         {
 -             struct timeval tv;
 -             gettimeofday(&tv, NULL);
 -             uint64_t usec = uint64_t(tv.tv_sec) * 1000 * 1000 + tv.tv_usec;
 - 
 -             static uint64_t globalCounter = 1;
 -             rng.seed(usec, globalCounter++);
 - 
 -             for (int i = 0; i < 4; i++)
 -                 rng();
 -         }
 - 
 -         context._engine.sampleRate = sr;
 -         contextSet(&context);
 -         module = PLUGIN_MODEL->createModule();
 - 
 -         numInputs = module->getNumInputs();
 -         numOutputs = module->getNumOutputs();
 -         numParams = module->getNumParams();
 -         numLights = module->getNumLights();
 -         ports = new void*[numInputs+numOutputs+numParams+numLights];
 - 
 -         Module::SampleRateChangeEvent e = { context._engine.sampleRate, 1.0f / context._engine.sampleRate };
 -         module->onSampleRateChange(e);
 - 
 -         // FIXME for CV ports we need to detect if something is connected
 -         for (int i=numInputs; --i >=0;)
 -         {
 -             // if (!kCvInputs[i])
 -             module->inputs[i].channels = 1;
 -         }
 -         for (int i=numOutputs; --i >=0;)
 -         {
 -             // if (!kCvOutputs[i])
 -             module->outputs[i].channels = 1;
 -         }
 - 
 -         d_stdout("Loaded " SLUG " :: %i inputs, %i outputs, %i params and %i lights",
 -                  numInputs, numOutputs, numParams, numLights);
 -     }
 - 
 -     PluginLv2()
 -     {
 -         contextSet(&context);
 -         delete[] ports;
 -         delete module;
 -     }
 - 
 -     void lv2_connect_port(const uint32_t port, void* const dataLocation)
 -     {
 -         ports[port] = dataLocation;
 -     }
 - 
 -     void lv2_run(const uint32_t sampleCount)
 -     {
 -         if (sampleCount == 0)
 -             return;
 - 
 -         contextSet(&context);
 - 
 -         Module::ProcessArgs args = { context._engine.sampleRate, 1.0f / context._engine.sampleRate, frameCount };
 - 
 -         for (int i=numParams; --i >=0;)
 -             module->params[i].setValue(*static_cast<const float*>(ports[numInputs+numOutputs+i]));
 - 
 -         for (uint32_t s=0; s<sampleCount; ++s)
 -         {
 -             for (int i=numInputs; --i >=0;)
 -             {
 -                 if (kCvInputs[i])
 -                     module->inputs[i].setVoltage(static_cast<const float*>(ports[i])[s]);
 -                 else
 -                     module->inputs[i].setVoltage(static_cast<const float*>(ports[i])[s] * 10.0f);
 -             }
 - 
 -             module->doProcess(args);
 - 
 -             for (int i=numOutputs; --i >=0;)
 -             {
 -                 if (kCvOutputs[i])
 -                     static_cast<float*>(ports[numInputs+i])[s] = module->outputs[i].getVoltage();
 -                 else
 -                     static_cast<float*>(ports[numInputs+i])[s] = module->outputs[i].getVoltage() * 0.1f;
 -             }
 - 
 -             ++args.frame;
 -         }
 - 
 -         for (int i=numLights; --i >=0;)
 -             *static_cast<float*>(ports[numInputs+numOutputs+numParams+i]) = module->lights[i].getBrightness();
 - 
 -         frameCount += sampleCount;
 -     }
 - };
 - 
 - static LV2_Handle lv2_instantiate(const LV2_Descriptor*, double sampleRate, const char* bundlePath, const LV2_Feature* const* features)
 - {
 -     return new PluginLv2(sampleRate);
 - }
 - 
 - // -----------------------------------------------------------------------
 - 
 - static void lv2_connect_port(LV2_Handle instance, uint32_t port, void* dataLocation)
 - {
 -     static_cast<PluginLv2*>(instance)->lv2_connect_port(port, dataLocation);
 - }
 - 
 - static void lv2_run(LV2_Handle instance, uint32_t sampleCount)
 - {
 -     static_cast<PluginLv2*>(instance)->lv2_run(sampleCount);
 - }
 - 
 - static void lv2_cleanup(LV2_Handle instance)
 - {
 -     delete static_cast<PluginLv2*>(instance);
 - }
 - 
 - // -----------------------------------------------------------------------
 - 
 - static const void* lv2_extension_data(const char* uri)
 - {
 -     return nullptr;
 - }
 - 
 - // -----------------------------------------------------------------------
 - 
 - static const LV2_Descriptor sLv2Descriptor = {
 -     "urn:cardinal:" SLUG,
 -     lv2_instantiate,
 -     lv2_connect_port,
 -     NULL, // activate
 -     lv2_run,
 -     NULL, // deactivate
 -     lv2_cleanup,
 -     lv2_extension_data
 - };
 - 
 - DISTRHO_PLUGIN_EXPORT
 - const LV2_Descriptor* lv2_descriptor(uint32_t index)
 - {
 -     USE_NAMESPACE_DISTRHO
 -     return (index == 0) ? &sLv2Descriptor : nullptr;
 - }
 - 
 - // -----------------------------------------------------------------------
 
 
  |