|
|
@@ -51,8 +51,6 @@ |
|
|
|
* - MIDI program changes |
|
|
|
* - MIDI sysex |
|
|
|
* == BUSES |
|
|
|
* - bus arrangements |
|
|
|
* - optional audio buses |
|
|
|
* - routing info, do we care? |
|
|
|
* == CV |
|
|
|
* - cv scaling to -1/+1 |
|
|
@@ -265,8 +263,11 @@ class PluginVst3 |
|
|
|
/* Buses: count possible buses we can provide to the host, in case they are not yet defined by the developer. |
|
|
|
* These values are only used if port groups aren't set. |
|
|
|
* |
|
|
|
* When port groups are not in use, we fill in appropriately. |
|
|
|
* 1 bus is provided for the main audio (if there is any) plus 1 for sidechain and 1 for each cv port. |
|
|
|
* When port groups are not in use: |
|
|
|
* - 1 bus is provided for the main audio (if there is any) |
|
|
|
* - 1 for sidechain |
|
|
|
* - 1 for each cv port |
|
|
|
* So basically: |
|
|
|
* Main audio is used as first bus, if available. |
|
|
|
* Then sidechain, also if available. |
|
|
|
* And finally each CV port individually. |
|
|
@@ -608,12 +609,12 @@ public: |
|
|
|
#endif |
|
|
|
{ |
|
|
|
#if DISTRHO_PLUGIN_NUM_INPUTS > 0 |
|
|
|
fillInBusInfoDetails<true>(); |
|
|
|
std::memset(fEnabledInputs, 0, sizeof(fEnabledInputs)); |
|
|
|
fillInBusInfoDetails<true>(); |
|
|
|
#endif |
|
|
|
#if DISTRHO_PLUGIN_NUM_OUTPUTS > 0 |
|
|
|
fillInBusInfoDetails<false>(); |
|
|
|
std::memset(fEnabledOutputs, 0, sizeof(fEnabledOutputs)); |
|
|
|
fillInBusInfoDetails<false>(); |
|
|
|
#endif |
|
|
|
|
|
|
|
if (const uint32_t extraParameterCount = fParameterCount + kVst3InternalParameterBaseCount) |
|
|
@@ -706,9 +707,9 @@ public: |
|
|
|
} |
|
|
|
|
|
|
|
fCachedParameterValues[kVst3InternalParameterBaseCount + index] = value; |
|
|
|
#if DISTRHO_PLUGIN_HAS_UI |
|
|
|
#if DISTRHO_PLUGIN_HAS_UI |
|
|
|
fParameterValueChangesForUI[kVst3InternalParameterBaseCount + index] = true; |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
fPlugin.setParameterValue(index, value); |
|
|
|
} |
|
|
|
|
|
|
@@ -825,17 +826,62 @@ public: |
|
|
|
|
|
|
|
v3_result getRoutingInfo(v3_routing_info*, v3_routing_info*) |
|
|
|
{ |
|
|
|
// TODO |
|
|
|
/* |
|
|
|
output->media_type = V3_AUDIO; |
|
|
|
output->bus_idx = 0; |
|
|
|
output->channel = -1; |
|
|
|
d_stdout("getRoutingInfo %s %d %d", |
|
|
|
v3_media_type_str(input->media_type), input->bus_idx, input->channel); |
|
|
|
*/ |
|
|
|
return V3_NOT_IMPLEMENTED; |
|
|
|
} |
|
|
|
|
|
|
|
v3_result activateBus(const int32_t /* mediaType */, |
|
|
|
const int32_t /* busDirection */, |
|
|
|
const int32_t /* busIndex */, |
|
|
|
const bool /* state */) |
|
|
|
v3_result activateBus(const int32_t mediaType, |
|
|
|
const int32_t busDirection, |
|
|
|
const int32_t busIndex, |
|
|
|
const bool state) noexcept |
|
|
|
{ |
|
|
|
// TODO, returning ok to make bitwig happy |
|
|
|
DISTRHO_SAFE_ASSERT_INT_RETURN(busDirection == V3_INPUT || busDirection == V3_OUTPUT, busDirection, V3_INVALID_ARG); |
|
|
|
DISTRHO_SAFE_ASSERT_INT_RETURN(busIndex >= 0, busIndex, V3_INVALID_ARG); |
|
|
|
|
|
|
|
if (mediaType == V3_AUDIO) |
|
|
|
{ |
|
|
|
#if DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS > 0 |
|
|
|
const uint32_t busId = static_cast<uint32_t>(busIndex); |
|
|
|
|
|
|
|
if (busDirection == V3_INPUT) |
|
|
|
{ |
|
|
|
#if DISTRHO_PLUGIN_NUM_INPUTS > 0 |
|
|
|
for (uint32_t i=0; i<DISTRHO_PLUGIN_NUM_INPUTS; ++i) |
|
|
|
{ |
|
|
|
const AudioPortWithBusId& port(fPlugin.getAudioPort(true, i)); |
|
|
|
|
|
|
|
if (port.busId == busId) |
|
|
|
fEnabledInputs[i] = state; |
|
|
|
} |
|
|
|
#endif |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
#if DISTRHO_PLUGIN_NUM_OUTPUTS > 0 |
|
|
|
for (uint32_t i=0; i<DISTRHO_PLUGIN_NUM_OUTPUTS; ++i) |
|
|
|
{ |
|
|
|
const AudioPortWithBusId& port(fPlugin.getAudioPort(false, i)); |
|
|
|
|
|
|
|
if (port.busId == busId) |
|
|
|
fEnabledOutputs[i] = state; |
|
|
|
} |
|
|
|
#endif |
|
|
|
} |
|
|
|
#endif |
|
|
|
} |
|
|
|
|
|
|
|
return V3_OK; |
|
|
|
|
|
|
|
#if DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS == 0 |
|
|
|
// unused |
|
|
|
(void)state; |
|
|
|
#endif |
|
|
|
} |
|
|
|
|
|
|
|
v3_result setActive(const bool active) |
|
|
@@ -1360,28 +1406,38 @@ public: |
|
|
|
|
|
|
|
{ |
|
|
|
int32_t i = 0; |
|
|
|
#if DISTRHO_PLUGIN_NUM_INPUTS > 0 |
|
|
|
if (data->inputs != nullptr) |
|
|
|
{ |
|
|
|
for (; i < data->inputs->num_channels; ++i) |
|
|
|
for (int32_t j = 0; j < data->inputs->num_channels; ++j) |
|
|
|
{ |
|
|
|
while (!fEnabledInputs[i] && i < DISTRHO_PLUGIN_NUM_INPUTS) |
|
|
|
inputs[i++] = fDummyAudioBuffer; |
|
|
|
|
|
|
|
DISTRHO_SAFE_ASSERT_INT_BREAK(i < DISTRHO_PLUGIN_NUM_INPUTS, i); |
|
|
|
inputs[i] = data->inputs->channel_buffers_32[i]; |
|
|
|
inputs[i++] = data->inputs->channel_buffers_32[j]; |
|
|
|
} |
|
|
|
} |
|
|
|
#endif |
|
|
|
for (; i < std::max(1, DISTRHO_PLUGIN_NUM_INPUTS); ++i) |
|
|
|
inputs[i] = fDummyAudioBuffer; |
|
|
|
} |
|
|
|
|
|
|
|
{ |
|
|
|
int32_t i = 0; |
|
|
|
#if DISTRHO_PLUGIN_NUM_OUTPUTS > 0 |
|
|
|
if (data->outputs != nullptr) |
|
|
|
{ |
|
|
|
for (; i < data->outputs->num_channels; ++i) |
|
|
|
for (int32_t j = 0; j < data->outputs->num_channels; ++j) |
|
|
|
{ |
|
|
|
while (!fEnabledOutputs[i] && i < DISTRHO_PLUGIN_NUM_OUTPUTS) |
|
|
|
outputs[i++] = fDummyAudioBuffer; |
|
|
|
|
|
|
|
DISTRHO_SAFE_ASSERT_INT_BREAK(i < DISTRHO_PLUGIN_NUM_OUTPUTS, i); |
|
|
|
outputs[i] = data->outputs->channel_buffers_32[i]; |
|
|
|
outputs[i++] = data->outputs->channel_buffers_32[j]; |
|
|
|
} |
|
|
|
} |
|
|
|
#endif |
|
|
|
for (; i < std::max(1, DISTRHO_PLUGIN_NUM_OUTPUTS); ++i) |
|
|
|
outputs[i] = fDummyAudioBuffer; |
|
|
|
} |
|
|
@@ -2410,15 +2466,17 @@ private: |
|
|
|
if (busInfo.sidechainPorts != 0) |
|
|
|
busInfo.sidechain = 1; |
|
|
|
|
|
|
|
uint32_t busIdFromGroup = 0; |
|
|
|
uint32_t busIdForCV = 0; |
|
|
|
const std::vector<uint32_t>::iterator vpgStart = visitedPortGroups.begin(); |
|
|
|
const std::vector<uint32_t>::iterator vpgEnd = visitedPortGroups.end(); |
|
|
|
|
|
|
|
for (uint32_t i=0; i<numPorts; ++i) |
|
|
|
{ |
|
|
|
AudioPortWithBusId& port(fPlugin.getAudioPort(isInput, i)); |
|
|
|
|
|
|
|
if (port.groupId != kPortGroupNone) |
|
|
|
{ |
|
|
|
port.busId = busIdFromGroup++; |
|
|
|
port.busId = std::find(vpgStart, vpgEnd, port.groupId) - vpgStart; |
|
|
|
|
|
|
|
if (busInfo.audio == 0 && (port.hints & kAudioPortIsSidechain) == 0x0) |
|
|
|
enabledPorts[i] = true; |
|
|
@@ -2457,9 +2515,7 @@ private: |
|
|
|
|
|
|
|
if (busId < busInfo.groups) |
|
|
|
{ |
|
|
|
numChannels = fPlugin.getAudioPortCountWithGroupId(isInput, busId); |
|
|
|
busType = V3_AUX; |
|
|
|
flags = 0; |
|
|
|
numChannels = 0; |
|
|
|
|
|
|
|
for (uint32_t i=0; i<numPorts; ++i) |
|
|
|
{ |
|
|
@@ -2472,8 +2528,6 @@ private: |
|
|
|
switch (port.groupId) |
|
|
|
{ |
|
|
|
case kPortGroupStereo: |
|
|
|
numChannels = 2; |
|
|
|
// fall-through |
|
|
|
case kPortGroupMono: |
|
|
|
strncpy_utf16(busName, isInput ? "Audio Input" : "Audio Output", 128); |
|
|
|
break; |
|
|
@@ -2485,14 +2539,23 @@ private: |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
numChannels = fPlugin.getAudioPortCountWithGroupId(isInput, port.groupId); |
|
|
|
|
|
|
|
if (busInfo.audio == 0 && (port.hints & kAudioPortIsSidechain) == 0x0) |
|
|
|
{ |
|
|
|
busType = V3_MAIN; |
|
|
|
flags = V3_DEFAULT_ACTIVE; |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
busType = V3_AUX; |
|
|
|
flags = 0; |
|
|
|
} |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
DISTRHO_SAFE_ASSERT_RETURN(numChannels != 0, V3_INTERNAL_ERR); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
@@ -2545,7 +2608,7 @@ private: |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// d_stdout("getAudioBusInfo %d %d", busId, numChannels); |
|
|
|
// d_stdout("getAudioBusInfo %d %d %d", (int)isInput, busId, numChannels); |
|
|
|
std::memset(info, 0, sizeof(v3_bus_info)); |
|
|
|
info->media_type = V3_AUDIO; |
|
|
|
info->direction = isInput ? V3_INPUT : V3_OUTPUT; |
|
|
@@ -2556,6 +2619,50 @@ private: |
|
|
|
return V3_OK; |
|
|
|
} |
|
|
|
|
|
|
|
template<bool isInput> |
|
|
|
v3_speaker_arrangement getSpeakerArrangementForAudioPort(const BusInfo& busInfo, const uint32_t portGroupId, uint32_t busId) const noexcept |
|
|
|
{ |
|
|
|
switch (portGroupId) |
|
|
|
{ |
|
|
|
case kPortGroupMono: |
|
|
|
return V3_SPEAKER_M; |
|
|
|
case kPortGroupStereo: |
|
|
|
return V3_SPEAKER_L | V3_SPEAKER_R; |
|
|
|
} |
|
|
|
|
|
|
|
v3_speaker_arrangement arr = 0x0; |
|
|
|
|
|
|
|
if (busId < busInfo.groups) |
|
|
|
{ |
|
|
|
const uint32_t numPortsInBus = fPlugin.getAudioPortCountWithGroupId(isInput, busId); |
|
|
|
for (uint32_t j=0; j<numPortsInBus; ++j) |
|
|
|
arr |= 1ull << (j + 33ull); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
busId -= busInfo.groups; |
|
|
|
|
|
|
|
if (busInfo.audio != 0 && busId == 0) |
|
|
|
{ |
|
|
|
arr = 0x0; |
|
|
|
for (uint32_t j=0; j<busInfo.audioPorts; ++j) |
|
|
|
arr |= 1ull << (j + 33ull); |
|
|
|
} |
|
|
|
else if (busInfo.sidechain != 0 && busId == busInfo.audio) |
|
|
|
{ |
|
|
|
arr = 0x0; |
|
|
|
for (uint32_t j=0; j<busInfo.sidechainPorts; ++j) |
|
|
|
arr |= 1ull << (busInfo.audioPorts + j + 33ull); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
arr = 1ull << (busInfo.audioPorts + busInfo.sidechainPorts + busId + 33ull); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
return arr; |
|
|
|
} |
|
|
|
|
|
|
|
template<bool isInput> |
|
|
|
bool getAudioBusArrangement(uint32_t busId, v3_speaker_arrangement* const speaker) const |
|
|
|
{ |
|
|
@@ -2586,54 +2693,12 @@ private: |
|
|
|
if (!enabledPorts[i]) |
|
|
|
{ |
|
|
|
*speaker = 0; |
|
|
|
// d_stdout("getAudioBusArrangement %d %lx", busId, 0); |
|
|
|
// d_stdout("getAudioBusArrangement %d %d not enabled", i, busId); |
|
|
|
return true; |
|
|
|
} |
|
|
|
|
|
|
|
v3_speaker_arrangement arr; |
|
|
|
|
|
|
|
switch (port.groupId) |
|
|
|
{ |
|
|
|
case kPortGroupMono: |
|
|
|
arr = V3_SPEAKER_M; |
|
|
|
break; |
|
|
|
case kPortGroupStereo: |
|
|
|
arr = V3_SPEAKER_L | V3_SPEAKER_R; |
|
|
|
break; |
|
|
|
default: |
|
|
|
if (busId < busInfo.groups) |
|
|
|
{ |
|
|
|
const uint32_t numPortsInBus = fPlugin.getAudioPortCountWithGroupId(isInput, busId); |
|
|
|
arr = 0x0; |
|
|
|
for (uint32_t j=0; j<numPortsInBus; ++j) |
|
|
|
arr |= 1ull << (j + 33ull); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
busId -= busInfo.groups; |
|
|
|
|
|
|
|
if (busInfo.audio != 0 && busId == 0) |
|
|
|
{ |
|
|
|
arr = 0x0; |
|
|
|
for (uint32_t j=0; j<busInfo.audioPorts; ++j) |
|
|
|
arr |= 1ull << (j + 33ull); |
|
|
|
} |
|
|
|
else if (busInfo.sidechain != 0 && busId == busInfo.audio) |
|
|
|
{ |
|
|
|
arr = 0x0; |
|
|
|
for (uint32_t j=0; j<busInfo.sidechainPorts; ++j) |
|
|
|
arr |= 1ull << (busInfo.audioPorts + j + 33ull); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
arr = 1ull << (busInfo.audioPorts + busInfo.sidechainPorts + busId + 33ull); |
|
|
|
} |
|
|
|
} |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
*speaker = arr; |
|
|
|
// d_stdout("getAudioBusArrangement %d %lx", busId, arr); |
|
|
|
*speaker = getSpeakerArrangementForAudioPort<isInput>(busInfo, port.groupId, busId); |
|
|
|
// d_stdout("getAudioBusArrangement %d enabled by value %lx", busId, *speaker); |
|
|
|
return true; |
|
|
|
} |
|
|
|
|
|
|
@@ -2657,6 +2722,8 @@ private: |
|
|
|
: nullptr; |
|
|
|
#endif |
|
|
|
|
|
|
|
bool ok = true; |
|
|
|
|
|
|
|
for (uint32_t busId=0; busId<numBuses; ++busId) |
|
|
|
{ |
|
|
|
const v3_speaker_arrangement arr = speakers[busId]; |
|
|
@@ -2673,26 +2740,14 @@ private: |
|
|
|
continue; |
|
|
|
} |
|
|
|
|
|
|
|
if (arr == (V3_SPEAKER_L|V3_SPEAKER_R)) |
|
|
|
{ |
|
|
|
// some hosts try to make CV ports stereo, that doesn't make any sense! |
|
|
|
if (port.hints & kAudioPortIsCV) |
|
|
|
return false; |
|
|
|
// get the only valid speaker arrangement for this bus, assuming enabled |
|
|
|
const v3_speaker_arrangement earr = getSpeakerArrangementForAudioPort<isInput>(busInfo, port.groupId, busId); |
|
|
|
|
|
|
|
// force stereo mode |
|
|
|
if (busId == 0 && busInfo.audioPorts != 0) |
|
|
|
{ |
|
|
|
busInfo.audioPorts = 2; |
|
|
|
enabledPorts[i] = i < 2; |
|
|
|
} |
|
|
|
|
|
|
|
/* |
|
|
|
// special case for turning mono into "stereo" |
|
|
|
if (port.groupId == kPortGroupMono) |
|
|
|
port.groupId = kPortGroupStereo; |
|
|
|
else if (busId == 0 && busInfo.audioPorts == 1) |
|
|
|
busInfo.audioPorts = 2; |
|
|
|
*/ |
|
|
|
// fail if host tries to map it to anything else |
|
|
|
if (earr != arr && arr != 0) |
|
|
|
{ |
|
|
|
ok = false; |
|
|
|
continue; |
|
|
|
} |
|
|
|
|
|
|
|
enabledPorts[i] = arr != 0; |
|
|
@@ -2716,7 +2771,7 @@ private: |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
return true; |
|
|
|
return ok; |
|
|
|
} |
|
|
|
#endif |
|
|
|
|
|
|
@@ -4594,7 +4649,7 @@ struct dpf_factory : v3_plugin_factory_cpp { |
|
|
|
d_stdout("dpf_factory::get_factory_info => %p", info); |
|
|
|
std::memset(info, 0, sizeof(*info)); |
|
|
|
|
|
|
|
info->flags = 0x10; |
|
|
|
info->flags = 0x10; // unicode |
|
|
|
DISTRHO_NAMESPACE::strncpy(info->vendor, getPluginInfo().getMaker(), ARRAY_SIZE(info->vendor)); |
|
|
|
DISTRHO_NAMESPACE::strncpy(info->url, getPluginInfo().getHomePage(), ARRAY_SIZE(info->url)); |
|
|
|
// DISTRHO_NAMESPACE::strncpy(info->email, "", ARRAY_SIZE(info->email)); // TODO |
|
|
|