Mixer: Fix crash when closing project containing certain configurations of modules.
This commit is contained in:
parent
97d12322f5
commit
0106604073
|
@ -174,6 +174,8 @@ Chain::~Chain ( )
|
|||
|
||||
_deleting = true;
|
||||
|
||||
/* FIXME: client may already be dead during teardown if group is destroyed first. */
|
||||
if ( client() )
|
||||
client()->lock();
|
||||
|
||||
for ( unsigned int i = scratch_port.size(); i--; )
|
||||
|
@ -182,8 +184,11 @@ Chain::~Chain ( )
|
|||
/* if we leave this up to FLTK, it will happen after we've
|
||||
already destroyed the client */
|
||||
modules_pack->clear();
|
||||
modules_pack = NULL;
|
||||
controls_pack->clear();
|
||||
modules_pack = NULL;
|
||||
|
||||
if ( client() )
|
||||
client()->unlock();
|
||||
}
|
||||
|
||||
|
@ -534,6 +539,8 @@ Chain::name ( const char *name )
|
|||
if ( strip()->group() )
|
||||
{
|
||||
if ( strip()->group()->single() )
|
||||
/* we are the owner of this group and its only member, so
|
||||
* rename it */
|
||||
strip()->group()->name(name);
|
||||
}
|
||||
|
||||
|
@ -713,6 +720,8 @@ Chain::add_to_process_queue ( Module *m )
|
|||
void
|
||||
Chain::build_process_queue ( void )
|
||||
{
|
||||
client()->lock();
|
||||
|
||||
process_queue.clear();
|
||||
|
||||
for ( int i = 0; i < modules(); ++i )
|
||||
|
@ -780,6 +789,8 @@ Chain::build_process_queue ( void )
|
|||
/* delete[] s; */
|
||||
/* } */
|
||||
/* } */
|
||||
|
||||
client()->unlock();
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -109,7 +109,7 @@ public:
|
|||
|
||||
bool can_support_input_channels ( int n );
|
||||
|
||||
int modules ( void ) const { return modules_pack->children(); }
|
||||
int modules ( void ) const { return modules_pack ? modules_pack->children() : 0; }
|
||||
Module *module ( int n ) const { return (Module*)modules_pack->child( n ); }
|
||||
void remove ( Controller_Module *m );
|
||||
void remove ( Module *m );
|
||||
|
|
|
@ -96,8 +96,6 @@ Controller_Module::~Controller_Module ( )
|
|||
|
||||
/* shutdown JACK port, if we have one */
|
||||
mode( GUI );
|
||||
|
||||
// disconnect();
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -56,6 +56,15 @@ Group::~Group ( )
|
|||
{
|
||||
DMESSAGE( "Destroying group" );
|
||||
|
||||
for ( std::list<Mixer_Strip*>::iterator i = strips.begin();
|
||||
i != strips.end();
|
||||
i++ )
|
||||
{
|
||||
/* avoid a use after free during project close when the group
|
||||
* may be destroyed before its member strips are */
|
||||
(*i)->clear_group();
|
||||
}
|
||||
|
||||
if ( _name )
|
||||
free( _name );
|
||||
|
||||
|
@ -100,6 +109,8 @@ Group::set ( Log_Entry &e )
|
|||
|
||||
void
|
||||
Group::latency ( jack_latency_callback_mode_t mode )
|
||||
{
|
||||
if ( trylock() )
|
||||
{
|
||||
for ( std::list<Mixer_Strip*>::iterator i = strips.begin();
|
||||
i != strips.end();
|
||||
|
@ -108,6 +119,8 @@ Group::latency ( jack_latency_callback_mode_t mode )
|
|||
if ( (*i)->chain() )
|
||||
(*i)->chain()->set_latency(mode == JackCaptureLatency ? JACK::Port::Input : JACK::Port::Output );
|
||||
}
|
||||
unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/* THREAD: RT */
|
||||
|
@ -208,8 +221,9 @@ Group::process ( nframes_t nframes )
|
|||
void
|
||||
Group::recal_load_coef ( void )
|
||||
{
|
||||
_load_coef = 1.0f / ( nframes() / (float)sample_rate() * 1000000.0 );
|
||||
_load_coef = 1.0f / ( nframes() / (float)sample_rate() * 1000000.0f );
|
||||
}
|
||||
|
||||
int
|
||||
Group::sample_rate_changed ( nframes_t srate )
|
||||
{
|
||||
|
@ -273,6 +287,7 @@ void
|
|||
Group::add ( Mixer_Strip *o )
|
||||
{
|
||||
lock();
|
||||
|
||||
if ( ! active() )
|
||||
{
|
||||
/* to call init */
|
||||
|
@ -280,10 +295,12 @@ Group::add ( Mixer_Strip *o )
|
|||
name(n);
|
||||
free(n);
|
||||
}
|
||||
|
||||
if ( o->chain() )
|
||||
o->chain()->thaw_ports();
|
||||
|
||||
strips.push_back(o);
|
||||
|
||||
unlock();
|
||||
}
|
||||
|
||||
|
@ -291,13 +308,15 @@ void
|
|||
Group::remove ( Mixer_Strip *o )
|
||||
{
|
||||
lock();
|
||||
|
||||
strips.remove(o);
|
||||
|
||||
if ( o->chain() )
|
||||
o->chain()->freeze_ports();
|
||||
|
||||
if ( strips.size() == 0 && active() )
|
||||
{
|
||||
Client::close();
|
||||
}
|
||||
|
||||
unlock();
|
||||
}
|
||||
|
||||
|
|
|
@ -97,6 +97,8 @@ public:
|
|||
void add (Mixer_Strip*);
|
||||
void remove (Mixer_Strip*);
|
||||
|
||||
int children ( void ) const { return strips.size(); }
|
||||
|
||||
/* Engine *engine ( void ) { return _engine; } */
|
||||
};
|
||||
|
||||
|
|
|
@ -821,8 +821,6 @@ void Mixer::remove ( Mixer_Strip *ms )
|
|||
|
||||
mixer_strips->remove( ms );
|
||||
|
||||
ms->group()->remove( ms );
|
||||
|
||||
if ( parent() )
|
||||
parent()->redraw();
|
||||
}
|
||||
|
|
|
@ -73,6 +73,7 @@ Mixer_Strip::Mixer_Strip( const char *strip_name ) : Fl_Group( 0, 0, 120, 600 )
|
|||
|
||||
init();
|
||||
|
||||
/* create single member group */
|
||||
_group = new Group(strip_name, true);
|
||||
|
||||
_group->add( this );
|
||||
|
@ -111,10 +112,26 @@ Mixer_Strip::~Mixer_Strip ( )
|
|||
/* make sure this gets destroyed before the chain */
|
||||
fader_tab->clear();
|
||||
|
||||
if ( _group )
|
||||
{
|
||||
_group->remove( this );
|
||||
}
|
||||
|
||||
if ( _chain )
|
||||
{
|
||||
delete _chain;
|
||||
_chain = NULL;
|
||||
}
|
||||
|
||||
if ( _group )
|
||||
{
|
||||
if ( 0 == _group->children() )
|
||||
delete _group;
|
||||
|
||||
_group = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
|
@ -347,6 +364,7 @@ void Mixer_Strip::cb_handle(Fl_Widget* o, void* v) {
|
|||
void
|
||||
Mixer_Strip::group ( Group *g )
|
||||
{
|
||||
/* FIXME: what is the intention here? */
|
||||
if ( !g && _group && _group->single() )
|
||||
return;
|
||||
|
||||
|
|
|
@ -170,6 +170,7 @@ public:
|
|||
Controller_Module *spatializer ( void );
|
||||
|
||||
Group *group ( void ) { return _group; }
|
||||
void clear_group ( void ) { _group = NULL; }
|
||||
|
||||
// int group ( void ) const;
|
||||
void group ( Group * );
|
||||
|
|
|
@ -105,19 +105,25 @@ Module::~Module ( )
|
|||
{
|
||||
Module *o = (Module*)control_input[i].connected_port()->module();
|
||||
|
||||
if ( ! o->is_default() )
|
||||
if ( !o )
|
||||
{
|
||||
DWARNING( "Programming error. Connected port has null module. %s %s",
|
||||
|
||||
label(),
|
||||
control_input[i].connected_port()->name());
|
||||
}
|
||||
|
||||
control_input[i].disconnect();
|
||||
|
||||
if ( o )
|
||||
{
|
||||
if ( ! o->is_default() )
|
||||
{
|
||||
DMESSAGE( "Deleting connected module %s", o->label() );
|
||||
|
||||
delete o;
|
||||
}
|
||||
else
|
||||
{
|
||||
control_input[i].disconnect();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
control_input[i].destroy_osc_port();
|
||||
|
@ -125,6 +131,9 @@ Module::~Module ( )
|
|||
for ( unsigned int i = 0; i < control_output.size(); ++i )
|
||||
control_output[i].disconnect();
|
||||
|
||||
aux_audio_output.clear();
|
||||
aux_audio_input.clear();
|
||||
|
||||
audio_input.clear();
|
||||
audio_output.clear();
|
||||
|
||||
|
@ -1180,8 +1189,20 @@ Module::freeze_ports ( void )
|
|||
for ( int i = 0; i < ncontrol_inputs(); ++i )
|
||||
{
|
||||
if ( control_input[i].connected() )
|
||||
{
|
||||
if ( ! control_input[i].connected_port()->module() )
|
||||
{
|
||||
DWARNING( "Programming error. Connected port has null module. %s %s",
|
||||
|
||||
name(),
|
||||
control_input[i].connected_port()->name());
|
||||
}
|
||||
else
|
||||
{
|
||||
control_input[i].connected_port()->module()->freeze_ports();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for ( unsigned int i = 0; i < aux_audio_input.size(); ++i )
|
||||
{
|
||||
|
|
|
@ -173,6 +173,9 @@ public:
|
|||
|
||||
virtual ~Port ( )
|
||||
{
|
||||
/* FIXME: will this cause problems with cloning an instance? */
|
||||
disconnect();
|
||||
|
||||
if ( _by_number_path )
|
||||
free( _by_number_path );
|
||||
_by_number_path = NULL;
|
||||
|
@ -321,18 +324,8 @@ public:
|
|||
/* disconnect from *all* connected ports */
|
||||
void disconnect ( void )
|
||||
{
|
||||
if ( _connected.size() )
|
||||
{
|
||||
for ( std::list<Port*>::iterator i = _connected.begin(); i != _connected.end(); i++ )
|
||||
{
|
||||
Port *p = *i;
|
||||
|
||||
/* iterator about to be invalidated... */
|
||||
i = _connected.erase(i);
|
||||
|
||||
disconnect(p);
|
||||
}
|
||||
}
|
||||
while ( _connected.size() )
|
||||
disconnect(_connected.front());
|
||||
}
|
||||
|
||||
void jack_port ( JACK::Port *v ) { _jack_port = v; }
|
||||
|
|
Loading…
Reference in New Issue