NSM/JackPatch: Replace mutex in callback handling with ringbuffer (may help with JACK1 which runs the callbacks in the RT thread).

This commit is contained in:
Jonathan Moore Liles 2013-08-13 17:32:23 -07:00
parent d1c4fe418b
commit 21ab68d3e5
1 changed files with 50 additions and 53 deletions

View File

@ -42,14 +42,12 @@
#include <lo/lo.h> #include <lo/lo.h>
#include <pthread.h> #include <jack/ringbuffer.h>
int client_active = 0; int client_active = 0;
jack_client_t *client; jack_client_t *client;
pthread_mutex_t port_lock;
lo_server losrv; lo_server losrv;
lo_address nsm_addr; lo_address nsm_addr;
int nsm_is_active; int nsm_is_active;
@ -72,15 +70,21 @@ struct patch_record {
struct port_record { struct port_record {
char *port; char *port;
int reg; /* true if registered, false if unregistered */
struct port_record *next; struct port_record *next;
}; };
static struct port_record *new_ports = NULL; struct port_notification_record {
int len;
int reg; /* true if registered, false if unregistered */
char port[];
};
static struct port_record *known_ports = NULL; static struct port_record *known_ports = NULL;
static struct patch_record *patch_list = NULL; static struct patch_record *patch_list = NULL;
static jack_ringbuffer_t *port_ringbuffer = NULL;
/** /**
* Pretty-print patch relationship of /pr/ * Pretty-print patch relationship of /pr/
*/ */
@ -114,34 +118,18 @@ dequeue ( struct patch_record *pr )
} }
void void
enqueue_port ( struct port_record **q, const char *port, int reg ) enqueue_port ( struct port_record **q, const char *port )
{ {
struct port_record *p = malloc( sizeof( struct port_record )); struct port_record *p = malloc( sizeof( struct port_record ));
p->port = strdup( port ); p->port = strdup( port );
p->reg = reg;
p->next = *q; p->next = *q;
*q = p; *q = p;
} }
struct port_record *
dequeue_port ( struct port_record **q )
{
if ( *q )
{
struct port_record *p = *q;
*q = p->next;
return p;
}
return NULL;
}
void enqueue_known_port ( const char *port ) void enqueue_known_port ( const char *port )
{ {
enqueue_port( &known_ports, port, 1 ); enqueue_port( &known_ports, port );
} }
const char * find_known_port ( const char *port ) const char * find_known_port ( const char *port )
@ -155,29 +143,6 @@ const char * find_known_port ( const char *port )
return NULL; return NULL;
} }
void
enqueue_new_port ( const char *port, int reg )
{
pthread_mutex_lock( &port_lock );
enqueue_port( &new_ports, port, reg );
pthread_mutex_unlock( &port_lock );
}
struct port_record *
dequeue_new_port ( void )
{
pthread_mutex_lock( &port_lock );
struct port_record *p = dequeue_port( &new_ports );
pthread_mutex_unlock( &port_lock );
return p;
}
int int
process_patch ( const char *patch ) process_patch ( const char *patch )
{ {
@ -565,6 +530,8 @@ die ( void )
if ( client_active ) if ( client_active )
jack_deactivate( client ); jack_deactivate( client );
printf( "JACKPATCH: Closing jack client\n" );
jack_client_close( client ); jack_client_close( client );
client = NULL; client = NULL;
exit( 0 ); exit( 0 );
@ -719,11 +686,31 @@ init_osc ( const char *osc_port )
lo_server_add_method( losrv, "/reply", "ssss", osc_announce_reply, NULL ); lo_server_add_method( losrv, "/reply", "ssss", osc_announce_reply, NULL );
} }
struct port_notification_record *
dequeue_new_port ( void )
{
int size = 0;
if ( sizeof( int ) == jack_ringbuffer_peek( port_ringbuffer, (char*)&size, sizeof( int ) ) )
{
if ( jack_ringbuffer_read_space( port_ringbuffer ) >= size );
{
struct port_notification_record *pr = malloc( size );
jack_ringbuffer_read( port_ringbuffer, (char*)pr, size );
return pr;
}
}
return NULL;
}
void void
check_for_new_ports ( void ) check_for_new_ports ( void )
{ {
struct port_record *p = NULL; struct port_notification_record *p = NULL;
while ( ( p = dequeue_new_port() ) ) while ( ( p = dequeue_new_port() ) )
{ {
@ -732,7 +719,6 @@ check_for_new_ports ( void )
else else
remove_known_port( p->port ); remove_known_port( p->port );
free( p->port );
free( p ); free( p );
} }
} }
@ -741,10 +727,22 @@ void
port_registration_callback( jack_port_id_t id, int reg, void *arg ) port_registration_callback( jack_port_id_t id, int reg, void *arg )
{ {
jack_port_t *p = jack_port_by_id( client, id ); jack_port_t *p = jack_port_by_id( client, id );
const char *port = jack_port_name( p ); const char *port = jack_port_name( p );
enqueue_new_port( port, reg ); int size = strlen(port) + 1 + sizeof( struct port_notification_record );
struct port_notification_record *pr = malloc( size );
pr->len = size;
pr->reg = reg;
strcpy( pr->port, port );
if ( size != jack_ringbuffer_write( port_ringbuffer, (const char *)pr, size ) )
{
fprintf( stderr, "ERROR: port notification buffer overrun" );
}
// enqueue_new_port( port, reg );
} }
/* */ /* */
@ -767,8 +765,7 @@ main ( int argc, char **argv )
} }
pthread_mutex_init( &port_lock, NULL ); port_ringbuffer = jack_ringbuffer_create( 1024 * 8 );
set_traps(); set_traps();
@ -812,7 +809,7 @@ main ( int argc, char **argv )
for ( ;; ) for ( ;; )
{ {
lo_server_recv_noblock( losrv, 500 ); lo_server_recv_noblock( losrv, 200 );
if ( client_active ) if ( client_active )
check_for_new_ports(); check_for_new_ports();