Browse Source

Mixer: Fix issues with port auto-connection

Closes #188
tags/non-daw-v1.2.0
Jonathan Moore Liles 8 years ago
parent
commit
3946d39221
10 changed files with 192 additions and 63 deletions
  1. +1
    -1
      lib/ntk
  2. +3
    -3
      mixer/src/Chain.C
  3. +26
    -15
      mixer/src/JACK_Module.C
  4. +12
    -0
      mixer/src/Mixer.C
  5. +17
    -20
      mixer/src/Mixer_Strip.C
  6. +38
    -0
      mixer/src/Module.C
  7. +76
    -23
      mixer/src/Module.H
  8. +4
    -0
      mixer/src/Project.C
  9. +2
    -0
      mixer/src/Project.H
  10. +13
    -1
      nonlib/JACK/Port.C

+ 1
- 1
lib/ntk

@@ -1 +1 @@
Subproject commit 9884cca97d2dc7a34e730b942465b0bb808c6ccb
Subproject commit 5719b0044d9f267de5391fab006370cc7f4e70bd

+ 3
- 3
mixer/src/Chain.C View File

@@ -383,7 +383,7 @@ Chain::configure_ports ( void )
for ( unsigned int i = 0; i < req_buffers; ++i )
{
Module::Port p( NULL, Module::Port::OUTPUT, Module::Port::AUDIO );
p.connect_to( buffer_alloc( client()->nframes() ) );
p.set_buffer( buffer_alloc( client()->nframes() ) );
buffer_fill_with_silence( (sample_t*)p.buffer(), client()->nframes() );
scratch_port.push_back( p );
}
@@ -749,11 +749,11 @@ Chain::build_process_queue ( void )
for ( unsigned int j = 0; j < m->audio_input.size(); ++j )
{
m->audio_input[j].connect_to( &scratch_port[j] );
m->audio_input[j].set_buffer( scratch_port[j].buffer() );
}
for ( unsigned int j = 0; j < m->audio_output.size(); ++j )
{
m->audio_output[j].connect_to( &scratch_port[j] );
m->audio_output[j].set_buffer( scratch_port[j].buffer() );
}

m->handle_port_connection_change();


+ 26
- 15
mixer/src/JACK_Module.C View File

@@ -51,6 +51,8 @@ extern char *instance_name;
static JACK_Module *receptive_to_drop = NULL;

const int MAX_PORTS = 16;

JACK_Module::JACK_Module ( bool log )
: Module ( 25, 25, name() )
{
@@ -70,8 +72,8 @@ JACK_Module::JACK_Module ( bool log )
{
Port p( this, Port::INPUT, Port::CONTROL, "Inputs" );
p.hints.type = Port::Hints::INTEGER;
p.hints.minimum = 0;
p.hints.maximum = 16;
p.hints.minimum = 1;
p.hints.maximum = MAX_PORTS;
p.hints.ranged = true;
p.hints.visible = false;

@@ -84,8 +86,8 @@ JACK_Module::JACK_Module ( bool log )
{
Port p( this, Port::INPUT, Port::CONTROL, "Outputs" );
p.hints.type = Port::Hints::INTEGER;
p.hints.minimum = 0;
p.hints.maximum = 16;
p.hints.minimum = 1;
p.hints.maximum = MAX_PORTS;
p.hints.ranged = true;
p.hints.visible = false;

@@ -226,8 +228,7 @@ get_connections_for_ports ( std::vector<Module::Port> ports )
free( strip_name );
strip_name = s;
}
else
if ( 2 == sscanf( *c, "Non-Mixer.%a[^:(] (%a[^:)]):", &client_id, &strip_name ) )
else if ( 2 == sscanf( *c, "Non-Mixer.%a[^:(] (%a[^:)]):", &client_id, &strip_name ) )
{
free( client_id );
char *s = NULL;
@@ -235,8 +236,7 @@ get_connections_for_ports ( std::vector<Module::Port> ports )
free( strip_name );
strip_name = s;
}
else
if ( 2 == sscanf( *c, "Non-Timeline.%a[^:/]:%a[^/]/", &client_id, &strip_name ) )
else if ( 2 == sscanf( *c, "Non-Timeline.%a[^:/]:%a[^/]/", &client_id, &strip_name ) )
{
free( client_id );
char *s = NULL;
@@ -244,8 +244,7 @@ get_connections_for_ports ( std::vector<Module::Port> ports )
free( strip_name );
strip_name = s;
}
else
if ( 2 == sscanf( *c, "Non-DAW.%a[^:/]:%a[^/]/", &client_id, &strip_name ) )
else if ( 2 == sscanf( *c, "Non-DAW.%a[^:/]:%a[^/]/", &client_id, &strip_name ) )
{
free( client_id );
char *s = NULL;
@@ -379,11 +378,11 @@ JACK_Module::configure_inputs ( int n )
{
if ( n > 0 )
{
if ( is_default() )
control_input[0].hints.minimum = 1;

output_connection_handle->show();
}

if ( n < 1 || n > MAX_PORTS )
return false;
int on = audio_input.size();

@@ -396,6 +395,8 @@ JACK_Module::configure_inputs ( int n )
add_port( Port( this, Port::INPUT, Port::AUDIO ) );
}
}

mixer->maybe_auto_connect_output(&aux_audio_output.back());
}
else
{
@@ -403,9 +404,11 @@ JACK_Module::configure_inputs ( int n )
{
audio_input.back().disconnect();
audio_input.pop_back();
aux_audio_output.back().disconnect();
aux_audio_output.back().jack_port()->shutdown();
delete aux_audio_output.back().jack_port();
aux_audio_output.pop_back();
}
}

@@ -422,7 +425,10 @@ bool
JACK_Module::configure_outputs ( int n )
{
int on = audio_output.size();

if ( n > MAX_PORTS )
return false;
if ( n > 0 )
{
input_connection_handle->show();
@@ -437,6 +443,8 @@ JACK_Module::configure_outputs ( int n )
add_port( Port( this, Port::OUTPUT, Port::AUDIO ) );
}
}

mixer->auto_connect();
}
else
{
@@ -444,6 +452,7 @@ JACK_Module::configure_outputs ( int n )
{
audio_output.back().disconnect();
audio_output.pop_back();
aux_audio_input.back().disconnect();
aux_audio_input.back().jack_port()->shutdown();
delete aux_audio_input.back().jack_port();
aux_audio_input.pop_back();
@@ -458,9 +467,11 @@ JACK_Module::configure_outputs ( int n )
dec_button->show();
inc_button->show();
}

return true;
}


bool
JACK_Module::initialize ( void )
{
@@ -703,7 +714,7 @@ JACK_Module::process ( nframes_t nframes )
buffer_copy( (sample_t*)aux_audio_output[i].jack_port()->buffer(nframes),
(sample_t*)audio_input[i].buffer(),
nframes );
}
}
}



+ 12
- 0
mixer/src/Mixer.C View File

@@ -1148,6 +1148,12 @@ Mixer::get_auto_connect_targets ( void )
void
Mixer::auto_connect ( void )
{
if ( Project::is_opening() )
/* it's more efficient to do this once at the end rather than as we go. */
return;
DMESSAGE("Full auto-connect cycle" );
/* give strips with group affinity the first shot */
for ( int i = 0; i < mixer_strips->children(); i++ )
{
@@ -1170,6 +1176,12 @@ Mixer::auto_connect ( void )
void
Mixer::maybe_auto_connect_output ( Module::Port *p )
{
if ( Project::is_opening() )
/* it's more efficient to do this once at the end rather than as we go. */
return;

// DMESSAGE( "Single output auto connect cycle" );
/* give strips with group affinity the first shot */
for ( int i = 0; i < mixer_strips->children(); i++ )
{


+ 17
- 20
mixer/src/Mixer_Strip.C View File

@@ -996,7 +996,6 @@ Mixer_Strip::has_group_affinity ( void ) const
return _auto_input && strncmp( _auto_input, "*/", 2 );
}


bool
Mixer_Strip::maybe_auto_connect_output ( Module::Port *p )
{
@@ -1009,25 +1008,16 @@ Mixer_Strip::maybe_auto_connect_output ( Module::Port *p )

if ( ! _auto_input )
{
if ( p->connected_port() && p->connected_port()->module()->chain()->strip() == this )
{
/* first break previous auto connection */
p->connected_port()->jack_port()->disconnect( p->jack_port()->jack_name() );
p->disconnect();
}
/* break any previous connection between this port and this module */
p->disconnect_from_strip(this);
}
if ( _auto_input && matches_pattern( _auto_input, p ) )
{
DMESSAGE( "Auto connecting port" );

if ( p->connected_port() )
{
/* first break previous auto connection */
p->connected_port()->jack_port()->disconnect( p->jack_port()->jack_name() );
p->disconnect();
}

/* break any prior auto-connection */
p->disconnect();
// FIXME: Find a better way to get the port index.
const char* jack_name = p->jack_port()->jack_name();
/* get port number */
@@ -1036,14 +1026,21 @@ Mixer_Strip::maybe_auto_connect_output ( Module::Port *p )

/* FIXME: safe assumption? */
JACK_Module *m = (JACK_Module*)chain()->module(0);

if ( !m )
{
/* no jack module in the chian... may be in the process of adding the JACK module to the chain... i.e in log replay when loading a project. */
return false;
}
if ( n < m->aux_audio_input.size() )
if ( n >= m->aux_audio_input.size() )
{
m->aux_audio_input[n].jack_port()->connect( jack_name );
/* make a note of the connection so we know to disconnected later */
m->aux_audio_input[n].connect_to( p );
// DMESSAGE( "No port to connect to at this index");
return false;
}

m->aux_audio_input[n].connect_to( p );
if ( p->module()->is_default() )
{
/* only do this for mains */


+ 38
- 0
mixer/src/Module.C View File

@@ -86,6 +86,18 @@ Module::~Module ( )
audio_input[i].disconnect();
for ( unsigned int i = 0; i < audio_output.size(); ++i )
audio_output[i].disconnect();
for ( unsigned int i = 0; i < aux_audio_input.size(); ++i )
{
aux_audio_input[i].disconnect();
aux_audio_input[i].jack_port()->shutdown();
delete aux_audio_input[i].jack_port();
}
for ( unsigned int i = 0; i < aux_audio_output.size(); ++i )
{
aux_audio_output[i].disconnect();
aux_audio_output[i].jack_port()->shutdown();
delete aux_audio_output[i].jack_port();
}
for ( unsigned int i = 0; i < control_input.size(); ++i )
{
/* destroy connected Controller_Module */
@@ -129,6 +141,15 @@ Module::~Module ( )
void
Module::init ( void )
{

/* we use pointers to these vector elements for port auto connection stuff and need to prevent reallocation from invalidating them. */
audio_input.reserve(16);
audio_output.reserve(16);
control_input.reserve(16);
control_output.reserve(16);
aux_audio_input.reserve(16);
aux_audio_output.reserve(16);
// _latency = 0;
_is_default = false;
_editor = 0;
@@ -245,6 +266,23 @@ Module::paste_before ( void )


void
Module::Port::disconnect_from_strip ( Mixer_Strip *o )
{
for ( std::list<Port*>::iterator i = _connected.begin(); i != _connected.end(); i++ )
{
Port *p = *i;

if ( p->module()->chain()->strip() == o )
{
/* iterator about to be invalidated... */
i = _connected.erase(i);
disconnect(p);
}
}
}

const char *
Module::Port::osc_number_path ( void )
{


+ 76
- 23
mixer/src/Module.H View File

@@ -31,12 +31,15 @@
#include "Loggable.H"
#include "JACK/Port.H"
#include "OSC/Endpoint.H"
#include <list>
#include <algorithm>

class Chain;
class Module_Parameter_Editor;
class Fl_Menu_;
class Fl_Menu_Button;
class Fl_Button;
class Mixer_Strip;

class Module : public Fl_Group, public Loggable {

@@ -86,6 +89,11 @@ public:

class Port
{

/* support multiple connection for audio ports (many to one, one to many, many to many).
control ports only support one to one and one to many. */

/* char *type_names[] = { "Audio", "Control" }; */
/* char *direction_names[] = { "Input", "Output" }; */

@@ -139,7 +147,6 @@ public:
_type = type;
_buf = 0;
_nframes = 0;
_connected = 0;
_module = module;
_scaled_signal = 0;
_unscaled_signal = 0;
@@ -155,7 +162,6 @@ public:
_type = p._type;
_buf = p._buf;
_nframes = p._nframes;
_connected = p._connected;
_module = p._module;
hints = p.hints;
_scaled_signal = p._scaled_signal;
@@ -170,9 +176,6 @@ public:
if ( _by_number_path )
free( _by_number_path );
_by_number_path = NULL;

// change_osc_path( NULL );
// disconnect();
}

const char *name ( void ) const { return _name; }
@@ -242,44 +245,94 @@ public:
return 0.0f;
}

bool connected ( void ) const { return _connected; }
bool connected ( void ) const {
if ( _type == Port::AUDIO )
/* internal audio ports are considered connected by the buffer setting */
return _buf != 0;
else
/* control and external audio ports belong to a graph */
return _connected.size() > 0;
}
bool connected_osc ( void ) const;

Port *connected_port ( void ) const
{
return _connected;
ASSERT( _type == Port::CONTROL, "Operation only available for control ports" );
return _connected.size() == 0 ? NULL : _connected.front();
}

void connect_to ( Port *to )
{
_buf = to->_buf;
to->_connected = this;
_connected = to;
if ( _type != Port::AUX_AUDIO )
{
_buf = to->_buf;
}

if ( jack_port() && to->jack_port() )
jack_port()->connect( to->jack_port()->jack_name() );

if ( std::find(_connected.begin(),_connected.end(),to) == _connected.end() )
{
_connected.push_back(to);
to->_connected.push_back(this);
}
}


/* disconnect this port from any ports of modules belonging to strip /o/ */
void disconnect_from_strip ( Mixer_Strip *o );
void connect_to ( void *buf )
{
ASSERT( _type == Port::CONTROL, "Operation only available for control ports" );
_buf = buf;
update_connected_port_buffer();
}

void set_buffer ( void *buf )
{
ASSERT( _type != Port::CONTROL, "Operation only available for audio ports" );
_buf = buf;
}

void send_feedback ( void );

void disconnect ( void )
bool connected_to ( Port *p )
{
if ( _connected && _connected != (void*)0x01 )
{
_connected->_connected = NULL;
return std::find( _connected.begin(), _connected.end(), p ) != _connected.end();
}
/* disconnect from specified port */
void disconnect ( Port *p )
{
if ( ! connected_to(p) )
return;

if ( _connected->_module )
_connected->_module->handle_control_disconnect( this );
if ( _type == Port::CONTROL && p->_module )
p->_module->handle_control_disconnect( this );
if ( jack_port() && p->jack_port() )
jack_port()->disconnect( p->jack_port()->jack_name() );

_connected = NULL;
_connected.remove(p);
p->_connected.remove(this);
}
/* 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);
}
}
else
_connected = NULL;

/* FIXME: do something! */
}

void jack_port ( JACK::Port *v ) { _jack_port = v; }
@@ -289,8 +342,8 @@ public:

char *generate_osc_path ( void );
void change_osc_path ( char *path );
Port *_connected;
std::list <Port*> _connected;
Type _type;
Direction _direction;
const char *_name;


+ 4
- 0
mixer/src/Project.C View File

@@ -58,6 +58,7 @@ char Project::_name[256];
char Project::_created_on[40];
char Project::_path[512];
bool Project::_is_open = false;
bool Project::_is_opening = false;
int Project::_lockfd = 0;

@@ -261,6 +262,8 @@ Project::open ( const char *name )
if ( version != PROJECT_VERSION )
return E_VERSION;

_is_opening = true;
if ( ! Loggable::replay( "snapshot" ) )
return E_INVALID;

@@ -279,6 +282,7 @@ Project::open ( const char *name )

_is_open = true;

_is_opening = false;
// tle->load_timeline_settings();

// timeline->zoom_fit();


+ 2
- 0
mixer/src/Project.H View File

@@ -27,6 +27,7 @@ class Project

static int _lockfd;
static bool _is_open;
static bool _is_opening;
static char _name[256];
static char _path[512];
static char _created_on[40];
@@ -61,4 +62,5 @@ public:
static const char *path ( void ) { return _path; }
static const char *created_on ( void ) { return _created_on; }
static const bool is_opening ( void ) { return _is_opening; }
};

+ 13
- 1
nonlib/JACK/Port.C View File

@@ -380,12 +380,20 @@ namespace JACK
{
const char *name = jack_port_name( _port );

/* jack complains when you attempt to connect an already connected port... */
if ( connected_to( to ) )
return 0;
if ( _direction == Output )
{
DMESSAGE("Connecting jack port %s to %s", name, to );

return jack_connect( _client->jack_client(), name, to );
}
else
{
DMESSAGE("Connecting jack port %s to %s", to, name );

return jack_connect( _client->jack_client(), to, name );
}
}
@@ -397,11 +405,15 @@ namespace JACK
const char *name = jack_port_name( _port );

if ( _direction == Output )
{
{
DMESSAGE("Disconnecting jack port %s from %s", name, from );
return jack_disconnect( _client->jack_client(), name, from );
}
else
{
DMESSAGE("Disconnecting jack port %s from %s", from, name );
return jack_disconnect( _client->jack_client(), from, name );
}
}


Loading…
Cancel
Save