Add hack to support 'renaming' of JACK::Client.

We wouldn't need this if JACK had jack_client_set_name().
This commit is contained in:
Jonathan Moore Liles 2010-01-16 18:38:27 -06:00
parent a971175c8e
commit e1a41ba9c9
11 changed files with 286 additions and 38 deletions

View File

@ -77,6 +77,8 @@
#include <FL/Fl_Flip_Button.H>
#include "const.h"
std::list <Chain*> Chain::chain;
@ -437,8 +439,17 @@ Chain::can_support_input_channels ( int n )
void
Chain::name ( const char *name )
{
char ename[512];
snprintf( ename, sizeof(ename), "%s/%s", APP_NAME, name );
_name = engine()->name( ename );
/* FIXME: discarding the name jack picked is technically wrong! */
_name = name;
for ( int i = 0; i < modules(); ++i )
module( i )->handle_chain_name_changed();
}

View File

@ -166,10 +166,10 @@ Controller_Module::connect_to ( Port *p )
{
chain()->engine()->lock();
char name[256];
snprintf( name, sizeof( name ), "%s-CV", p->name() );
// char name[256];
// snprintf( name, sizeof( name ), "%s-CV", p->name() );
JACK::Port po( chain()->engine()->client(), JACK::Port::Input, chain()->name(), 0, name );
JACK::Port po( chain()->engine(), JACK::Port::Input, p->name(), 0, "CV" );
if ( po.valid() )
{

View File

@ -86,7 +86,7 @@ JACK_Module::configure_inputs ( int n )
{
for ( int i = on; i < n; ++i )
{
JACK::Port po( chain()->engine()->client(), JACK::Port::Output, chain()->name(), i );
JACK::Port po( chain()->engine(), JACK::Port::Output, i );
if ( po.valid() )
{
@ -120,7 +120,7 @@ JACK_Module::configure_outputs ( int n )
{
for ( int i = on; i < n; ++i )
{
JACK::Port po( chain()->engine()->client(), JACK::Port::Input, chain()->name(), i );
JACK::Port po( chain()->engine(), JACK::Port::Input, i );
if ( po.valid() )
{
@ -188,10 +188,10 @@ void
JACK_Module::handle_chain_name_changed ( void )
{
for ( unsigned int i = 0; i < jack_output.size(); ++i )
jack_output[ i ].name( chain()->name(), i );
jack_output[ i ].name( NULL, i );
for ( unsigned int i = 0; i < jack_input.size(); ++i )
jack_input[ i ].name( chain()->name(), i );
jack_input[ i ].name( NULL, i );
}

View File

@ -17,6 +17,8 @@
/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/*******************************************************************************/
#pragma once
#define APP_NAME "Non-Mixer"
#define APP_TITLE "The Non-Mixer"
#define __MODULE__ "non-mixer"

View File

@ -41,7 +41,7 @@ Control_Sequence::Control_Sequence ( Track *track ) : Sequence( 0 )
_track = track;
_output = new JACK::Port( engine->client(), JACK::Port::Output, track->name(), track->ncontrols(), "cv" );
_output = new JACK::Port( engine, JACK::Port::Output, track->name(), track->ncontrols(), "cv" );
if ( track )
track->add( this );
@ -110,7 +110,7 @@ Control_Sequence::set ( Log_Entry &e )
assert( t );
_output = new JACK::Port( engine->client(), JACK::Port::Output, t->name(), t->ncontrols(), "cv" );
_output = new JACK::Port( engine, JACK::Port::Output, t->name(), t->ncontrols(), "cv" );
t->add( this );
}

View File

@ -77,7 +77,7 @@ Track::configure_outputs ( int n )
{
for ( int i = on; i < n; ++i )
{
JACK::Port p( engine->client(), JACK::Port::Output, name(), i );
JACK::Port p( engine, JACK::Port::Output, name(), i );
if ( p.valid() )
output.push_back( p );
@ -124,7 +124,7 @@ Track::configure_inputs ( int n )
{
for ( int i = on; i < n; ++i )
{
JACK::Port p( engine->client(), JACK::Port::Input, name(), i );
JACK::Port p( engine, JACK::Port::Input, name(), i );
if ( p.valid() )
input.push_back( p );

View File

@ -25,7 +25,7 @@
// Transport transport;
#define client engine->client()
#define client engine->jack_client()

View File

@ -18,6 +18,9 @@
/*******************************************************************************/
#include "Client.H"
#include "Port.H"
#include <algorithm>
@ -146,4 +149,66 @@ namespace JACK
// WARNING( "Unkown error while setting freewheeling mode" );
}
void
Client::port_added ( Port *p )
{
std::list < JACK::Port * >::iterator i = std::find( _active_ports.begin(), _active_ports.end(), p );
if ( i != _active_ports.end() )
return;
_active_ports.push_back( p );
}
void
Client::port_removed ( Port *p )
{
_active_ports.remove( p );
}
void
Client::freeze_ports ( void )
{
for ( std::list < JACK::Port * >::iterator i = _active_ports.begin();
i != _active_ports.end();
++i )
{
(*i)->freeze();
}
}
void
Client::thaw_ports ( void )
{
for ( std::list < JACK::Port * >::iterator i = _active_ports.begin();
i != _active_ports.end();
++i )
{
(*i)->thaw();
}
}
const char *
Client::name ( const char *s )
{
/* Because the JACK API does not provide a mechanism for renaming
* clients, we have to save connections, destroy our client,
* create a client with the new name, and restore our
* connections. Lovely. */
freeze_ports();
jack_deactivate( _client );
jack_client_close( _client );
_client = NULL;
s = init( s );
thaw_ports();
return s;
}
}

View File

@ -24,10 +24,16 @@
typedef jack_nframes_t nframes_t;
typedef float sample_t;
#include <list>
namespace JACK
{
class Port;
class Client
{
std::list <JACK::Port*> _active_ports;
jack_client_t *_client;
nframes_t _sample_rate;
@ -55,6 +61,9 @@ namespace JACK
Client ( const Client &rhs );
Client & operator = ( const Client &rhs );
void freeze_ports ( void );
void thaw_ports ( void );
protected:
void deactivate ( void );
@ -66,12 +75,16 @@ namespace JACK
public:
jack_client_t * client ( void ) { return _client; }
jack_client_t * jack_client ( void ) { return _client; }
void port_added ( JACK::Port * p );
void port_removed ( JACK::Port *p );
Client ( );
virtual ~Client ( );
const char * init ( const char *client_name );
const char * name ( const char * );
nframes_t nframes ( void ) const { return jack_get_buffer_size( _client ); }
float frame_rate ( void ) const { return jack_get_sample_rate( _client ); }

View File

@ -23,6 +23,7 @@
#include <string.h>
#include <stdio.h> // sprintf
#include <errno.h>
namespace JACK
{
@ -35,22 +36,36 @@ namespace JACK
return jack_port_name_size() - jack_client_name_size() - 6;
}
/* nframes is the number of frames to buffer */
Port::Port ( jack_client_t *client, jack_port_t *port )
Port::Port ( const Port &rhs )
{
_client = client;
_port = port;
_name = jack_port_name( _port );
_freezer = rhs._freezer;
_client = rhs._client;
_port = rhs._port;
_name = strdup( rhs._name );
_client->port_added( this );
}
Port::Port ( jack_client_t *client, const char *name, type_e dir )
/* nframes is the number of frames to buffer */
Port::Port ( JACK::Client *client, jack_port_t *port )
{
_freezer = NULL;
_client = client;
_port = port;
_name = strdup( jack_port_name( _port ) );
}
Port::Port ( JACK::Client *client, const char *name, type_e dir )
{
_freezer = NULL;
_client = client;
activate( name, dir );
}
Port::Port ( jack_client_t *client, type_e dir, const char *base, int n, const char *type )
Port::Port ( JACK::Client *client, type_e dir, const char *base, int n, const char *type )
{
_freezer = NULL;
_client = client;
const char *name = name_for_port( dir, base, n, type );
@ -58,8 +73,28 @@ namespace JACK
activate( name, dir );
}
Port::Port ( JACK::Client *client, type_e dir, int n, const char *type )
{
_freezer = NULL;
_client = client;
const char *name = name_for_port( dir, NULL, n, type );
activate( name, dir );
}
Port::~Port ( )
{
if ( _name )
free( _name );
_client->port_removed( this );
/* if ( _freezer ) */
/* { */
/* delete _freezer; */
/* _freezer = NULL; */
/* } */
/* if ( _port ) */
/* jack_port_unregister( _client, _port ); */
@ -74,15 +109,22 @@ namespace JACK
const char *dir_s = dir == Port::Output ? "out" : "in";
pname[0] = '\0';
if ( base )
{
strncpy( pname, base, Port::max_name() );
strcat( pname, "/" );
}
pname[ Port::max_name() - 1 ] = '\0';
int l = strlen( pname );
if ( type )
snprintf( pname + l, sizeof( pname ) - l, "/%s-%s-%d", type, dir_s, n + 1 );
snprintf( pname + l, sizeof( pname ) - l, "%s-%s-%d", type, dir_s, n + 1 );
else
snprintf( pname + l, sizeof( pname ) - l, "/%s-%d", dir_s, n + 1 );
snprintf( pname + l, sizeof( pname ) - l, "%s-%d", dir_s, n + 1 );
return pname;
}
@ -90,11 +132,13 @@ namespace JACK
void
Port::activate ( const char *name, type_e dir )
{
_name = name;
_port = jack_port_register( _client, _name,
_name = strdup( name );
_port = jack_port_register( _client->jack_client(), _name,
JACK_DEFAULT_AUDIO_TYPE,
dir == Output ? JackPortIsOutput : JackPortIsInput,
0 );
_client->port_added( this );
}
/** returns the sum of latency of all ports between this one and a
@ -107,7 +151,7 @@ namespace JACK
nframes_t
Port::total_latency ( void ) const
{
return jack_port_get_total_latency( _client, _port );
return jack_port_get_total_latency( _client->jack_client() , _port );
}
/** returns the number of frames of latency assigned to this port */
@ -128,14 +172,16 @@ namespace JACK
Port::shutdown ( void )
{
if ( _port )
jack_port_unregister( _client, _port );
jack_port_unregister( _client->jack_client(), _port );
_client->port_removed( this );
}
/** rename port */
bool
Port::name ( const char *name )
{
_name = name;
_name = strdup( name );
return 0 == jack_port_set_name( _port, name );
}
@ -170,4 +216,78 @@ namespace JACK
memset( buffer( nframes ), 0, nframes * sizeof( sample_t ) );
}
/** Return a malloc()'d null terminated array of strings
* representing all ports to which this port is connected. */
const char **
Port::connections ( void )
{
return jack_port_get_connections( _port );
}
/** Restore the connections returned by connections() */
bool
Port::connections ( const char **port_names )
{
if ( ! port_names )
return true;
for ( const char **port_name = port_names; *port_name; ++port_name )
{
const char *src;
const char *dst;
const char *name = jack_port_name( _port );
if ( type() == Output )
{
src = name;
dst = *port_name;
}
else
{
src = *port_name;
dst = name;
}
if ( int err = jack_connect( _client->jack_client(), src, dst ) )
{
if ( EEXIST == err )
{
/* connection already exists, not a problem */
}
else
{
return false;
}
}
}
return true;
}
void
Port::freeze ( void )
{
if ( _freezer )
delete _freezer;
freeze_state *f = new freeze_state();
f->connections = connections();
f->direction = type();
f->name = strdup( name() );
_freezer = f;
}
void
Port::thaw ( void )
{
activate( name(), _freezer->direction );
connections( _freezer->connections );
delete _freezer;
_freezer = NULL;
}
}

View File

@ -21,14 +21,15 @@
// #include <jack/jack.h>
#include "Client.H"
#include <stdlib.h>
namespace JACK
{
class Port
{
jack_port_t *_port;
const char *_name;
jack_client_t *_client;
char *_name;
JACK::Client *_client;
/* FIXME: reference count? */
@ -42,18 +43,15 @@ namespace JACK
static int max_name ( void );
Port ( jack_client_t *client, jack_port_t *port );
Port ( jack_client_t *client, const char *name, type_e dir );
Port ( jack_client_t *client, type_e dir, const char *base, int n, const char *type=0 );
Port ( JACK::Client *client, jack_port_t *port );
Port ( JACK::Client *client, const char *name, type_e dir );
Port ( JACK::Client *client, type_e dir, const char *base, int n, const char *type=0 );
Port ( JACK::Client *client, type_e dir, int n, const char *type=0 );
// Port ( );
~Port ( );
/* Port ( const Port & rhs ) */
/* { */
/* _port = rhs.port; */
/* _name = rhs.name; */
/* } */
Port ( const Port & rhs );
bool valid ( void ) const { return _port; }
@ -76,6 +74,45 @@ namespace JACK
void read ( sample_t *buf, nframes_t nframes );
void *buffer ( nframes_t nframes );
void silence ( nframes_t nframes );
/* */
const char ** connections ( void );
bool connections ( const char **port_names );
void freeze ( void );
void thaw ( void );
private:
/* holds all we need to know about a jack port to recreate it on a
new client */
struct freeze_state
{
const char **connections;
type_e direction;
char *name;
freeze_state ( )
{
connections = NULL;
name = NULL;
}
~freeze_state ( )
{
if ( connections )
{
free( connections );
connections = NULL;
}
if ( name )
{
free( name );
}
}
};
freeze_state *_freezer;
};
}