| 
							- /*
 -  * XY Controller UI, taken from Cadence
 -  * Copyright (C) 2011-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 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 doc/GPL.txt file.
 -  */
 - 
 - #include "CarlaDefines.h"
 - 
 - #include "CarlaMIDI.h"
 - #include "CarlaNativeExtUI.hpp"
 - 
 - #include "midi-queue.hpp"
 - #include "water/text/StringArray.h"
 - 
 - // -----------------------------------------------------------------------
 - 
 - class XYControllerPlugin : public NativePluginAndUiClass
 - {
 - public:
 -     enum Parameters {
 -         kParamInX,
 -         kParamInY,
 -         kParamOutX,
 -         kParamOutY,
 -         kParamCount,
 -     };
 - 
 -     XYControllerPlugin(const NativeHostDescriptor* const host)
 -         : NativePluginAndUiClass(host, "xycontroller-ui"),
 -           params(),
 -           channels(),
 -           mqueue(),
 -           mqueueRT()
 -     {
 -         carla_zeroStruct(params);
 -         carla_zeroStruct(channels);
 -         channels[0] = true;
 -     }
 - 
 - protected:
 -     // -------------------------------------------------------------------
 -     // Plugin parameter calls
 - 
 -     uint32_t getParameterCount() const override
 -     {
 -         return kParamCount;
 -     }
 - 
 -     const NativeParameter* getParameterInfo(const uint32_t index) const override
 -     {
 -         CARLA_SAFE_ASSERT_RETURN(index < kParamCount, nullptr);
 - 
 -         static NativeParameter param;
 - 
 -         int hints = NATIVE_PARAMETER_IS_ENABLED|NATIVE_PARAMETER_IS_AUTOMATABLE;
 - 
 -         param.name = nullptr;
 -         param.unit = "%";
 -         param.ranges.def       = 0.0f;
 -         param.ranges.min       = -100.0f;
 -         param.ranges.max       = 100.0f;
 -         param.ranges.step      = 1.0f;
 -         param.ranges.stepSmall = 0.01f;
 -         param.ranges.stepLarge = 10.0f;
 -         param.scalePointCount  = 0;
 -         param.scalePoints      = nullptr;
 - 
 -         switch (index)
 -         {
 -         case kParamInX:
 -             param.name = "X";
 -             break;
 -         case kParamInY:
 -             param.name = "Y";
 -             break;
 -         case kParamOutX:
 -             hints |= NATIVE_PARAMETER_IS_OUTPUT;
 -             param.name = "Out X";
 -             break;
 -         case kParamOutY:
 -             hints |= NATIVE_PARAMETER_IS_OUTPUT;
 -             param.name = "Out Y";
 -             break;
 -         }
 - 
 -         param.hints = static_cast<NativeParameterHints>(hints);
 - 
 -         return ¶m;
 -     }
 - 
 -     float getParameterValue(const uint32_t index) const override
 -     {
 -         CARLA_SAFE_ASSERT_RETURN(index < kParamCount, 0.0f);
 - 
 -         return params[index];
 -     }
 - 
 -     // -------------------------------------------------------------------
 -     // Plugin state calls
 - 
 -     void setParameterValue(const uint32_t index, const float value) override
 -     {
 -         switch (index)
 -         {
 -         case kParamInX:
 -         case kParamInY:
 -             params[index] = value;
 -             break;
 -         }
 -     }
 - 
 -     void setCustomData(const char* const key, const char* const value) override
 -     {
 -         CARLA_SAFE_ASSERT_RETURN(key != nullptr && key[0] != '\0',);
 -         CARLA_SAFE_ASSERT_RETURN(value != nullptr,);
 - 
 -         if (std::strcmp(key, "channels") == 0)
 -         {
 -             const water::StringArray chans(water::StringArray::fromTokens(value, ",", ""));
 - 
 -             carla_zeroStruct(channels);
 - 
 -             for (const water::String *it=chans.begin(), *end=chans.end(); it != end; ++it)
 -             {
 -                 const int ichan = std::atoi((*it).toRawUTF8());
 -                 CARLA_SAFE_ASSERT_INT_CONTINUE(ichan >= 1 && ichan <= 16, ichan);
 - 
 -                 channels[ichan-1] = true;
 -             }
 -         }
 -     }
 - 
 -     // -------------------------------------------------------------------
 -     // Plugin process calls
 - 
 -     void process(const float* const*, float**, const uint32_t,
 -                  const NativeMidiEvent* const midiEvents, const uint32_t midiEventCount) override
 -     {
 -         params[kParamOutX] = params[kParamInX];
 -         params[kParamOutY] = params[kParamInY];
 - 
 -         if (mqueue.isNotEmpty() && mqueueRT.tryToCopyDataFrom(mqueue))
 -         {
 -             uint8_t d1, d2, d3;
 -             NativeMidiEvent ev = { 0, 0, 3, { 0, 0, 0, 0 } };
 - 
 -             while (mqueueRT.get(d1, d2, d3))
 -             {
 -                 ev.data[0] = d1;
 -                 ev.data[1] = d2;
 -                 ev.data[2] = d3;
 -                 writeMidiEvent(&ev);
 -             }
 -         }
 - 
 -         for (uint32_t i=0; i < midiEventCount; ++i)
 -             writeMidiEvent(&midiEvents[i]);
 -     }
 - 
 -     // -------------------------------------------------------------------
 -     // Pipe Server calls
 - 
 -     bool msgReceived(const char* const msg) noexcept override
 -     {
 -         if (NativePluginAndUiClass::msgReceived(msg))
 -             return true;
 - 
 -         if (std::strcmp(msg, "cc") == 0)
 -         {
 -             uint8_t cc, value;
 -             CARLA_SAFE_ASSERT_RETURN(readNextLineAsByte(cc), true);
 -             CARLA_SAFE_ASSERT_RETURN(readNextLineAsByte(value), true);
 - 
 -             const CarlaMutexLocker cml(mqueue.getMutex());
 - 
 -             for (int i=0; i<16; ++i)
 -             {
 -                 if (channels[i])
 -                     if (! mqueue.put(uint8_t(MIDI_STATUS_CONTROL_CHANGE | (i & MIDI_CHANNEL_BIT)), cc, value))
 -                         break;
 -             }
 - 
 -             return true;
 -         }
 - 
 -         if (std::strcmp(msg, "cc2") == 0)
 -         {
 -             uint8_t cc1, value1, cc2, value2;
 -             CARLA_SAFE_ASSERT_RETURN(readNextLineAsByte(cc1), true);
 -             CARLA_SAFE_ASSERT_RETURN(readNextLineAsByte(value1), true);
 -             CARLA_SAFE_ASSERT_RETURN(readNextLineAsByte(cc2), true);
 -             CARLA_SAFE_ASSERT_RETURN(readNextLineAsByte(value2), true);
 - 
 -             const CarlaMutexLocker cml(mqueue.getMutex());
 - 
 -             for (int i=0; i<16; ++i)
 -             {
 -                 if (channels[i])
 -                 {
 -                     if (! mqueue.put(uint8_t(MIDI_STATUS_CONTROL_CHANGE | (i & MIDI_CHANNEL_BIT)), cc1, value1))
 -                         break;
 -                     if (! mqueue.put(uint8_t(MIDI_STATUS_CONTROL_CHANGE | (i & MIDI_CHANNEL_BIT)), cc2, value2))
 -                         break;
 -                 }
 -             }
 - 
 -             return true;
 -         }
 - 
 -         if (std::strcmp(msg, "note") == 0)
 -         {
 -             bool onOff;
 -             uint8_t note;
 -             CARLA_SAFE_ASSERT_RETURN(readNextLineAsBool(onOff), true);
 -             CARLA_SAFE_ASSERT_RETURN(readNextLineAsByte(note), true);
 - 
 -             const uint8_t status   = onOff ? MIDI_STATUS_NOTE_ON : MIDI_STATUS_NOTE_OFF;
 -             const uint8_t velocity = onOff ? 100 : 0;
 - 
 -             const CarlaMutexLocker cml(mqueue.getMutex());
 - 
 -             for (int i=0; i<16; ++i)
 -             {
 -                 if (channels[i])
 -                     if (! mqueue.put(uint8_t(status | (i & MIDI_CHANNEL_BIT)), note, velocity))
 -                         break;
 -             }
 - 
 -             return true;
 -         }
 - 
 -         return false;
 -     }
 - 
 - private:
 -     float params[kParamCount];
 -     bool channels[16];
 - 
 -     MIDIEventQueue<128> mqueue, mqueueRT;
 - 
 -     PluginClassEND(XYControllerPlugin)
 -     CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(XYControllerPlugin)
 - };
 - 
 - // -----------------------------------------------------------------------
 - 
 - static const NativePluginDescriptor notesDesc = {
 -     /* category  */ NATIVE_PLUGIN_CATEGORY_UTILITY,
 -     /* hints     */ static_cast<NativePluginHints>(NATIVE_PLUGIN_IS_RTSAFE
 -                                                   |NATIVE_PLUGIN_HAS_UI),
 -     /* supports  */ NATIVE_PLUGIN_SUPPORTS_NOTHING,
 -     /* audioIns  */ 0,
 -     /* audioOuts */ 0,
 -     /* midiIns   */ 1,
 -     /* midiOuts  */ 1,
 -     /* paramIns  */ 2,
 -     /* paramOuts */ 2,
 -     /* name      */ "XY Controller",
 -     /* label     */ "xycontroller",
 -     /* maker     */ "falkTX",
 -     /* copyright */ "GNU GPL v2+",
 -     PluginDescriptorFILL(XYControllerPlugin)
 - };
 - 
 - // -----------------------------------------------------------------------
 - 
 - CARLA_API_EXPORT
 - void carla_register_native_plugin_xycontroller();
 - 
 - CARLA_API_EXPORT
 - void carla_register_native_plugin_xycontroller()
 - {
 -     carla_register_native_plugin(¬esDesc);
 - }
 - 
 - // -----------------------------------------------------------------------
 
 
  |