Very crude and dirty first host midi implementation
Signed-off-by: falkTX <falktx@falktx.com>
This commit is contained in:
parent
810928190c
commit
b863d0e54c
6 changed files with 758 additions and 450 deletions
|
|
@ -42,7 +42,7 @@
|
|||
#include <list>
|
||||
|
||||
#include "DistrhoPluginUtils.hpp"
|
||||
#include "PluginDriver.hpp"
|
||||
#include "PluginContext.hpp"
|
||||
#include "extra/Base64.hpp"
|
||||
#include "extra/SharedResourcePointer.hpp"
|
||||
|
||||
|
|
@ -182,9 +182,6 @@ struct Initializer
|
|||
"Make sure Cardinal was downloaded and installed correctly.", asset::systemDir.c_str());
|
||||
}
|
||||
|
||||
INFO("Initializing midi driver");
|
||||
midi::addDriver(0, new CardinalMidiDriver);
|
||||
|
||||
INFO("Initializing plugins");
|
||||
plugin::initStaticPlugins();
|
||||
|
||||
|
|
@ -315,6 +312,66 @@ struct Initializer
|
|||
|
||||
// -----------------------------------------------------------------------------------------------------------
|
||||
|
||||
void CardinalPluginContext::writeMidiMessage(const rack::midi::Message& message)
|
||||
{
|
||||
const size_t size = message.bytes.size();
|
||||
DISTRHO_SAFE_ASSERT_RETURN(size > 0,);
|
||||
DISTRHO_SAFE_ASSERT_RETURN(message.frame >= 0,);
|
||||
|
||||
MidiEvent event;
|
||||
event.frame = message.frame;
|
||||
|
||||
switch (message.bytes[0] & 0xF0)
|
||||
{
|
||||
case 0x80:
|
||||
case 0x90:
|
||||
case 0xA0:
|
||||
case 0xB0:
|
||||
case 0xE0:
|
||||
event.size = 3;
|
||||
break;
|
||||
case 0xC0:
|
||||
case 0xD0:
|
||||
event.size = 2;
|
||||
break;
|
||||
case 0xF0:
|
||||
switch (message.bytes[0] & 0x0F)
|
||||
{
|
||||
case 0x0:
|
||||
case 0x4:
|
||||
case 0x5:
|
||||
case 0x7:
|
||||
case 0x9:
|
||||
case 0xD:
|
||||
// unsupported
|
||||
return;
|
||||
case 0x1:
|
||||
case 0x2:
|
||||
case 0x3:
|
||||
case 0xE:
|
||||
event.size = 3;
|
||||
break;
|
||||
case 0x6:
|
||||
case 0x8:
|
||||
case 0xA:
|
||||
case 0xB:
|
||||
case 0xC:
|
||||
case 0xF:
|
||||
event.size = 1;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
DISTRHO_SAFE_ASSERT_RETURN(size >= event.size,);
|
||||
|
||||
std::memcpy(event.data, message.bytes.data(), event.size);
|
||||
|
||||
plugin->writeMidiEvent(event);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------------
|
||||
|
||||
struct ScopedContext {
|
||||
ScopedContext(const CardinalBasePlugin* const plugin)
|
||||
{
|
||||
|
|
@ -327,6 +384,7 @@ struct ScopedContext {
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------------
|
||||
|
||||
class CardinalPlugin : public CardinalBasePlugin
|
||||
|
|
@ -335,13 +393,8 @@ class CardinalPlugin : public CardinalBasePlugin
|
|||
|
||||
float** fAudioBufferCopy;
|
||||
std::string fAutosavePath;
|
||||
String fWindowSize;
|
||||
|
||||
// for base/context handling
|
||||
CardinalMidiInputDevice** fCurrentMidiInputs;
|
||||
CardinalMidiOutputDevice** fCurrentMidiOutputs;
|
||||
uint64_t fPreviousFrame;
|
||||
Mutex fDeviceMutex;
|
||||
String fWindowSize;
|
||||
|
||||
#ifndef HEADLESS
|
||||
// real values, not VCV interpreted ones
|
||||
|
|
@ -353,8 +406,6 @@ public:
|
|||
: CardinalBasePlugin(kModuleParameters + kWindowParameterCount, 0, kCardinalStateCount),
|
||||
fInitializer(this),
|
||||
fAudioBufferCopy(nullptr),
|
||||
fCurrentMidiInputs(nullptr),
|
||||
fCurrentMidiOutputs(nullptr),
|
||||
fPreviousFrame(0)
|
||||
{
|
||||
#ifndef HEADLESS
|
||||
|
|
@ -432,14 +483,6 @@ public:
|
|||
delete context;
|
||||
}
|
||||
|
||||
{
|
||||
const MutexLocker cml(fDeviceMutex);
|
||||
delete[] fCurrentMidiInputs;
|
||||
fCurrentMidiInputs = nullptr;
|
||||
delete[] fCurrentMidiOutputs;
|
||||
fCurrentMidiOutputs = nullptr;
|
||||
}
|
||||
|
||||
if (! fAutosavePath.empty())
|
||||
rack::system::removeRecursively(fAutosavePath);
|
||||
}
|
||||
|
|
@ -450,101 +493,6 @@ public:
|
|||
}
|
||||
|
||||
protected:
|
||||
/* --------------------------------------------------------------------------------------------------------
|
||||
* Cardinal Base things */
|
||||
|
||||
void assignMidiInputDevice(CardinalMidiInputDevice* const dev) noexcept override
|
||||
{
|
||||
CardinalMidiInputDevice** const oldDevs = fCurrentMidiInputs;
|
||||
|
||||
uint numDevs = 0;
|
||||
if (oldDevs != nullptr)
|
||||
{
|
||||
while (oldDevs[numDevs] != nullptr)
|
||||
++numDevs;
|
||||
}
|
||||
|
||||
CardinalMidiInputDevice** const newDevs = new CardinalMidiInputDevice*[numDevs + 2];
|
||||
|
||||
for (uint i=0; i<numDevs; ++i)
|
||||
newDevs[i] = oldDevs[i];
|
||||
|
||||
newDevs[numDevs+0] = dev;
|
||||
newDevs[numDevs+1] = nullptr;
|
||||
|
||||
{
|
||||
const MutexLocker cml(fDeviceMutex);
|
||||
fCurrentMidiInputs = newDevs;
|
||||
}
|
||||
|
||||
delete[] oldDevs;
|
||||
}
|
||||
|
||||
void assignMidiOutputDevice(CardinalMidiOutputDevice* const dev) noexcept override
|
||||
{
|
||||
CardinalMidiOutputDevice** const oldDevs = fCurrentMidiOutputs;
|
||||
|
||||
uint numDevs = 0;
|
||||
if (oldDevs != nullptr)
|
||||
{
|
||||
while (oldDevs[numDevs] != nullptr)
|
||||
++numDevs;
|
||||
}
|
||||
|
||||
CardinalMidiOutputDevice** const newDevs = new CardinalMidiOutputDevice*[numDevs + 2];
|
||||
|
||||
for (uint i=0; i<numDevs; ++i)
|
||||
newDevs[i] = oldDevs[i];
|
||||
|
||||
newDevs[numDevs+0] = dev;
|
||||
newDevs[numDevs+1] = nullptr;
|
||||
|
||||
{
|
||||
const MutexLocker cml(fDeviceMutex);
|
||||
fCurrentMidiOutputs = newDevs;
|
||||
}
|
||||
|
||||
delete[] oldDevs;
|
||||
}
|
||||
|
||||
void clearMidiInputDevice(CardinalMidiInputDevice* const dev) noexcept override
|
||||
{
|
||||
const MutexLocker cml(fDeviceMutex);
|
||||
|
||||
CardinalMidiInputDevice** const inputs = fCurrentMidiInputs;
|
||||
DISTRHO_SAFE_ASSERT_RETURN(inputs != nullptr,);
|
||||
|
||||
for (uint i=0; inputs[i] != nullptr; ++i)
|
||||
{
|
||||
CardinalMidiInputDevice* const input = inputs[i];
|
||||
if (input != dev)
|
||||
continue;
|
||||
for (; inputs[i+1] != nullptr; ++i)
|
||||
inputs[i] = inputs[i+1];
|
||||
inputs[i] = nullptr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void clearMidiOutputDevice(CardinalMidiOutputDevice* const dev) noexcept override
|
||||
{
|
||||
const MutexLocker cml(fDeviceMutex);
|
||||
|
||||
CardinalMidiOutputDevice** const outputs = fCurrentMidiOutputs;
|
||||
DISTRHO_SAFE_ASSERT_RETURN(outputs != nullptr,);
|
||||
|
||||
for (uint i=0; outputs[i] != nullptr; ++i)
|
||||
{
|
||||
CardinalMidiOutputDevice* const output = outputs[i];
|
||||
if (output != dev)
|
||||
continue;
|
||||
for (; outputs[i+1] != nullptr; ++i)
|
||||
outputs[i] = outputs[i+1];
|
||||
outputs[i] = nullptr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------------------
|
||||
* Information */
|
||||
|
||||
|
|
@ -875,32 +823,22 @@ protected:
|
|||
}
|
||||
}
|
||||
|
||||
inline void sendSingleSimpleMidiMessage(const MidiEvent& midiEvent)
|
||||
{
|
||||
if (CardinalMidiInputDevice** inputs = fCurrentMidiInputs)
|
||||
{
|
||||
for (;*inputs != nullptr; ++inputs)
|
||||
(*inputs)->handleSingleSimpleMessageFromHost(midiEvent);
|
||||
}
|
||||
}
|
||||
|
||||
void run(const float** const inputs, float** const outputs, const uint32_t frames,
|
||||
const MidiEvent* const midiEvents, const uint32_t midiEventCount) override
|
||||
{
|
||||
const MutexLocker cml(fDeviceMutex);
|
||||
rack::contextSet(context);
|
||||
|
||||
{
|
||||
const TimePosition& timePos(getTimePosition());
|
||||
|
||||
bool reset = false;
|
||||
MidiEvent singleTimeMidiEvent = { 0, 1, { 0, 0, 0, 0 }, nullptr };
|
||||
|
||||
if (timePos.playing)
|
||||
{
|
||||
if (timePos.frame == 0 || fPreviousFrame + frames != timePos.frame)
|
||||
reset = true;
|
||||
|
||||
/*
|
||||
if (! context->playing)
|
||||
{
|
||||
if (timePos.frame == 0)
|
||||
|
|
@ -912,11 +850,14 @@ protected:
|
|||
singleTimeMidiEvent.data[0] = 0xFB; // continue
|
||||
sendSingleSimpleMidiMessage(singleTimeMidiEvent);
|
||||
}
|
||||
*/
|
||||
}
|
||||
else if (context->playing)
|
||||
{
|
||||
/*
|
||||
singleTimeMidiEvent.data[0] = 0xFC; // stop
|
||||
sendSingleSimpleMidiMessage(singleTimeMidiEvent);
|
||||
*/
|
||||
}
|
||||
|
||||
context->playing = timePos.playing;
|
||||
|
|
@ -945,12 +886,6 @@ protected:
|
|||
fPreviousFrame = timePos.frame;
|
||||
}
|
||||
|
||||
if (CardinalMidiInputDevice** inputs = fCurrentMidiInputs)
|
||||
{
|
||||
for (;*inputs != nullptr; ++inputs)
|
||||
(*inputs)->handleMessagesFromHost(midiEvents, midiEventCount);
|
||||
}
|
||||
|
||||
// separate buffers, use them
|
||||
if (inputs != outputs && (inputs == nullptr || inputs[0] != outputs[0]))
|
||||
{
|
||||
|
|
@ -970,6 +905,9 @@ protected:
|
|||
for (int i=0; i<DISTRHO_PLUGIN_NUM_OUTPUTS; ++i)
|
||||
std::memset(outputs[i], 0, sizeof(float)*frames);
|
||||
|
||||
context->midiEvents = midiEvents;
|
||||
context->midiEventCount = midiEventCount;
|
||||
|
||||
context->engine->stepBlock(frames);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -60,6 +60,8 @@ struct CardinalPluginContext : rack::Context {
|
|||
uintptr_t nativeWindowId;
|
||||
const float* const* dataIns;
|
||||
float** dataOuts;
|
||||
const MidiEvent* midiEvents;
|
||||
uint32_t midiEventCount;
|
||||
Plugin* const plugin;
|
||||
#ifndef HEADLESS
|
||||
UI* ui;
|
||||
|
|
@ -95,6 +97,8 @@ struct CardinalPluginContext : rack::Context {
|
|||
nativeWindowId(0),
|
||||
dataIns(nullptr),
|
||||
dataOuts(nullptr),
|
||||
midiEvents(nullptr),
|
||||
midiEventCount(0),
|
||||
plugin(p)
|
||||
#ifndef HEADLESS
|
||||
, ui(nullptr)
|
||||
|
|
@ -103,6 +107,8 @@ struct CardinalPluginContext : rack::Context {
|
|||
std::memset(parameters, 0, sizeof(parameters));
|
||||
}
|
||||
|
||||
void writeMidiMessage(const rack::midi::Message& message);
|
||||
|
||||
#ifndef HEADLESS
|
||||
bool addIdleCallback(IdleCallback* cb) const;
|
||||
void removeIdleCallback(IdleCallback* cb) const;
|
||||
|
|
@ -129,10 +135,6 @@ public:
|
|||
: Plugin(parameterCount, programCount, stateCount),
|
||||
context(new CardinalPluginContext(this)) {}
|
||||
~CardinalBasePlugin() override {}
|
||||
virtual void assignMidiInputDevice(CardinalMidiInputDevice* dev) noexcept = 0;
|
||||
virtual void assignMidiOutputDevice(CardinalMidiOutputDevice* dev) noexcept = 0;
|
||||
virtual void clearMidiInputDevice(CardinalMidiInputDevice* dev) noexcept = 0;
|
||||
virtual void clearMidiOutputDevice(CardinalMidiOutputDevice* dev) noexcept = 0;
|
||||
};
|
||||
|
||||
#ifndef HEADLESS
|
||||
|
|
|
|||
|
|
@ -1,257 +0,0 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "PluginContext.hpp"
|
||||
|
||||
START_NAMESPACE_DISTRHO
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------------
|
||||
|
||||
struct CardinalMidiInputDevice : rack::midi::InputDevice
|
||||
{
|
||||
CardinalBasePlugin* const fPlugin;
|
||||
rack::midi::Message msg;
|
||||
|
||||
CardinalMidiInputDevice(CardinalBasePlugin* const plugin)
|
||||
: fPlugin(plugin)
|
||||
{
|
||||
msg.bytes.resize(0xff);
|
||||
}
|
||||
|
||||
std::string getName() override
|
||||
{
|
||||
return "Cardinal";
|
||||
}
|
||||
|
||||
inline void handleSingleSimpleMessageFromHost(const MidiEvent& midiEvent)
|
||||
{
|
||||
if (subscribed.size() == 0)
|
||||
return;
|
||||
|
||||
msg.frame = midiEvent.frame;
|
||||
std::memcpy(msg.bytes.data(), midiEvent.data, midiEvent.size);
|
||||
|
||||
onMessage(msg);
|
||||
}
|
||||
|
||||
inline void handleMessagesFromHost(const MidiEvent* const midiEvents, const uint32_t midiEventCount)
|
||||
{
|
||||
if (subscribed.size() == 0)
|
||||
return;
|
||||
|
||||
for (uint32_t i=0; i<midiEventCount; ++i)
|
||||
{
|
||||
const MidiEvent& midiEvent(midiEvents[i]);
|
||||
const uint8_t* data;
|
||||
|
||||
if (midiEvent.size > MidiEvent::kDataSize)
|
||||
{
|
||||
data = midiEvent.dataExt;
|
||||
msg.bytes.resize(midiEvent.size);
|
||||
}
|
||||
else
|
||||
{
|
||||
data = midiEvent.data;
|
||||
}
|
||||
|
||||
msg.frame = midiEvent.frame;
|
||||
std::memcpy(msg.bytes.data(), data, midiEvent.size);
|
||||
|
||||
onMessage(msg);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------------
|
||||
|
||||
struct CardinalMidiOutputDevice : rack::midi::OutputDevice
|
||||
{
|
||||
CardinalBasePlugin* const fPlugin;
|
||||
|
||||
CardinalMidiOutputDevice(CardinalBasePlugin* const plugin)
|
||||
: fPlugin(plugin) {}
|
||||
|
||||
std::string getName() override
|
||||
{
|
||||
return "Cardinal";
|
||||
}
|
||||
|
||||
void sendMessage(const rack::midi::Message& message) override
|
||||
{
|
||||
const size_t size = message.bytes.size();
|
||||
DISTRHO_SAFE_ASSERT_RETURN(size > 0,);
|
||||
|
||||
MidiEvent event;
|
||||
event.frame = message.frame < 0 ? 0 : (message.frame - fPlugin->context->engine->getBlockFrame());
|
||||
|
||||
switch (message.bytes[0] & 0xF0)
|
||||
{
|
||||
case 0x80:
|
||||
case 0x90:
|
||||
case 0xA0:
|
||||
case 0xB0:
|
||||
case 0xE0:
|
||||
event.size = 3;
|
||||
break;
|
||||
case 0xC0:
|
||||
case 0xD0:
|
||||
event.size = 2;
|
||||
break;
|
||||
case 0xF0:
|
||||
switch (message.bytes[0] & 0x0F)
|
||||
{
|
||||
case 0x0:
|
||||
case 0x4:
|
||||
case 0x5:
|
||||
case 0x7:
|
||||
case 0x9:
|
||||
case 0xD:
|
||||
// unsupported
|
||||
return;
|
||||
case 0x1:
|
||||
case 0x2:
|
||||
case 0x3:
|
||||
case 0xE:
|
||||
event.size = 3;
|
||||
break;
|
||||
case 0x6:
|
||||
case 0x8:
|
||||
case 0xA:
|
||||
case 0xB:
|
||||
case 0xC:
|
||||
case 0xF:
|
||||
event.size = 1;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
DISTRHO_SAFE_ASSERT_RETURN(size >= event.size,);
|
||||
|
||||
std::memcpy(event.data, message.bytes.data(), event.size);
|
||||
|
||||
fPlugin->writeMidiEvent(event);
|
||||
}
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------------
|
||||
|
||||
struct CardinalMidiDriver : rack::midi::Driver
|
||||
{
|
||||
CardinalMidiDriver() {}
|
||||
|
||||
std::string getName() override
|
||||
{
|
||||
return "Plugin Driver";
|
||||
}
|
||||
|
||||
std::vector<int> getInputDeviceIds() override
|
||||
{
|
||||
return std::vector<int>({ 0 });
|
||||
}
|
||||
|
||||
std::vector<int> getOutputDeviceIds() override
|
||||
{
|
||||
return std::vector<int>({ 0 });
|
||||
}
|
||||
|
||||
int getDefaultInputDeviceId() override
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int getDefaultOutputDeviceId() override
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::string getInputDeviceName(int) override
|
||||
{
|
||||
return "Plugin Device";
|
||||
}
|
||||
|
||||
std::string getOutputDeviceName(int) override
|
||||
{
|
||||
return "Plugin Device";
|
||||
}
|
||||
|
||||
rack::midi::InputDevice* subscribeInput(int, rack::midi::Input* const input) override
|
||||
{
|
||||
CardinalPluginContext* const pluginContext = reinterpret_cast<CardinalPluginContext*>(input->context);
|
||||
DISTRHO_SAFE_ASSERT_RETURN(pluginContext != nullptr, nullptr);
|
||||
|
||||
CardinalBasePlugin* const plugin = reinterpret_cast<CardinalBasePlugin*>(pluginContext->plugin);
|
||||
DISTRHO_SAFE_ASSERT_RETURN(plugin != nullptr, nullptr);
|
||||
|
||||
CardinalMidiInputDevice* const device = new CardinalMidiInputDevice(plugin);
|
||||
device->subscribe(input);
|
||||
plugin->assignMidiInputDevice(device);
|
||||
return device;
|
||||
}
|
||||
|
||||
rack::midi::OutputDevice* subscribeOutput(int, rack::midi::Output* const output) override
|
||||
{
|
||||
CardinalPluginContext* const pluginContext = reinterpret_cast<CardinalPluginContext*>(output->context);
|
||||
DISTRHO_SAFE_ASSERT_RETURN(pluginContext != nullptr, nullptr);
|
||||
|
||||
CardinalBasePlugin* const plugin = reinterpret_cast<CardinalBasePlugin*>(pluginContext->plugin);
|
||||
DISTRHO_SAFE_ASSERT_RETURN(plugin != nullptr, nullptr);
|
||||
|
||||
CardinalMidiOutputDevice* const device = new CardinalMidiOutputDevice(plugin);
|
||||
device->subscribe(output);
|
||||
plugin->assignMidiOutputDevice(device);
|
||||
return device;
|
||||
}
|
||||
|
||||
void unsubscribeInput(int, rack::midi::Input* const input) override
|
||||
{
|
||||
CardinalMidiInputDevice* const device = reinterpret_cast<CardinalMidiInputDevice*>(input->device);
|
||||
DISTRHO_SAFE_ASSERT_RETURN(device != nullptr,);
|
||||
|
||||
CardinalPluginContext* const pluginContext = reinterpret_cast<CardinalPluginContext*>(input->context);
|
||||
DISTRHO_SAFE_ASSERT_RETURN(pluginContext != nullptr,);
|
||||
|
||||
CardinalBasePlugin* const plugin = reinterpret_cast<CardinalBasePlugin*>(pluginContext->plugin);
|
||||
DISTRHO_SAFE_ASSERT_RETURN(plugin != nullptr,);
|
||||
|
||||
plugin->clearMidiInputDevice(device);
|
||||
device->unsubscribe(input);
|
||||
delete device;
|
||||
}
|
||||
|
||||
void unsubscribeOutput(int, rack::midi::Output* const output) override
|
||||
{
|
||||
CardinalMidiOutputDevice* const device = reinterpret_cast<CardinalMidiOutputDevice*>(output->device);
|
||||
DISTRHO_SAFE_ASSERT_RETURN(device != nullptr,);
|
||||
|
||||
CardinalPluginContext* const pluginContext = reinterpret_cast<CardinalPluginContext*>(output->context);
|
||||
DISTRHO_SAFE_ASSERT_RETURN(pluginContext != nullptr,);
|
||||
|
||||
CardinalBasePlugin* const plugin = reinterpret_cast<CardinalBasePlugin*>(pluginContext->plugin);
|
||||
DISTRHO_SAFE_ASSERT_RETURN(plugin != nullptr,);
|
||||
|
||||
plugin->clearMidiOutputDevice(device);
|
||||
device->unsubscribe(output);
|
||||
delete device;
|
||||
}
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------------
|
||||
|
||||
END_NAMESPACE_DISTRHO
|
||||
|
|
@ -24,9 +24,9 @@
|
|||
},
|
||||
{
|
||||
"id": 2,
|
||||
"plugin": "Core",
|
||||
"version": "2.0.0",
|
||||
"model": "MIDIToCVInterface",
|
||||
"plugin": "Cardinal",
|
||||
"model": "HostMIDI",
|
||||
"version": "2.0",
|
||||
"params": [],
|
||||
"leftModuleId": 1,
|
||||
"rightModuleId": 3,
|
||||
|
|
@ -35,12 +35,7 @@
|
|||
"polyMode": 0,
|
||||
"clockDivision": 24,
|
||||
"lastPitch": 8192,
|
||||
"lastMod": 0,
|
||||
"midi": {
|
||||
"driver": 0,
|
||||
"deviceName": "Cardinal",
|
||||
"channel": -1
|
||||
}
|
||||
"lastMod": 0
|
||||
},
|
||||
"pos": [
|
||||
5,
|
||||
|
|
@ -49,47 +44,26 @@
|
|||
},
|
||||
{
|
||||
"id": 3,
|
||||
"plugin": "Core",
|
||||
"version": "2.0.0",
|
||||
"model": "CV-MIDI",
|
||||
"plugin": "Cardinal",
|
||||
"model": "HostParameters",
|
||||
"version": "2.0",
|
||||
"params": [],
|
||||
"leftModuleId": 2,
|
||||
"rightModuleId": 4,
|
||||
"data": {
|
||||
"midi": {
|
||||
"driver": 0,
|
||||
"deviceName": "Cardinal",
|
||||
"channel": 0
|
||||
}
|
||||
},
|
||||
"pos": [
|
||||
13,
|
||||
18,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"plugin": "Cardinal",
|
||||
"model": "HostParameters",
|
||||
"version": "2.0",
|
||||
"params": [],
|
||||
"leftModuleId": 3,
|
||||
"rightModuleId": 5,
|
||||
"pos": [
|
||||
21,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"plugin": "Cardinal",
|
||||
"model": "HostTime",
|
||||
"version": "2.0",
|
||||
"params": [],
|
||||
"leftModuleId": 4,
|
||||
"rightModuleId": 6,
|
||||
"leftModuleId": 3,
|
||||
"pos": [
|
||||
30,
|
||||
27,
|
||||
0
|
||||
]
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue