mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-22 06:36:29 +01:00
Update variable-i/o channel assignment, separate sidechains
We need to be able to distinguish * 2 ins: mono + sidechain * 2 ins: stereo input
This commit is contained in:
parent
17f0b87648
commit
7ec10f7771
6 changed files with 247 additions and 204 deletions
|
|
@ -106,8 +106,8 @@ class LIBARDOUR_API AUPlugin : public ARDOUR::Plugin
|
||||||
|
|
||||||
bool has_editor () const;
|
bool has_editor () const;
|
||||||
|
|
||||||
bool match_variable_io (const ChanCount& in, ChanCount& out, ChanCount* imprecise);
|
bool match_variable_io (ChanCount& in, ChanCount& aux_in, ChanCount& out);
|
||||||
bool reconfigure_io (ChanCount in, ChanCount out);
|
bool reconfigure_io (ChanCount in, ChanCount aux_in, ChanCount out);
|
||||||
|
|
||||||
ChanCount output_streams() const;
|
ChanCount output_streams() const;
|
||||||
ChanCount input_streams() const;
|
ChanCount input_streams() const;
|
||||||
|
|
@ -203,6 +203,7 @@ class LIBARDOUR_API AUPlugin : public ARDOUR::Plugin
|
||||||
uint32_t configured_output_busses;
|
uint32_t configured_output_busses;
|
||||||
|
|
||||||
uint32_t *bus_inputs;
|
uint32_t *bus_inputs;
|
||||||
|
uint32_t *bus_inused;
|
||||||
uint32_t *bus_outputs;
|
uint32_t *bus_outputs;
|
||||||
std::vector <std::string> _bus_name_in;
|
std::vector <std::string> _bus_name_in;
|
||||||
std::vector <std::string> _bus_name_out;
|
std::vector <std::string> _bus_name_out;
|
||||||
|
|
@ -219,7 +220,6 @@ class LIBARDOUR_API AUPlugin : public ARDOUR::Plugin
|
||||||
BufferSet* input_buffers;
|
BufferSet* input_buffers;
|
||||||
ChanMapping const * input_map;
|
ChanMapping const * input_map;
|
||||||
samplecnt_t samples_processed;
|
samplecnt_t samples_processed;
|
||||||
uint32_t audio_input_cnt;
|
|
||||||
|
|
||||||
std::vector<AUParameterDescriptor> descriptors;
|
std::vector<AUParameterDescriptor> descriptors;
|
||||||
AUEventListenerRef _parameter_listener;
|
AUEventListenerRef _parameter_listener;
|
||||||
|
|
|
||||||
|
|
@ -117,8 +117,8 @@ public:
|
||||||
|
|
||||||
bool has_editor() const { return false; }
|
bool has_editor() const { return false; }
|
||||||
|
|
||||||
bool match_variable_io (const ChanCount& in, ChanCount& out, ChanCount* imprecise);
|
bool match_variable_io (ChanCount& in, ChanCount& aux_in, ChanCount& out);
|
||||||
bool reconfigure_io (ChanCount in, ChanCount out);
|
bool reconfigure_io (ChanCount in, ChanCount aux_in, ChanCount out);
|
||||||
|
|
||||||
ChanCount output_streams() const { return _configured_out; }
|
ChanCount output_streams() const { return _configured_out; }
|
||||||
ChanCount input_streams() const { return _configured_in; }
|
ChanCount input_streams() const { return _configured_in; }
|
||||||
|
|
|
||||||
|
|
@ -294,8 +294,8 @@ public:
|
||||||
*/
|
*/
|
||||||
PBD::Signal2<void, uint32_t, float> ParameterChangedExternally;
|
PBD::Signal2<void, uint32_t, float> ParameterChangedExternally;
|
||||||
|
|
||||||
virtual bool reconfigure_io (ChanCount /*in*/, ChanCount /*out*/) { return true; }
|
virtual bool reconfigure_io (ChanCount /*in*/, ChanCount /*aux_in*/, ChanCount /*out*/) { return true; }
|
||||||
virtual bool match_variable_io (const ChanCount& /*in*/, ChanCount& /*out*/, ChanCount* imprecise = 0) { return false; }
|
virtual bool match_variable_io (ChanCount& /*in*/, ChanCount& /*aux_in*/, ChanCount& /*out*/) { return false; }
|
||||||
|
|
||||||
virtual ChanCount output_streams () const;
|
virtual ChanCount output_streams () const;
|
||||||
virtual ChanCount input_streams () const;
|
virtual ChanCount input_streams () const;
|
||||||
|
|
|
||||||
|
|
@ -443,6 +443,7 @@ AUPlugin::AUPlugin (AudioEngine& engine, Session& session, boost::shared_ptr<CAC
|
||||||
, configured_input_busses (0)
|
, configured_input_busses (0)
|
||||||
, configured_output_busses (0)
|
, configured_output_busses (0)
|
||||||
, bus_inputs (0)
|
, bus_inputs (0)
|
||||||
|
, bus_inused (0)
|
||||||
, bus_outputs (0)
|
, bus_outputs (0)
|
||||||
, input_maxbuf (0)
|
, input_maxbuf (0)
|
||||||
, input_offset (0)
|
, input_offset (0)
|
||||||
|
|
@ -450,7 +451,6 @@ AUPlugin::AUPlugin (AudioEngine& engine, Session& session, boost::shared_ptr<CAC
|
||||||
, input_buffers (0)
|
, input_buffers (0)
|
||||||
, input_map (0)
|
, input_map (0)
|
||||||
, samples_processed (0)
|
, samples_processed (0)
|
||||||
, audio_input_cnt (0)
|
|
||||||
, _parameter_listener (0)
|
, _parameter_listener (0)
|
||||||
, _parameter_listener_arg (0)
|
, _parameter_listener_arg (0)
|
||||||
, transport_sample (0)
|
, transport_sample (0)
|
||||||
|
|
@ -485,6 +485,7 @@ AUPlugin::AUPlugin (const AUPlugin& other)
|
||||||
, configured_input_busses (0)
|
, configured_input_busses (0)
|
||||||
, configured_output_busses (0)
|
, configured_output_busses (0)
|
||||||
, bus_inputs (0)
|
, bus_inputs (0)
|
||||||
|
, bus_inused (0)
|
||||||
, bus_outputs (0)
|
, bus_outputs (0)
|
||||||
, input_maxbuf (0)
|
, input_maxbuf (0)
|
||||||
, input_offset (0)
|
, input_offset (0)
|
||||||
|
|
@ -492,7 +493,6 @@ AUPlugin::AUPlugin (const AUPlugin& other)
|
||||||
, input_buffers (0)
|
, input_buffers (0)
|
||||||
, input_map (0)
|
, input_map (0)
|
||||||
, samples_processed (0)
|
, samples_processed (0)
|
||||||
, audio_input_cnt (0)
|
|
||||||
, _parameter_listener (0)
|
, _parameter_listener (0)
|
||||||
, _parameter_listener_arg (0)
|
, _parameter_listener_arg (0)
|
||||||
, transport_sample (0)
|
, transport_sample (0)
|
||||||
|
|
@ -526,6 +526,7 @@ AUPlugin::~AUPlugin ()
|
||||||
|
|
||||||
free (buffers);
|
free (buffers);
|
||||||
free (bus_inputs);
|
free (bus_inputs);
|
||||||
|
free (bus_inused);
|
||||||
free (bus_outputs);
|
free (bus_outputs);
|
||||||
free (cb_offsets);
|
free (cb_offsets);
|
||||||
}
|
}
|
||||||
|
|
@ -618,9 +619,15 @@ AUPlugin::init ()
|
||||||
DEBUG_TRACE (DEBUG::AudioUnitConfig, "count output elements\n");
|
DEBUG_TRACE (DEBUG::AudioUnitConfig, "count output elements\n");
|
||||||
unit->GetElementCount (kAudioUnitScope_Output, output_elements);
|
unit->GetElementCount (kAudioUnitScope_Output, output_elements);
|
||||||
|
|
||||||
cb_offsets = (samplecnt_t*) calloc (input_elements, sizeof(samplecnt_t));
|
|
||||||
bus_inputs = (uint32_t*) calloc (input_elements, sizeof(uint32_t));
|
if (input_elements > 0) {
|
||||||
bus_outputs = (uint32_t*) calloc (output_elements, sizeof(uint32_t));
|
cb_offsets = (samplecnt_t*) calloc (input_elements, sizeof(samplecnt_t));
|
||||||
|
bus_inputs = (uint32_t*) calloc (input_elements, sizeof(uint32_t));
|
||||||
|
bus_inused = (uint32_t*) calloc (input_elements, sizeof(uint32_t));
|
||||||
|
}
|
||||||
|
if (output_elements > 0) {
|
||||||
|
bus_outputs = (uint32_t*) calloc (output_elements, sizeof(uint32_t));
|
||||||
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < output_elements; ++i) {
|
for (size_t i = 0; i < output_elements; ++i) {
|
||||||
unit->Reset (kAudioUnitScope_Output, i);
|
unit->Reset (kAudioUnitScope_Output, i);
|
||||||
|
|
@ -647,6 +654,7 @@ AUPlugin::init ()
|
||||||
err = unit->GetFormat (kAudioUnitScope_Input, i, fmt);
|
err = unit->GetFormat (kAudioUnitScope_Input, i, fmt);
|
||||||
if (err == noErr) {
|
if (err == noErr) {
|
||||||
bus_inputs[i] = fmt.mChannelsPerFrame;
|
bus_inputs[i] = fmt.mChannelsPerFrame;
|
||||||
|
bus_inused[i] = bus_inputs[i];
|
||||||
}
|
}
|
||||||
CFStringRef name;
|
CFStringRef name;
|
||||||
UInt32 sz = sizeof (CFStringRef);
|
UInt32 sz = sizeof (CFStringRef);
|
||||||
|
|
@ -1088,29 +1096,35 @@ AUPlugin::set_block_size (pframes_t nframes)
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
AUPlugin::reconfigure_io (ChanCount in, ChanCount out)
|
AUPlugin::reconfigure_io (ChanCount in, ChanCount aux_in, ChanCount out)
|
||||||
{
|
{
|
||||||
AudioStreamBasicDescription streamFormat;
|
AudioStreamBasicDescription streamFormat;
|
||||||
bool was_initialized = initialized;
|
bool was_initialized = initialized;
|
||||||
int32_t audio_out = out.n_audio();
|
|
||||||
if (audio_input_cnt > 0) {
|
|
||||||
in.set (DataType::AUDIO, audio_input_cnt);
|
|
||||||
}
|
|
||||||
const int32_t audio_in = in.n_audio();
|
|
||||||
|
|
||||||
DEBUG_TRACE (DEBUG::AudioUnitConfig, string_compose ("configure %1 for %2 in %3 out\n", name(), in, out));
|
DEBUG_TRACE (DEBUG::AudioUnitConfig, string_compose ("AUPlugin::reconfigure_io %1 for in: %2 aux-in %3 out: %4 out\n", name(), in, aux_in, out));
|
||||||
|
|
||||||
|
//TODO handle cases of no-input, only sidechain
|
||||||
|
// (needs special-casing of configured_input_busses)
|
||||||
|
if (input_elements == 1 || in.n_audio () == 0) {
|
||||||
|
in += aux_in;
|
||||||
|
aux_in.reset ();
|
||||||
|
}
|
||||||
|
|
||||||
|
const int32_t audio_in = in.n_audio();
|
||||||
|
const int32_t audio_out = out.n_audio();
|
||||||
|
assert (in.n_audio () > 0);
|
||||||
|
|
||||||
if (initialized) {
|
if (initialized) {
|
||||||
//if we are already running with the requested i/o config, bail out here
|
/* if we are already running with the requested i/o config, bail out here */
|
||||||
if ( (audio_in==input_channels) && (audio_out==output_channels) ) {
|
if ((audio_in + aux_in.n_audio () == input_channels) && (audio_out == output_channels)) {
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
deactivate ();
|
deactivate ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
streamFormat.mSampleRate = _session.sample_rate();
|
streamFormat.mSampleRate = _session.sample_rate();
|
||||||
streamFormat.mFormatID = kAudioFormatLinearPCM;
|
streamFormat.mFormatID = kAudioFormatLinearPCM;
|
||||||
streamFormat.mFormatFlags = kAudioFormatFlagIsFloat|kAudioFormatFlagIsPacked|kAudioFormatFlagIsNonInterleaved;
|
streamFormat.mFormatFlags = kAudioFormatFlagIsFloat|kAudioFormatFlagIsPacked|kAudioFormatFlagIsNonInterleaved;
|
||||||
|
|
||||||
#ifdef __LITTLE_ENDIAN__
|
#ifdef __LITTLE_ENDIAN__
|
||||||
|
|
@ -1128,13 +1142,15 @@ AUPlugin::reconfigure_io (ChanCount in, ChanCount out)
|
||||||
streamFormat.mBytesPerPacket = 4;
|
streamFormat.mBytesPerPacket = 4;
|
||||||
streamFormat.mBytesPerFrame = 4;
|
streamFormat.mBytesPerFrame = 4;
|
||||||
|
|
||||||
configured_input_busses = 0;
|
configured_input_busses = 0;
|
||||||
configured_output_busses = 0;
|
configured_output_busses = 0;
|
||||||
|
|
||||||
/* reset busses */
|
/* reset busses */
|
||||||
for (size_t i = 0; i < output_elements; ++i) {
|
for (size_t i = 0; i < output_elements; ++i) {
|
||||||
unit->Reset (kAudioUnitScope_Output, i);
|
unit->Reset (kAudioUnitScope_Output, i);
|
||||||
}
|
}
|
||||||
for (size_t i = 0; i < input_elements; ++i) {
|
for (size_t i = 0; i < input_elements; ++i) {
|
||||||
|
bus_inused[i] = 0;
|
||||||
unit->Reset (kAudioUnitScope_Input, i);
|
unit->Reset (kAudioUnitScope_Input, i);
|
||||||
/* remove any input callbacks */
|
/* remove any input callbacks */
|
||||||
AURenderCallbackStruct renderCallbackInfo;
|
AURenderCallbackStruct renderCallbackInfo;
|
||||||
|
|
@ -1147,32 +1163,62 @@ AUPlugin::reconfigure_io (ChanCount in, ChanCount out)
|
||||||
uint32_t used_in = 0;
|
uint32_t used_in = 0;
|
||||||
uint32_t used_out = 0;
|
uint32_t used_out = 0;
|
||||||
|
|
||||||
if (variable_inputs || input_elements == 1) {
|
if (input_elements == 0) {
|
||||||
// we only ever use the first bus
|
configured_input_busses = 0;
|
||||||
if (input_elements > 1) {
|
} else if (variable_inputs || input_elements == 1 || audio_in < bus_inputs[0]) {
|
||||||
warning << string_compose (_("AU %1 has multiple input busses and variable port count."), name()) << endmsg;
|
/* we only ever use the first bus and configure it to match */
|
||||||
|
if (variable_inputs && input_elements > 1) {
|
||||||
|
info << string_compose (_("AU %1 has multiple input busses and variable port count."), name()) << endmsg;
|
||||||
}
|
}
|
||||||
streamFormat.mChannelsPerFrame = audio_in;
|
streamFormat.mChannelsPerFrame = audio_in;
|
||||||
if (set_stream_format (kAudioUnitScope_Input, 0, streamFormat) != 0) {
|
if (set_stream_format (kAudioUnitScope_Input, 0, streamFormat) != 0) {
|
||||||
|
warning << string_compose (_("AU %1 failed to reconfigure input: %2"), name(), audio_in) << endmsg;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
bus_inused[0] = audio_in;
|
||||||
configured_input_busses = 1;
|
configured_input_busses = 1;
|
||||||
used_in = audio_in;
|
used_in = audio_in;
|
||||||
} else {
|
} else {
|
||||||
|
/* more inputs than the first bus' channel-count: distribute sequentially */
|
||||||
configured_input_busses = 0;
|
configured_input_busses = 0;
|
||||||
uint32_t remain = audio_in;
|
uint32_t remain = audio_in + aux_in.n_audio ();
|
||||||
|
aux_in.reset (); /* now taken care of */
|
||||||
for (uint32_t bus = 0; remain > 0 && bus < input_elements; ++bus) {
|
for (uint32_t bus = 0; remain > 0 && bus < input_elements; ++bus) {
|
||||||
uint32_t cnt = std::min (remain, bus_inputs[bus]);
|
uint32_t cnt = std::min (remain, bus_inputs[bus]);
|
||||||
if (cnt == 0) { continue; }
|
|
||||||
DEBUG_TRACE (DEBUG::AudioUnitConfig, string_compose ("%1 configure input bus: %2 chn: %3", name(), bus, cnt));
|
DEBUG_TRACE (DEBUG::AudioUnitConfig, string_compose ("%1 configure input bus: %2 chn: %3", name(), bus, cnt));
|
||||||
|
|
||||||
streamFormat.mChannelsPerFrame = cnt;
|
streamFormat.mChannelsPerFrame = cnt;
|
||||||
if (set_stream_format (kAudioUnitScope_Input, bus, streamFormat) != 0) {
|
if (set_stream_format (kAudioUnitScope_Input, bus, streamFormat) != 0) {
|
||||||
return false;
|
if (cnt > 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
bus_inused[bus] = cnt;
|
||||||
used_in += cnt;
|
used_in += cnt;
|
||||||
++configured_input_busses;
|
|
||||||
remain -= cnt;
|
remain -= cnt;
|
||||||
|
if (cnt == 0) { continue; }
|
||||||
|
++configured_input_busses;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* add additional busses, connect aux-inputs */
|
||||||
|
if (configured_input_busses == 1 && aux_in.n_audio () > 0 && input_elements > 1) {
|
||||||
|
uint32_t remain = aux_in.n_audio ();
|
||||||
|
for (uint32_t bus = 1; remain > 0 && bus < input_elements; ++bus) {
|
||||||
|
uint32_t cnt = std::min (remain, bus_inputs[bus]);
|
||||||
|
DEBUG_TRACE (DEBUG::AudioUnitConfig, string_compose ("%1 configure aux input bus: %2 chn: %3", name(), bus, cnt));
|
||||||
|
|
||||||
|
streamFormat.mChannelsPerFrame = cnt;
|
||||||
|
if (set_stream_format (kAudioUnitScope_Input, bus, streamFormat) != 0) {
|
||||||
|
if (cnt > 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bus_inused[bus] = cnt;
|
||||||
|
used_in += cnt;
|
||||||
|
remain -= cnt;
|
||||||
|
if (cnt == 0) { continue; }
|
||||||
|
++configured_input_busses;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1183,6 +1229,7 @@ AUPlugin::reconfigure_io (ChanCount in, ChanCount out)
|
||||||
|
|
||||||
streamFormat.mChannelsPerFrame = audio_out;
|
streamFormat.mChannelsPerFrame = audio_out;
|
||||||
if (set_stream_format (kAudioUnitScope_Output, 0, streamFormat) != 0) {
|
if (set_stream_format (kAudioUnitScope_Output, 0, streamFormat) != 0) {
|
||||||
|
warning << string_compose (_("AU %1 failed to reconfigure output: %2"), name(), audio_out) << endmsg;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
configured_output_busses = 1;
|
configured_output_busses = 1;
|
||||||
|
|
@ -1213,21 +1260,23 @@ AUPlugin::reconfigure_io (ChanCount in, ChanCount out)
|
||||||
OSErr err;
|
OSErr err;
|
||||||
if ((err = unit->SetProperty (kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input,
|
if ((err = unit->SetProperty (kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input,
|
||||||
i, (void*) &renderCallbackInfo, sizeof(renderCallbackInfo))) != 0) {
|
i, (void*) &renderCallbackInfo, sizeof(renderCallbackInfo))) != 0) {
|
||||||
error << string_compose (_("cannot install render callback (err = %1)"), err) << endmsg;
|
error << string_compose (_("AU: %1 cannot install render callback (err = %2)"), name(), err) << endmsg;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
free (buffers);
|
free (buffers);
|
||||||
buffers = (AudioBufferList *) malloc (offsetof(AudioBufferList, mBuffers) +
|
buffers = (AudioBufferList *) malloc (offsetof(AudioBufferList, mBuffers) + used_out * sizeof(::AudioBuffer));
|
||||||
used_out * sizeof(::AudioBuffer));
|
|
||||||
|
|
||||||
input_channels = used_in;
|
input_channels = used_in;
|
||||||
output_channels = used_out;
|
output_channels = used_out;
|
||||||
/* reset plugin info to show currently configured state */
|
|
||||||
|
|
||||||
|
/* reset plugin info to show currently configured state */
|
||||||
_info->n_inputs = ChanCount (DataType::AUDIO, used_in) + ChanCount (DataType::MIDI, _has_midi_input ? 1 : 0);
|
_info->n_inputs = ChanCount (DataType::AUDIO, used_in) + ChanCount (DataType::MIDI, _has_midi_input ? 1 : 0);
|
||||||
_info->n_outputs = ChanCount (DataType::AUDIO, used_out);
|
_info->n_outputs = ChanCount (DataType::AUDIO, used_out);
|
||||||
|
|
||||||
|
DEBUG_TRACE (DEBUG::AudioUnitConfig, string_compose ("AUPlugin::configured %1 used-in: %2 used-out %3, in-bus: %4 out-bus: %5, I/O %6 %7\n",
|
||||||
|
name(), used_in, used_out, configured_input_busses, configured_output_busses, _info->n_inputs, _info->n_outputs));
|
||||||
|
|
||||||
if (was_initialized) {
|
if (was_initialized) {
|
||||||
activate ();
|
activate ();
|
||||||
}
|
}
|
||||||
|
|
@ -1267,49 +1316,33 @@ AUPlugin::output_streams() const
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
AUPlugin::match_variable_io (const ChanCount& in, ChanCount& out, ChanCount* imprecise)
|
AUPlugin::match_variable_io (ChanCount& in, ChanCount& aux_in, ChanCount& out)
|
||||||
{
|
{
|
||||||
_output_configs.clear ();
|
_output_configs.clear ();
|
||||||
const int32_t audio_in = in.n_audio();
|
|
||||||
|
/* if the plugin has no input busses, treat side-chain as normal input */
|
||||||
|
const int32_t audio_in = in.n_audio() + ((input_elements == 1) ? aux_in.n_audio() : 0);
|
||||||
|
/* preferred setting (provided by plugin_insert) */
|
||||||
|
const int32_t preferred_out = out.n_audio ();
|
||||||
|
|
||||||
AUPluginInfoPtr pinfo = boost::dynamic_pointer_cast<AUPluginInfo>(get_info());
|
AUPluginInfoPtr pinfo = boost::dynamic_pointer_cast<AUPluginInfo>(get_info());
|
||||||
|
|
||||||
/* lets check MIDI first */
|
|
||||||
|
|
||||||
if (in.n_midi() > 0 && !_has_midi_input && !imprecise) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
vector<pair<int,int> > io_configs = pinfo->cache.io_configs;
|
vector<pair<int,int> > io_configs = pinfo->cache.io_configs;
|
||||||
|
|
||||||
#if 0
|
#ifndef NDEBUG
|
||||||
printf ("AU I/O Initial Config list for '%s' (%zu) n_in-bus: %d n_out-bus: %d\n", name(), io_configs.size(), input_elements, output_elements);
|
if (DEBUG_ENABLED(DEBUG::AudioUnitConfig)) {
|
||||||
for (vector<pair<int,int> >::iterator i = io_configs.begin(); i != io_configs.end(); ++i) {
|
DEBUG_STR_DECL(a);
|
||||||
printf ("- I/O %d / %d\n", i->first, i->second);
|
DEBUG_STR_APPEND(a, string_compose ("AU Initial I/O Config list for %1 n_cfg: %2, in-bus %4 out-bus: %5\n", name(), io_configs.size(), input_elements, output_elements));
|
||||||
|
for (vector<pair<int,int> >::iterator i = io_configs.begin(); i != io_configs.end(); ++i) {
|
||||||
|
DEBUG_STR_APPEND(a, string_compose (" - I/O %1 / %2\n", i->first, i->second));
|
||||||
|
}
|
||||||
|
DEBUG_TRACE (DEBUG::AudioUnitConfig, DEBUG_STR(a).str());
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (input_elements > 1) {
|
/* add output busses as sum to possible outputs */
|
||||||
const vector<pair<int,int> >& ioc (pinfo->cache.io_configs);
|
#ifndef NDEBUG
|
||||||
for (vector<pair<int,int> >::const_iterator i = ioc.begin(); i != ioc.end(); ++i) {
|
bool outs_added = false;
|
||||||
int32_t possible_in = i->first;
|
#endif
|
||||||
int32_t possible_out = i->second;
|
|
||||||
if (possible_in < 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
for (uint32_t i = 1; i < input_elements; ++i) {
|
|
||||||
// can't use up-to bus_inputs[]
|
|
||||||
// waves' SC-C6(s) for example fails to configure with only 1 input
|
|
||||||
// on the 2nd bus.
|
|
||||||
io_configs.push_back (pair<int,int> (possible_in + bus_inputs[i], possible_out));
|
|
||||||
}
|
|
||||||
/* only add additional, optional busses to first available config.
|
|
||||||
* AUPluginInfo::cached_io_configuration () already incrementally
|
|
||||||
* adds busses (for instruments w/ multiple configurations)
|
|
||||||
*/
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (output_elements > 1) {
|
if (output_elements > 1) {
|
||||||
const vector<pair<int,int> >& ioc (pinfo->cache.io_configs);
|
const vector<pair<int,int> >& ioc (pinfo->cache.io_configs);
|
||||||
for (vector<pair<int,int> >::const_iterator i = ioc.begin(); i != ioc.end(); ++i) {
|
for (vector<pair<int,int> >::const_iterator i = ioc.begin(); i != ioc.end(); ++i) {
|
||||||
|
|
@ -1325,6 +1358,9 @@ AUPlugin::match_variable_io (const ChanCount& in, ChanCount& out, ChanCount* imp
|
||||||
}
|
}
|
||||||
io_configs.push_back (pair<int,int> (possible_in, possible_out + c));
|
io_configs.push_back (pair<int,int> (possible_in, possible_out + c));
|
||||||
}
|
}
|
||||||
|
#ifndef NDEBUG
|
||||||
|
outs_added = true;
|
||||||
|
#endif
|
||||||
/* only add additional, optional busses to first available config.
|
/* only add additional, optional busses to first available config.
|
||||||
* AUPluginInfo::cached_io_configuration () already incrementally
|
* AUPluginInfo::cached_io_configuration () already incrementally
|
||||||
* adds busses (for instruments w/ multiple configurations)
|
* adds busses (for instruments w/ multiple configurations)
|
||||||
|
|
@ -1333,19 +1369,19 @@ AUPlugin::match_variable_io (const ChanCount& in, ChanCount& out, ChanCount* imp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUG_TRACE (DEBUG::AudioUnitConfig, string_compose ("%1 has %2 IO configurations, looking for %3 in, %4 out\n",
|
DEBUG_TRACE (DEBUG::AudioUnitConfig, string_compose ("%1 has %2 IO configurations, looking for in: %3 aux: %4 out: %5\n", name(), io_configs.size(), in, aux_in, out));
|
||||||
name(), io_configs.size(), in, out));
|
|
||||||
|
|
||||||
#if 0
|
#ifndef NDEBUG
|
||||||
printf ("AU I/O Config list for '%s' (%zu)\n", name(), io_configs.size());
|
if (DEBUG_ENABLED(DEBUG::AudioUnitConfig) && outs_added) {
|
||||||
for (vector<pair<int,int> >::iterator i = io_configs.begin(); i != io_configs.end(); ++i) {
|
DEBUG_STR_DECL(a);
|
||||||
printf ("- I/O %d / %d\n", i->first, i->second);
|
DEBUG_STR_APPEND(a, string_compose ("AU Final I/O Config list for %1 n_cfg: %2\n", name(), io_configs.size()));
|
||||||
|
for (vector<pair<int,int> >::iterator i = io_configs.begin(); i != io_configs.end(); ++i) {
|
||||||
|
DEBUG_STR_APPEND(a, string_compose (" - I/O %1 / %2\n", i->first, i->second));
|
||||||
|
}
|
||||||
|
DEBUG_TRACE (DEBUG::AudioUnitConfig, DEBUG_STR(a).str());
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// preferred setting (provided by plugin_insert)
|
|
||||||
const int32_t preferred_out = out.n_audio ();
|
|
||||||
|
|
||||||
/* kAudioUnitProperty_SupportedNumChannels
|
/* kAudioUnitProperty_SupportedNumChannels
|
||||||
* https://developer.apple.com/library/mac/documentation/MusicAudio/Conceptual/AudioUnitProgrammingGuide/TheAudioUnit/TheAudioUnit.html#//apple_ref/doc/uid/TP40003278-CH12-SW20
|
* https://developer.apple.com/library/mac/documentation/MusicAudio/Conceptual/AudioUnitProgrammingGuide/TheAudioUnit/TheAudioUnit.html#//apple_ref/doc/uid/TP40003278-CH12-SW20
|
||||||
*
|
*
|
||||||
|
|
@ -1376,51 +1412,45 @@ AUPlugin::match_variable_io (const ChanCount& in, ChanCount& out, ChanCount* imp
|
||||||
float penalty = 9999;
|
float penalty = 9999;
|
||||||
int32_t used_possible_in = 0;
|
int32_t used_possible_in = 0;
|
||||||
bool found = false;
|
bool found = false;
|
||||||
|
|
||||||
#if defined (__clang__)
|
#if defined (__clang__)
|
||||||
# pragma clang diagnostic push
|
# pragma clang diagnostic push
|
||||||
# pragma clang diagnostic ignored "-Wtautological-compare"
|
# pragma clang diagnostic ignored "-Wtautological-compare"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define FOUNDCFG_PENALTY(in, out, p) { \
|
#define FOUNDCFG_PENALTY(n_in, n_out, p) { \
|
||||||
_output_configs.insert (out); \
|
_output_configs.insert (n_out); \
|
||||||
if (p < penalty) { \
|
if (p < penalty) { \
|
||||||
used_possible_in = possible_in; \
|
used_possible_in = possible_in; \
|
||||||
audio_out = (out); \
|
audio_out = (n_out); \
|
||||||
if (imprecise) { \
|
in.set (DataType::AUDIO, (n_in)); \
|
||||||
imprecise->set (DataType::AUDIO, (in)); \
|
penalty = p; \
|
||||||
} \
|
found = true; \
|
||||||
penalty = p; \
|
variable_inputs = possible_in < 0; \
|
||||||
found = true; \
|
variable_outputs = possible_out < 0; \
|
||||||
variable_inputs = possible_in < 0; \
|
} \
|
||||||
variable_outputs = possible_out < 0; \
|
|
||||||
} \
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define FOUNDCFG_IMPRECISE(in, out) { \
|
#define FOUNDCFG_IMPRECISE(n_in, n_out) { \
|
||||||
const float p = \
|
const float p = fabsf ((float)(n_out) - preferred_out) * \
|
||||||
fabsf ((float)(out) - preferred_out) * \
|
(((n_out) > preferred_out) ? 1.1 : 1) \
|
||||||
(((out) > preferred_out) ? 1.1 : 1) \
|
+ fabsf ((float)(n_in) - audio_in) * \
|
||||||
+ fabsf ((float)(in) - audio_in) * \
|
(((n_in) > audio_in) ? 275 : 250); \
|
||||||
(((in) > audio_in) ? 275 : 250); \
|
FOUNDCFG_PENALTY(n_in, n_out, p); \
|
||||||
FOUNDCFG_PENALTY(in, out, p); \
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define FOUNDCFG(out) \
|
#define FOUNDCFG(n_out) \
|
||||||
FOUNDCFG_IMPRECISE(audio_in, out)
|
FOUNDCFG_IMPRECISE(audio_in, n_out)
|
||||||
|
|
||||||
#define ANYTHINGGOES \
|
#define ANYTHINGGOES \
|
||||||
_output_configs.insert (0);
|
_output_configs.insert (0);
|
||||||
|
|
||||||
#define UPTO(nch) { \
|
#define UPTO(nch) { \
|
||||||
for (int32_t n = 1; n <= nch; ++n) { \
|
for (int32_t n = 1; n <= nch; ++n) { \
|
||||||
_output_configs.insert (n); \
|
_output_configs.insert (n); \
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
if (imprecise) {
|
|
||||||
*imprecise = in;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (vector<pair<int,int> >::iterator i = io_configs.begin(); i != io_configs.end(); ++i) {
|
for (vector<pair<int,int> >::iterator i = io_configs.begin(); i != io_configs.end(); ++i) {
|
||||||
|
|
||||||
int32_t possible_in = i->first;
|
int32_t possible_in = i->first;
|
||||||
|
|
@ -1478,11 +1508,7 @@ AUPlugin::match_variable_io (const ChanCount& in, ChanCount& out, ChanCount* imp
|
||||||
/* configuration can match up to -possible_in */
|
/* configuration can match up to -possible_in */
|
||||||
desired_in = min (-possible_in, audio_in);
|
desired_in = min (-possible_in, audio_in);
|
||||||
}
|
}
|
||||||
if (!imprecise && audio_in != desired_in) {
|
if (possible_out == -1 || possible_out == -2) {
|
||||||
/* skip that configuration, it cannot match
|
|
||||||
* the required audio input count, and we
|
|
||||||
* cannot ask for change via \imprecise */
|
|
||||||
} else if (possible_out == -1 || possible_out == -2) {
|
|
||||||
/* any output configuration possible
|
/* any output configuration possible
|
||||||
* out == -2 is invalid, interpreted as out == -1
|
* out == -2 is invalid, interpreted as out == -1
|
||||||
* Really imprecise only if desired_in != audio_in */
|
* Really imprecise only if desired_in != audio_in */
|
||||||
|
|
@ -1508,14 +1534,28 @@ AUPlugin::match_variable_io (const ChanCount& in, ChanCount& out, ChanCount* imp
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (used_possible_in < -2 && audio_in == 0) {
|
if (used_possible_in < -2 && audio_in == 0 && aux_in.n_audio () == 0) {
|
||||||
// input-port count cannot be zero, use as many ports
|
/* input-port count cannot be zero, use as many ports
|
||||||
// as outputs, but at most abs(possible_in)
|
* as outputs, but at most abs(possible_in) */
|
||||||
audio_input_cnt = max (1, min (audio_out, -used_possible_in));
|
uint32_t n_in = max (1, min (audio_out, -used_possible_in));
|
||||||
|
in.set (DataType::AUDIO, n_in);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
if (aux_in.n_audio () > 0 && input_elements > 1) {
|
||||||
|
in.set (DataType::AUDIO, in.n_audio() + aux_in.n_audio());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
out.set (DataType::MIDI, 0); /// XXX currently always zero
|
out.set (DataType::MIDI, 0); /// XXX currently always zero
|
||||||
out.set (DataType::AUDIO, audio_out);
|
out.set (DataType::AUDIO, audio_out);
|
||||||
DEBUG_TRACE (DEBUG::AudioUnitConfig, string_compose ("\tCHOSEN: in %1 out %2\n", in, out));
|
|
||||||
|
if (input_elements == 1) {
|
||||||
|
/* subtract aux-ins that were treated as default inputs */
|
||||||
|
in.set (DataType::AUDIO, in.n_audio() - aux_in.n_audio());
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUG_TRACE (DEBUG::AudioUnitConfig, string_compose ("\tCHOSEN: in: %1 aux-in: %2 out: %3\n", in, aux_in, out));
|
||||||
|
|
||||||
#if defined (__clang__)
|
#if defined (__clang__)
|
||||||
# pragma clang diagnostic pop
|
# pragma clang diagnostic pop
|
||||||
|
|
@ -1559,7 +1599,7 @@ AUPlugin::render_callback(AudioUnitRenderActionFlags*,
|
||||||
assert (bus < input_elements);
|
assert (bus < input_elements);
|
||||||
uint32_t busoff = 0;
|
uint32_t busoff = 0;
|
||||||
for (uint32_t i = 0; i < bus; ++i) {
|
for (uint32_t i = 0; i < bus; ++i) {
|
||||||
busoff += bus_inputs[i];
|
busoff += bus_inused[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t limit = min ((uint32_t) ioData->mNumberBuffers, input_maxbuf);
|
uint32_t limit = min ((uint32_t) ioData->mNumberBuffers, input_maxbuf);
|
||||||
|
|
@ -1929,19 +1969,22 @@ AUPlugin::describe_io_port (ARDOUR::DataType dt, bool input, uint32_t id) const
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string busname;
|
std::string busname;
|
||||||
|
bool is_sidechain = false;
|
||||||
|
|
||||||
if (dt == DataType::AUDIO) {
|
if (dt == DataType::AUDIO) {
|
||||||
if (input) {
|
if (input) {
|
||||||
uint32_t pid = id;
|
uint32_t pid = id;
|
||||||
for (uint32_t bus = 0; bus < input_elements; ++bus) {
|
for (uint32_t bus = 0; bus < input_elements; ++bus) {
|
||||||
if (pid < bus_inputs[bus]) {
|
if (pid < bus_inused[bus]) {
|
||||||
id = pid;
|
id = pid;
|
||||||
ss << _bus_name_in[bus];
|
ss << _bus_name_in[bus];
|
||||||
ss << " / Bus " << (1 + bus);
|
ss << " / Bus " << (1 + bus);
|
||||||
busname = _bus_name_in[bus];
|
busname = _bus_name_in[bus];
|
||||||
|
is_sidechain = bus > 0;
|
||||||
|
busname = _bus_name_in[bus];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
pid -= bus_inputs[bus];
|
pid -= bus_inused[bus];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
@ -1968,6 +2011,7 @@ AUPlugin::describe_io_port (ARDOUR::DataType dt, bool input, uint32_t id) const
|
||||||
ss << (id + 1);
|
ss << (id + 1);
|
||||||
|
|
||||||
Plugin::IOPortDescription iod (ss.str());
|
Plugin::IOPortDescription iod (ss.str());
|
||||||
|
iod.is_sidechain = is_sidechain;
|
||||||
if (!busname.empty()) {
|
if (!busname.empty()) {
|
||||||
iod.group_name = busname;
|
iod.group_name = busname;
|
||||||
iod.group_channel = id;
|
iod.group_channel = id;
|
||||||
|
|
|
||||||
|
|
@ -394,9 +394,12 @@ LuaProc::load_script ()
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
LuaProc::match_variable_io (const ChanCount& in, ChanCount& out, ChanCount* imprecise)
|
LuaProc::match_variable_io (ChanCount& in, ChanCount& aux_in, ChanCount& out)
|
||||||
{
|
{
|
||||||
// caller must hold process lock (no concurrent calls to interpreter
|
/* Lua does not have dedicated sidechain busses */
|
||||||
|
in += aux_in;
|
||||||
|
|
||||||
|
/* caller must hold process lock (no concurrent calls to interpreter */
|
||||||
_output_configs.clear ();
|
_output_configs.clear ();
|
||||||
|
|
||||||
lua_State* L = lua.getState ();
|
lua_State* L = lua.getState ();
|
||||||
|
|
@ -445,50 +448,44 @@ LuaProc::match_variable_io (const ChanCount& in, ChanCount& out, ChanCount* impr
|
||||||
float penalty = 9999;
|
float penalty = 9999;
|
||||||
bool found = false;
|
bool found = false;
|
||||||
|
|
||||||
#define FOUNDCFG_PENALTY(in, out, p) { \
|
#define FOUNDCFG_PENALTY(n_in, n_out, p) { \
|
||||||
_output_configs.insert (out); \
|
_output_configs.insert (n_out); \
|
||||||
if (p < penalty) { \
|
if (p < penalty) { \
|
||||||
audio_out = (out); \
|
audio_out = (n_out); \
|
||||||
midi_out = possible_midiout; \
|
midi_out = possible_midiout; \
|
||||||
if (imprecise) { \
|
in.set (DataType::AUDIO, (n_in)); \
|
||||||
imprecise->set (DataType::AUDIO, (in)); \
|
in.set (DataType::MIDI, possible_midiin); \
|
||||||
imprecise->set (DataType::MIDI, possible_midiin); \
|
_has_midi_input = (possible_midiin > 0); \
|
||||||
} \
|
_has_midi_output = (possible_midiout > 0); \
|
||||||
_has_midi_input = (possible_midiin > 0); \
|
penalty = p; \
|
||||||
_has_midi_output = (possible_midiout > 0); \
|
found = true; \
|
||||||
penalty = p; \
|
} \
|
||||||
found = true; \
|
|
||||||
} \
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define FOUNDCFG_IMPRECISE(in, out) { \
|
#define FOUNDCFG_IMPRECISE(n_in, n_out) { \
|
||||||
const float p = fabsf ((float)(out) - preferred_out) * \
|
const float p = fabsf ((float)(n_out) - preferred_out) * \
|
||||||
(((out) > preferred_out) ? 1.1 : 1) \
|
(((n_out) > preferred_out) ? 1.1 : 1) \
|
||||||
+ fabsf ((float)possible_midiout - preferred_midiout) * \
|
+ fabsf ((float)possible_midiout - preferred_midiout) * \
|
||||||
((possible_midiout - preferred_midiout) ? 0.6 : 0.5) \
|
((possible_midiout - preferred_midiout) ? 0.6 : 0.5) \
|
||||||
+ fabsf ((float)(in) - audio_in) * \
|
+ fabsf ((float)(n_in) - audio_in) * \
|
||||||
(((in) > audio_in) ? 275 : 250) \
|
(((n_in) > audio_in) ? 275 : 250) \
|
||||||
+ fabsf ((float)possible_midiin - midi_in) * \
|
+ fabsf ((float)possible_midiin - midi_in) * \
|
||||||
((possible_midiin - midi_in) ? 100 : 110); \
|
((possible_midiin - midi_in) ? 100 : 110); \
|
||||||
FOUNDCFG_PENALTY(in, out, p); \
|
FOUNDCFG_PENALTY(n_in, n_out, p); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define FOUNDCFG(out) \
|
#define FOUNDCFG(n_out) \
|
||||||
FOUNDCFG_IMPRECISE(audio_in, out)
|
FOUNDCFG_IMPRECISE(audio_in, n_out)
|
||||||
|
|
||||||
#define ANYTHINGGOES \
|
#define ANYTHINGGOES \
|
||||||
_output_configs.insert (0);
|
_output_configs.insert (0);
|
||||||
|
|
||||||
#define UPTO(nch) { \
|
#define UPTO(nch) { \
|
||||||
for (int n = 1; n < nch; ++n) { \
|
for (int n = 1; n < nch; ++n) { \
|
||||||
_output_configs.insert (n); \
|
_output_configs.insert (n); \
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
if (imprecise) {
|
|
||||||
*imprecise = in;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (luabridge::Iterator i (iotable); !i.isNil (); ++i) {
|
for (luabridge::Iterator i (iotable); !i.isNil (); ++i) {
|
||||||
luabridge::LuaRef io (i.value ());
|
luabridge::LuaRef io (i.value ());
|
||||||
if (!io.isTable()) {
|
if (!io.isTable()) {
|
||||||
|
|
@ -500,10 +497,6 @@ LuaProc::match_variable_io (const ChanCount& in, ChanCount& out, ChanCount* impr
|
||||||
int possible_midiin = io["midi_in"].isNumber() ? io["midi_in"] : 0;
|
int possible_midiin = io["midi_in"].isNumber() ? io["midi_in"] : 0;
|
||||||
int possible_midiout = io["midi_out"].isNumber() ? io["midi_out"] : 0;
|
int possible_midiout = io["midi_out"].isNumber() ? io["midi_out"] : 0;
|
||||||
|
|
||||||
if (midi_in != possible_midiin && !imprecise) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// exact match
|
// exact match
|
||||||
if ((possible_in == audio_in) && (possible_out == preferred_out)) {
|
if ((possible_in == audio_in) && (possible_out == preferred_out)) {
|
||||||
/* Set penalty so low that this output configuration
|
/* Set penalty so low that this output configuration
|
||||||
|
|
@ -548,11 +541,7 @@ LuaProc::match_variable_io (const ChanCount& in, ChanCount& out, ChanCount* impr
|
||||||
/* configuration can match up to -possible_in */
|
/* configuration can match up to -possible_in */
|
||||||
desired_in = std::min (-possible_in, audio_in);
|
desired_in = std::min (-possible_in, audio_in);
|
||||||
}
|
}
|
||||||
if (!imprecise && audio_in != desired_in) {
|
if (possible_out == -1 || possible_out == -2) {
|
||||||
/* skip that configuration, it cannot match
|
|
||||||
* the required audio input count, and we
|
|
||||||
* cannot ask for change via \imprecise */
|
|
||||||
} else if (possible_out == -1 || possible_out == -2) {
|
|
||||||
/* any output configuration possible
|
/* any output configuration possible
|
||||||
* out == -2 is invalid, interpreted as out == -1.
|
* out == -2 is invalid, interpreted as out == -1.
|
||||||
* Really imprecise only if desired_in != audio_in */
|
* Really imprecise only if desired_in != audio_in */
|
||||||
|
|
@ -577,22 +566,24 @@ LuaProc::match_variable_io (const ChanCount& in, ChanCount& out, ChanCount* impr
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (imprecise) {
|
|
||||||
_selected_in = *imprecise;
|
|
||||||
} else {
|
|
||||||
_selected_in = in;
|
|
||||||
}
|
|
||||||
|
|
||||||
out.set (DataType::MIDI, midi_out);
|
out.set (DataType::MIDI, midi_out);
|
||||||
out.set (DataType::AUDIO, audio_out);
|
out.set (DataType::AUDIO, audio_out);
|
||||||
|
|
||||||
|
_selected_in = in;
|
||||||
_selected_out = out;
|
_selected_out = out;
|
||||||
|
|
||||||
|
/* restore side-chain input count */
|
||||||
|
in -= aux_in;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
LuaProc::reconfigure_io (ChanCount in, ChanCount out)
|
LuaProc::reconfigure_io (ChanCount in, ChanCount out, ChanCount aux_in)
|
||||||
{
|
{
|
||||||
|
in += aux_in;
|
||||||
|
assert (in == _selected_in && out ==_selected_out);
|
||||||
|
|
||||||
in.set (DataType::MIDI, _has_midi_input ? 1 : 0);
|
in.set (DataType::MIDI, _has_midi_input ? 1 : 0);
|
||||||
out.set (DataType::MIDI, _has_midi_output ? 1 : 0);
|
out.set (DataType::MIDI, _has_midi_output ? 1 : 0);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -441,8 +441,9 @@ bool
|
||||||
PluginInsert::has_output_presets (ChanCount in, ChanCount out)
|
PluginInsert::has_output_presets (ChanCount in, ChanCount out)
|
||||||
{
|
{
|
||||||
if (!_configured && _plugins[0]->get_info ()->reconfigurable_io ()) {
|
if (!_configured && _plugins[0]->get_info ()->reconfigurable_io ()) {
|
||||||
// collect possible configurations, prefer given in/out
|
/* collect possible configurations, prefer given in/out */
|
||||||
_plugins[0]->match_variable_io (in, out);
|
ChanCount aux_in;
|
||||||
|
_plugins[0]->match_variable_io (in, aux_in, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
PluginOutputConfiguration ppc (_plugins[0]->possible_output ());
|
PluginOutputConfiguration ppc (_plugins[0]->possible_output ());
|
||||||
|
|
@ -1916,6 +1917,8 @@ PluginInsert::configure_io (ChanCount in, ChanCount out)
|
||||||
_configured_internal = in;
|
_configured_internal = in;
|
||||||
_configured_out = out;
|
_configured_out = out;
|
||||||
|
|
||||||
|
ChanCount aux_in;
|
||||||
|
|
||||||
if (_sidechain) {
|
if (_sidechain) {
|
||||||
/* TODO hide midi-bypass, and custom outs. Best /fake/ "out" here.
|
/* TODO hide midi-bypass, and custom outs. Best /fake/ "out" here.
|
||||||
* (currently _sidechain->configure_io always succeeds
|
* (currently _sidechain->configure_io always succeeds
|
||||||
|
|
@ -1926,13 +1929,14 @@ PluginInsert::configure_io (ChanCount in, ChanCount out)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
_configured_internal += _sidechain->input()->n_ports();
|
_configured_internal += _sidechain->input()->n_ports();
|
||||||
|
aux_in = _sidechain->input()->n_ports();
|
||||||
|
|
||||||
// include (static_cast<Route*>owner())->name() ??
|
// include (static_cast<Route*>owner())->name() ??
|
||||||
_sidechain->input ()-> set_pretty_name (string_compose (_("SC %1"), name ()));
|
_sidechain->input ()-> set_pretty_name (string_compose (_("SC %1"), name ()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get plugin configuration */
|
/* get plugin configuration */
|
||||||
_match = private_can_support_io_configuration (in, out);
|
_match = private_can_support_io_configuration (in, out); // sets out
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
if (DEBUG_ENABLED(DEBUG::ChanMapping)) {
|
if (DEBUG_ENABLED(DEBUG::ChanMapping)) {
|
||||||
DEBUG_STR_DECL(a);
|
DEBUG_STR_DECL(a);
|
||||||
|
|
@ -1953,7 +1957,7 @@ PluginInsert::configure_io (ChanCount in, ChanCount out)
|
||||||
switch (_match.method) {
|
switch (_match.method) {
|
||||||
case Split:
|
case Split:
|
||||||
case Hide:
|
case Hide:
|
||||||
if (_plugins.front()->reconfigure_io (natural_input_streams(), out) == false) {
|
if (_plugins.front()->reconfigure_io (natural_input_streams(), ChanCount (), out) == false) {
|
||||||
PluginIoReConfigure (); /* EMIT SIGNAL */
|
PluginIoReConfigure (); /* EMIT SIGNAL */
|
||||||
_configured = false;
|
_configured = false;
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -1961,11 +1965,15 @@ PluginInsert::configure_io (ChanCount in, ChanCount out)
|
||||||
break;
|
break;
|
||||||
case Delegate:
|
case Delegate:
|
||||||
{
|
{
|
||||||
ChanCount din (_configured_internal);
|
ChanCount din (in);
|
||||||
ChanCount dout (din); // hint
|
ChanCount daux (aux_in);
|
||||||
|
ChanCount dout (_configured_out);
|
||||||
if (_custom_cfg) {
|
if (_custom_cfg) {
|
||||||
if (_custom_sinks.n_total () > 0) {
|
if (_custom_sinks.n_total () > 0) {
|
||||||
din = _custom_sinks;
|
din = std::min (natural_input_streams(), _custom_sinks);
|
||||||
|
if (_custom_sinks > natural_input_streams()) {
|
||||||
|
daux = _custom_sinks - din;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
dout = _custom_out;
|
dout = _custom_out;
|
||||||
} else if (_preset_out.n_audio () > 0) {
|
} else if (_preset_out.n_audio () > 0) {
|
||||||
|
|
@ -1973,17 +1981,12 @@ PluginInsert::configure_io (ChanCount in, ChanCount out)
|
||||||
} else if (dout.n_midi () > 0 && dout.n_audio () == 0) {
|
} else if (dout.n_midi () > 0 && dout.n_audio () == 0) {
|
||||||
dout.set (DataType::AUDIO, 2);
|
dout.set (DataType::AUDIO, 2);
|
||||||
}
|
}
|
||||||
if (out.n_audio () == 0) { out.set (DataType::AUDIO, 1); }
|
//if (dout.n_audio () == 0) { dout.set (DataType::AUDIO, 1); } // XXX why?
|
||||||
ChanCount useins;
|
DEBUG_TRACE (DEBUG::ChanMapping, string_compose ("%1: Delegate lookup: %2 %3 %4\n", name(), din, daux, dout));
|
||||||
DEBUG_TRACE (DEBUG::ChanMapping, string_compose ("%1: Delegate lookup : %2 %3\n", name(), din, dout));
|
bool const r = _plugins.front()->match_variable_io (din, daux, dout);
|
||||||
bool const r = _plugins.front()->match_variable_io (din, dout, &useins);
|
|
||||||
assert (r);
|
assert (r);
|
||||||
if (useins.n_audio() == 0) {
|
DEBUG_TRACE (DEBUG::ChanMapping, string_compose ("%1: Delegate configuration: %2 %3 %4\n", name(), din, daux, dout));
|
||||||
useins = din;
|
if (_plugins.front()->reconfigure_io (din, daux, dout) == false) {
|
||||||
}
|
|
||||||
DEBUG_TRACE (DEBUG::ChanMapping, string_compose ("%1: Delegate configuration: %2 %3\n", name(), useins, dout));
|
|
||||||
|
|
||||||
if (_plugins.front()->reconfigure_io (useins, dout) == false) {
|
|
||||||
PluginIoReConfigure (); /* EMIT SIGNAL */
|
PluginIoReConfigure (); /* EMIT SIGNAL */
|
||||||
_configured = false;
|
_configured = false;
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -1994,7 +1997,7 @@ PluginInsert::configure_io (ChanCount in, ChanCount out)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (_plugins.front()->reconfigure_io (in, out) == false) {
|
if (_plugins.front()->reconfigure_io (in, aux_in, out) == false) {
|
||||||
PluginIoReConfigure (); /* EMIT SIGNAL */
|
PluginIoReConfigure (); /* EMIT SIGNAL */
|
||||||
_configured = false;
|
_configured = false;
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -2257,11 +2260,14 @@ PluginInsert::internal_can_support_io_configuration (ChanCount const & inx, Chan
|
||||||
DEBUG_TRACE (DEBUG::ChanMapping, string_compose ("%1: resolving 'Impossible' match...\n", name()));
|
DEBUG_TRACE (DEBUG::ChanMapping, string_compose ("%1: resolving 'Impossible' match...\n", name()));
|
||||||
|
|
||||||
if (info->reconfigurable_io()) {
|
if (info->reconfigurable_io()) {
|
||||||
ChanCount useins;
|
//out = inx; // hint
|
||||||
out = inx; // hint
|
ChanCount main_in = inx;
|
||||||
if (out.n_midi () > 0 && out.n_audio () == 0) { out.set (DataType::AUDIO, 2); }
|
ChanCount aux_in = sidechain_input_pins ();
|
||||||
if (out.n_audio () == 0) { out.set (DataType::AUDIO, 1); }
|
if (out.n_midi () > 0 && out.n_audio () == 0) {
|
||||||
bool const r = _plugins.front()->match_variable_io (inx + sidechain_input_pins (), out, &useins);
|
out.set (DataType::AUDIO, 2);
|
||||||
|
}
|
||||||
|
//if (out.n_audio () == 0) { out.set (DataType::AUDIO, 1); } // why?
|
||||||
|
bool const r = _plugins.front()->match_variable_io (main_in, aux_in, out);
|
||||||
if (!r) {
|
if (!r) {
|
||||||
// houston, we have a problem.
|
// houston, we have a problem.
|
||||||
return Match (Impossible, 0);
|
return Match (Impossible, 0);
|
||||||
|
|
@ -2315,7 +2321,7 @@ PluginInsert::internal_can_support_io_configuration (ChanCount const & inx, Chan
|
||||||
|
|
||||||
/* this is the original Ardour 3/4 behavior, mainly for backwards compatibility */
|
/* this is the original Ardour 3/4 behavior, mainly for backwards compatibility */
|
||||||
PluginInsert::Match
|
PluginInsert::Match
|
||||||
PluginInsert::automatic_can_support_io_configuration (ChanCount const & inx, ChanCount& out) const
|
PluginInsert::automatic_can_support_io_configuration (ChanCount const& inx, ChanCount& out) const
|
||||||
{
|
{
|
||||||
if (_plugins.empty()) {
|
if (_plugins.empty()) {
|
||||||
return Match();
|
return Match();
|
||||||
|
|
@ -2329,10 +2335,11 @@ PluginInsert::automatic_can_support_io_configuration (ChanCount const & inx, Cha
|
||||||
/* Plugin has flexible I/O, so delegate to it
|
/* Plugin has flexible I/O, so delegate to it
|
||||||
* pre-seed outputs, plugin tries closest match
|
* pre-seed outputs, plugin tries closest match
|
||||||
*/
|
*/
|
||||||
out = in; // hint
|
//out = in; // hint
|
||||||
|
ChanCount aux_in = sidechain_input_pins ();
|
||||||
if (out.n_midi () > 0 && out.n_audio () == 0) { out.set (DataType::AUDIO, 2); }
|
if (out.n_midi () > 0 && out.n_audio () == 0) { out.set (DataType::AUDIO, 2); }
|
||||||
if (out.n_audio () == 0) { out.set (DataType::AUDIO, 1); }
|
if (out.n_audio () == 0) { out.set (DataType::AUDIO, 1); }
|
||||||
bool const r = _plugins.front()->match_variable_io (in + sidechain_input_pins (), out);
|
bool const r = _plugins.front()->match_variable_io (in, aux_in, out);
|
||||||
if (!r) {
|
if (!r) {
|
||||||
return Match (Impossible, 0);
|
return Match (Impossible, 0);
|
||||||
}
|
}
|
||||||
|
|
@ -3141,14 +3148,15 @@ PluginInsert::get_impulse_analysis_plugin()
|
||||||
// not great.
|
// not great.
|
||||||
ret = plugin_factory(_plugins[0]);
|
ret = plugin_factory(_plugins[0]);
|
||||||
ret->use_for_impulse_analysis ();
|
ret->use_for_impulse_analysis ();
|
||||||
|
ChanCount ins = internal_input_streams ();
|
||||||
ChanCount out (internal_output_streams ());
|
ChanCount out (internal_output_streams ());
|
||||||
|
ChanCount aux_in;
|
||||||
if (ret->get_info ()->reconfigurable_io ()) {
|
if (ret->get_info ()->reconfigurable_io ()) {
|
||||||
// populate get_info ()->n_inputs and ->n_outputs
|
// populate get_info ()->n_inputs and ->n_outputs
|
||||||
ChanCount useins;
|
ret->match_variable_io (ins, aux_in, out);
|
||||||
ret->match_variable_io (internal_input_streams (), out, &useins);
|
|
||||||
assert (out == internal_output_streams ());
|
assert (out == internal_output_streams ());
|
||||||
}
|
}
|
||||||
ret->reconfigure_io (internal_input_streams (), out);
|
ret->reconfigure_io (ins, aux_in, out);
|
||||||
ret->set_owner (_owner);
|
ret->set_owner (_owner);
|
||||||
_impulseAnalysisPlugin = ret;
|
_impulseAnalysisPlugin = ret;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue