disallow invalid port-removal
do not allow port-removal if the port would be re-added immediately after that again because the main-delivery actually needs it. As a side effect this prevents this crash: * create a stereo-track, then remove one output -> unhandled exception "AudioEngine::PortRegistrationFailure&" The problem: - the port is removed from the RCU ports list, but Port::drop() (which calls jack_port_unregister) is only called from the Port's destructor at some later time. (because a reference to the port still exists elsewhere) - the jack-port is not yet removed. - meanwhile Delivery::configure_io comes along and notices that there are more audio-buffers than ports and tries to re-register the port. - but the port still exists in jack, so it fails and throws an exception ...which is not handled.
This commit is contained in:
parent
94f366190e
commit
23eba1cc39
@ -733,7 +733,7 @@ PortMatrix::remove_channel (ARDOUR::BundleChannel b)
|
||||
int const r = io->remove_port (p, this);
|
||||
if (r == -1) {
|
||||
ArdourDialog d (_("Port removal not allowed"));
|
||||
Label l (_("This port cannot be removed, as the first plugin in the track or buss cannot accept the new number of inputs."));
|
||||
Label l (_("This port cannot be removed.\nEither the first plugin in the track or buss cannot accept\nthe new number of inputs or the last plugin has more outputs."));
|
||||
d.get_vbox()->pack_start (l);
|
||||
d.add_button (Stock::OK, RESPONSE_ACCEPT);
|
||||
d.set_modal (true);
|
||||
|
@ -530,6 +530,7 @@ class Route : public SessionObject, public Automatable, public RouteGroupMember,
|
||||
void silence_unlocked (framecnt_t);
|
||||
|
||||
ChanCount processor_max_streams;
|
||||
ChanCount processor_out_streams;
|
||||
|
||||
uint32_t pans_required() const;
|
||||
ChanCount n_process_buffers ();
|
||||
@ -553,6 +554,7 @@ class Route : public SessionObject, public Automatable, public RouteGroupMember,
|
||||
void output_change_handler (IOChange, void *src);
|
||||
|
||||
bool input_port_count_changing (ChanCount);
|
||||
bool output_port_count_changing (ChanCount);
|
||||
|
||||
bool _in_configure_processors;
|
||||
|
||||
|
@ -136,6 +136,7 @@ Route::init ()
|
||||
_input->PortCountChanging.connect_same_thread (*this, boost::bind (&Route::input_port_count_changing, this, _1));
|
||||
|
||||
_output->changed.connect_same_thread (*this, boost::bind (&Route::output_change_handler, this, _1, _2));
|
||||
_output->PortCountChanging.connect_same_thread (*this, boost::bind (&Route::output_port_count_changing, this, _1));
|
||||
|
||||
/* add amp processor */
|
||||
|
||||
@ -1704,6 +1705,8 @@ Route::configure_processors_unlocked (ProcessorStreams* err)
|
||||
}
|
||||
|
||||
ChanCount out;
|
||||
bool seen_mains_out = false;
|
||||
processor_out_streams = _input->n_ports();
|
||||
|
||||
list< pair<ChanCount,ChanCount> >::iterator c = configuration.begin();
|
||||
for (ProcessorList::iterator p = _processors.begin(); p != _processors.end(); ++p, ++c) {
|
||||
@ -1716,8 +1719,21 @@ Route::configure_processors_unlocked (ProcessorStreams* err)
|
||||
processor_max_streams = ChanCount::max(processor_max_streams, c->first);
|
||||
processor_max_streams = ChanCount::max(processor_max_streams, c->second);
|
||||
out = c->second;
|
||||
|
||||
if (boost::dynamic_pointer_cast<Delivery> (*p)
|
||||
&& boost::dynamic_pointer_cast<Delivery> (*p)->role() == Delivery::Main) {
|
||||
/* main delivery will increase port count to match input.
|
||||
* the Delivery::Main is usually the last processor - followed only by
|
||||
* 'MeterOutput'.
|
||||
*/
|
||||
seen_mains_out = true;
|
||||
}
|
||||
if (!seen_mains_out) {
|
||||
processor_out_streams = out;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (_meter) {
|
||||
_meter->reset_max_channels (processor_max_streams);
|
||||
}
|
||||
@ -3754,6 +3770,19 @@ Route::input_port_count_changing (ChanCount to)
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Called when there is a proposed change to the output port count */
|
||||
bool
|
||||
Route::output_port_count_changing (ChanCount to)
|
||||
{
|
||||
for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
|
||||
if (processor_out_streams.get(*t) > to.get(*t)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
/* The change is ok */
|
||||
return false;
|
||||
}
|
||||
|
||||
list<string>
|
||||
Route::unknown_processors () const
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user