We wouldn't need this if JACK had jack_client_set_name().tags/non-daw-v1.1.0
@@ -77,6 +77,8 @@ | |||||
#include <FL/Fl_Flip_Button.H> | #include <FL/Fl_Flip_Button.H> | ||||
#include "const.h" | |||||
std::list <Chain*> Chain::chain; | std::list <Chain*> Chain::chain; | ||||
@@ -437,8 +439,17 @@ Chain::can_support_input_channels ( int n ) | |||||
void | void | ||||
Chain::name ( const char *name ) | 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; | _name = name; | ||||
for ( int i = 0; i < modules(); ++i ) | for ( int i = 0; i < modules(); ++i ) | ||||
module( i )->handle_chain_name_changed(); | module( i )->handle_chain_name_changed(); | ||||
} | } | ||||
@@ -166,10 +166,10 @@ Controller_Module::connect_to ( Port *p ) | |||||
{ | { | ||||
chain()->engine()->lock(); | 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() ) | if ( po.valid() ) | ||||
{ | { | ||||
@@ -86,7 +86,7 @@ JACK_Module::configure_inputs ( int n ) | |||||
{ | { | ||||
for ( int i = on; i < n; ++i ) | 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() ) | if ( po.valid() ) | ||||
{ | { | ||||
@@ -120,7 +120,7 @@ JACK_Module::configure_outputs ( int n ) | |||||
{ | { | ||||
for ( int i = on; i < n; ++i ) | 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() ) | if ( po.valid() ) | ||||
{ | { | ||||
@@ -188,10 +188,10 @@ void | |||||
JACK_Module::handle_chain_name_changed ( void ) | JACK_Module::handle_chain_name_changed ( void ) | ||||
{ | { | ||||
for ( unsigned int i = 0; i < jack_output.size(); ++i ) | 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 ) | for ( unsigned int i = 0; i < jack_input.size(); ++i ) | ||||
jack_input[ i ].name( chain()->name(), i ); | |||||
jack_input[ i ].name( NULL, i ); | |||||
} | } | ||||
@@ -17,6 +17,8 @@ | |||||
/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | /* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | ||||
/*******************************************************************************/ | /*******************************************************************************/ | ||||
#pragma once | |||||
#define APP_NAME "Non-Mixer" | #define APP_NAME "Non-Mixer" | ||||
#define APP_TITLE "The Non-Mixer" | #define APP_TITLE "The Non-Mixer" | ||||
#define __MODULE__ "non-mixer" | #define __MODULE__ "non-mixer" |
@@ -41,7 +41,7 @@ Control_Sequence::Control_Sequence ( Track *track ) : Sequence( 0 ) | |||||
_track = track; | _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 ) | if ( track ) | ||||
track->add( this ); | track->add( this ); | ||||
@@ -110,7 +110,7 @@ Control_Sequence::set ( Log_Entry &e ) | |||||
assert( t ); | 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 ); | t->add( this ); | ||||
} | } | ||||
@@ -77,7 +77,7 @@ Track::configure_outputs ( int n ) | |||||
{ | { | ||||
for ( int i = on; i < n; ++i ) | 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() ) | if ( p.valid() ) | ||||
output.push_back( p ); | output.push_back( p ); | ||||
@@ -124,7 +124,7 @@ Track::configure_inputs ( int n ) | |||||
{ | { | ||||
for ( int i = on; i < n; ++i ) | 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() ) | if ( p.valid() ) | ||||
input.push_back( p ); | input.push_back( p ); | ||||
@@ -25,7 +25,7 @@ | |||||
// Transport transport; | // Transport transport; | ||||
#define client engine->client() | |||||
#define client engine->jack_client() | |||||
@@ -18,6 +18,9 @@ | |||||
/*******************************************************************************/ | /*******************************************************************************/ | ||||
#include "Client.H" | #include "Client.H" | ||||
#include "Port.H" | |||||
#include <algorithm> | |||||
@@ -146,4 +149,66 @@ namespace JACK | |||||
// WARNING( "Unkown error while setting freewheeling mode" ); | // 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; | |||||
} | |||||
} | } |
@@ -24,10 +24,16 @@ | |||||
typedef jack_nframes_t nframes_t; | typedef jack_nframes_t nframes_t; | ||||
typedef float sample_t; | typedef float sample_t; | ||||
#include <list> | |||||
namespace JACK | namespace JACK | ||||
{ | { | ||||
class Port; | |||||
class Client | class Client | ||||
{ | { | ||||
std::list <JACK::Port*> _active_ports; | |||||
jack_client_t *_client; | jack_client_t *_client; | ||||
nframes_t _sample_rate; | nframes_t _sample_rate; | ||||
@@ -55,6 +61,9 @@ namespace JACK | |||||
Client ( const Client &rhs ); | Client ( const Client &rhs ); | ||||
Client & operator = ( const Client &rhs ); | Client & operator = ( const Client &rhs ); | ||||
void freeze_ports ( void ); | |||||
void thaw_ports ( void ); | |||||
protected: | protected: | ||||
void deactivate ( void ); | void deactivate ( void ); | ||||
@@ -66,12 +75,16 @@ namespace JACK | |||||
public: | 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 ( ); | Client ( ); | ||||
virtual ~Client ( ); | virtual ~Client ( ); | ||||
const char * init ( const char *client_name ); | const char * init ( const char *client_name ); | ||||
const char * name ( const char * ); | |||||
nframes_t nframes ( void ) const { return jack_get_buffer_size( _client ); } | nframes_t nframes ( void ) const { return jack_get_buffer_size( _client ); } | ||||
float frame_rate ( void ) const { return jack_get_sample_rate( _client ); } | float frame_rate ( void ) const { return jack_get_sample_rate( _client ); } | ||||
@@ -23,6 +23,7 @@ | |||||
#include <string.h> | #include <string.h> | ||||
#include <stdio.h> // sprintf | #include <stdio.h> // sprintf | ||||
#include <errno.h> | |||||
namespace JACK | namespace JACK | ||||
{ | { | ||||
@@ -35,22 +36,36 @@ namespace JACK | |||||
return jack_port_name_size() - jack_client_name_size() - 6; | return jack_port_name_size() - jack_client_name_size() - 6; | ||||
} | } | ||||
Port::Port ( const Port &rhs ) | |||||
{ | |||||
_freezer = rhs._freezer; | |||||
_client = rhs._client; | |||||
_port = rhs._port; | |||||
_name = strdup( rhs._name ); | |||||
_client->port_added( this ); | |||||
} | |||||
/* nframes is the number of frames to buffer */ | /* nframes is the number of frames to buffer */ | ||||
Port::Port ( jack_client_t *client, jack_port_t *port ) | |||||
Port::Port ( JACK::Client *client, jack_port_t *port ) | |||||
{ | { | ||||
_freezer = NULL; | |||||
_client = client; | _client = client; | ||||
_port = port; | _port = port; | ||||
_name = jack_port_name( _port ); | |||||
_name = strdup( jack_port_name( _port ) ); | |||||
} | } | ||||
Port::Port ( jack_client_t *client, const char *name, type_e dir ) | |||||
Port::Port ( JACK::Client *client, const char *name, type_e dir ) | |||||
{ | { | ||||
_freezer = NULL; | |||||
_client = client; | _client = client; | ||||
activate( name, dir ); | 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; | _client = client; | ||||
const char *name = name_for_port( dir, base, n, type ); | const char *name = name_for_port( dir, base, n, type ); | ||||
@@ -58,8 +73,28 @@ namespace JACK | |||||
activate( name, dir ); | 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 ( ) | Port::~Port ( ) | ||||
{ | { | ||||
if ( _name ) | |||||
free( _name ); | |||||
_client->port_removed( this ); | |||||
/* if ( _freezer ) */ | |||||
/* { */ | |||||
/* delete _freezer; */ | |||||
/* _freezer = NULL; */ | |||||
/* } */ | |||||
/* if ( _port ) */ | /* if ( _port ) */ | ||||
/* jack_port_unregister( _client, _port ); */ | /* jack_port_unregister( _client, _port ); */ | ||||
@@ -74,15 +109,22 @@ namespace JACK | |||||
const char *dir_s = dir == Port::Output ? "out" : "in"; | const char *dir_s = dir == Port::Output ? "out" : "in"; | ||||
strncpy( pname, base, Port::max_name() ); | |||||
pname[0] = '\0'; | |||||
if ( base ) | |||||
{ | |||||
strncpy( pname, base, Port::max_name() ); | |||||
strcat( pname, "/" ); | |||||
} | |||||
pname[ Port::max_name() - 1 ] = '\0'; | pname[ Port::max_name() - 1 ] = '\0'; | ||||
int l = strlen( pname ); | int l = strlen( pname ); | ||||
if ( type ) | 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 | 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; | return pname; | ||||
} | } | ||||
@@ -90,11 +132,13 @@ namespace JACK | |||||
void | void | ||||
Port::activate ( const char *name, type_e dir ) | 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, | JACK_DEFAULT_AUDIO_TYPE, | ||||
dir == Output ? JackPortIsOutput : JackPortIsInput, | dir == Output ? JackPortIsOutput : JackPortIsInput, | ||||
0 ); | 0 ); | ||||
_client->port_added( this ); | |||||
} | } | ||||
/** returns the sum of latency of all ports between this one and a | /** returns the sum of latency of all ports between this one and a | ||||
@@ -107,7 +151,7 @@ namespace JACK | |||||
nframes_t | nframes_t | ||||
Port::total_latency ( void ) const | 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 */ | /** returns the number of frames of latency assigned to this port */ | ||||
@@ -128,14 +172,16 @@ namespace JACK | |||||
Port::shutdown ( void ) | Port::shutdown ( void ) | ||||
{ | { | ||||
if ( _port ) | if ( _port ) | ||||
jack_port_unregister( _client, _port ); | |||||
jack_port_unregister( _client->jack_client(), _port ); | |||||
_client->port_removed( this ); | |||||
} | } | ||||
/** rename port */ | /** rename port */ | ||||
bool | bool | ||||
Port::name ( const char *name ) | Port::name ( const char *name ) | ||||
{ | { | ||||
_name = name; | |||||
_name = strdup( name ); | |||||
return 0 == jack_port_set_name( _port, name ); | return 0 == jack_port_set_name( _port, name ); | ||||
} | } | ||||
@@ -170,4 +216,78 @@ namespace JACK | |||||
memset( buffer( nframes ), 0, nframes * sizeof( sample_t ) ); | 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; | |||||
} | |||||
} | } |
@@ -21,14 +21,15 @@ | |||||
// #include <jack/jack.h> | // #include <jack/jack.h> | ||||
#include "Client.H" | #include "Client.H" | ||||
#include <stdlib.h> | |||||
namespace JACK | namespace JACK | ||||
{ | { | ||||
class Port | class Port | ||||
{ | { | ||||
jack_port_t *_port; | jack_port_t *_port; | ||||
const char *_name; | |||||
jack_client_t *_client; | |||||
char *_name; | |||||
JACK::Client *_client; | |||||
/* FIXME: reference count? */ | /* FIXME: reference count? */ | ||||
@@ -42,18 +43,15 @@ namespace JACK | |||||
static int max_name ( void ); | 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 ( ); | ~Port ( ); | ||||
/* Port ( const Port & rhs ) */ | |||||
/* { */ | |||||
/* _port = rhs.port; */ | |||||
/* _name = rhs.name; */ | |||||
/* } */ | |||||
Port ( const Port & rhs ); | |||||
bool valid ( void ) const { return _port; } | bool valid ( void ) const { return _port; } | ||||
@@ -76,6 +74,45 @@ namespace JACK | |||||
void read ( sample_t *buf, nframes_t nframes ); | void read ( sample_t *buf, nframes_t nframes ); | ||||
void *buffer ( nframes_t nframes ); | void *buffer ( nframes_t nframes ); | ||||
void silence ( 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; | |||||
}; | }; | ||||
} | } |