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; | |||||
| }; | }; | ||||
| } | } | ||||