From 156b955fb4b0e707b9c9831e078934bd5cd361a0 Mon Sep 17 00:00:00 2001 From: paul Date: Fri, 8 Jun 2007 13:11:58 +0000 Subject: [PATCH] fix up port connection notification design; extend evmon client to test it git-svn-id: svn+ssh://jackaudio.org/trunk/jack@1047 0c269be4-1314-0410-8aa9-9f06e86f4224 --- configure.ac | 2 +- example-clients/evmon.c | 11 ++++- jack/jack.h | 2 +- jack/types.h | 2 +- jackd/engine.c | 46 +++++++++++++++++- libjack/client.c | 104 ++++++++++++++++++++-------------------- 6 files changed, 110 insertions(+), 57 deletions(-) diff --git a/configure.ac b/configure.ac index c506e07..84b66c2 100644 --- a/configure.ac +++ b/configure.ac @@ -17,7 +17,7 @@ dnl changes are made dnl --- JACK_MAJOR_VERSION=0 JACK_MINOR_VERSION=107 -JACK_MICRO_VERSION=0 +JACK_MICRO_VERSION=1 dnl --- dnl HOWTO: updating the jack protocol version diff --git a/example-clients/evmon.c b/example-clients/evmon.c index 279846b..32b9978 100644 --- a/example-clients/evmon.c +++ b/example-clients/evmon.c @@ -30,6 +30,12 @@ port_callback (jack_port_id_t port, int yn, void* arg) printf ("Port %d %s\n", port, (yn ? "registered" : "unregistered")); } +void +connect_callback (jack_port_id_t a, jack_port_id_t b, int yn, void* arg) +{ + printf ("Ports %d and %d %s\n", a, b, (yn ? "connected" : "disconnected")); +} + void client_callback (const char* client, int yn, void* arg) { @@ -63,6 +69,10 @@ main (int argc, char *argv[]) fprintf (stderr, "cannot set port registration callback\n"); return 1; } + if (jack_set_port_connect_callback (client, connect_callback, NULL)) { + fprintf (stderr, "cannot set port connect callback\n"); + return 1; + } if (jack_set_client_registration_callback (client, client_callback, NULL)) { fprintf (stderr, "cannot set client registration callback\n"); return 1; @@ -71,7 +81,6 @@ main (int argc, char *argv[]) fprintf (stderr, "cannot set graph order registration callback\n"); return 1; } - if (jack_activate (client)) { fprintf (stderr, "cannot activate client"); return 1; diff --git a/jack/jack.h b/jack/jack.h index ec8df56..929fe82 100644 --- a/jack/jack.h +++ b/jack/jack.h @@ -311,7 +311,7 @@ int jack_set_port_registration_callback (jack_client_t *, /** * Tell the JACK server to call @a connect_callback whenever a - * port is registered or unregistered, passing @a arg as a parameter. + * port is connected or disconnected, passing @a arg as a parameter. * * @return 0 on success, otherwise a non-zero error code */ diff --git a/jack/types.h b/jack/types.h index c5a3467..b997c57 100644 --- a/jack/types.h +++ b/jack/types.h @@ -182,7 +182,7 @@ typedef void (*JackClientRegistrationCallback)(const char* name, int register, v * zero if ports were disconnected * @param arg pointer to a client supplied data */ -typedef void (*JackPortConnectCallback)(jack_port_t* a, jack_port_t* b, int connect, void* arg); +typedef void (*JackPortConnectCallback)(jack_port_id_t a, jack_port_id_t b, int connect, void* arg); /** * Prototype for the client supplied function that is called diff --git a/jackd/engine.c b/jackd/engine.c index 872b0aa..a0732a5 100644 --- a/jackd/engine.c +++ b/jackd/engine.c @@ -108,6 +108,10 @@ static int jack_deliver_event (jack_engine_t *, jack_client_internal_t *, jack_event_t *); static void jack_deliver_event_to_all (jack_engine_t *engine, jack_event_t *event); +static void jack_notify_all_port_interested_clients (jack_engine_t *engine, + jack_port_id_t a, + jack_port_id_t b, + int connect); static void jack_engine_post_process (jack_engine_t *); static int jack_use_driver (jack_engine_t *engine, jack_driver_t *driver); static int jack_run_cycle (jack_engine_t *engine, jack_nframes_t nframes, @@ -2276,6 +2280,34 @@ jack_deliver_event_to_all (jack_engine_t *engine, jack_event_t *event) jack_unlock_graph (engine); } +static void +jack_notify_all_port_interested_clients (jack_engine_t *engine, jack_port_id_t a, jack_port_id_t b, int connected) +{ + JSList *node; + jack_event_t event; + + event.type = (connected ? PortConnected : PortDisconnected); + event.x.self_id = a; + event.y.other_id = b; + + /* GRAPH MUST BE LOCKED : see callers of jack_send_connection_notification() + */ + + for (node = engine->clients; node; node = jack_slist_next (node)) { + jack_client_internal_t* client; + + client = (jack_client_internal_t*) node->data; + + if (client->control->port_connect != NULL) { + + /* one of the ports belong to this client or it has a port connect callback */ + + jack_deliver_event (engine, client, &event); + + } + } +} + static int jack_deliver_event (jack_engine_t *engine, jack_client_internal_t *client, jack_event_t *event) @@ -3128,10 +3160,16 @@ jack_port_do_connect (jack_engine_t *engine, jack_send_connection_notification (engine, srcport->shared->client_id, src_id, dst_id, TRUE); + + jack_send_connection_notification (engine, dstport->shared->client_id, dst_id, src_id, TRUE); + /* send a port connection notification just once to everyone who cares */ + + jack_notify_all_port_interested_clients (engine, src_id, dst_id, 1); + jack_sort_graph (engine); } @@ -3193,6 +3231,10 @@ jack_port_disconnect_internal (jack_engine_t *engine, engine, dstport->shared->client_id, dst_id, src_id, FALSE); + /* send a port connection notification just once to everyone who cares */ + + jack_notify_all_port_interested_clients (engine, src_id, dst_id, 0); + if (connect->dir) { jack_client_internal_t *src; @@ -3812,8 +3854,8 @@ jack_send_connection_notification (jack_engine_t *engine, { jack_client_internal_t *client; - jack_event_t event; - + jack_event_t event; + if ((client = jack_client_internal_by_id (engine, client_id)) == NULL) { jack_error ("no such client %" PRIu32 " during connection notification", client_id); diff --git a/libjack/client.c b/libjack/client.c index b077624..b3956b4 100644 --- a/libjack/client.c +++ b/libjack/client.c @@ -426,62 +426,64 @@ jack_client_handle_port_connection (jack_client_t *client, jack_event_t *event) JSList *node; int need_free = FALSE; - switch (event->type) { - case PortConnected: - other = jack_port_new (client, event->y.other_id, - client->engine); - /* jack_port_by_id_int() always returns an internal - * port that does not need to be deallocated */ - control_port = jack_port_by_id_int (client, event->x.self_id, - &need_free); - pthread_mutex_lock (&control_port->connection_lock); - control_port->connections = - jack_slist_prepend (control_port->connections, - (void *) other); - pthread_mutex_unlock (&control_port->connection_lock); - - if (client->control->port_connect) { - client->control->port_connect (control_port, other, 1, client->control->port_connect_arg); - } - - break; + if (client->engine->ports[event->x.self_id].client_id == client->control->id || + client->engine->ports[event->y.other_id].client_id == client->control->id) { - case PortDisconnected: - /* jack_port_by_id_int() always returns an internal - * port that does not need to be deallocated */ - control_port = jack_port_by_id_int (client, event->x.self_id, - &need_free); - pthread_mutex_lock (&control_port->connection_lock); + /* its one of ours */ - for (node = control_port->connections; node; - node = jack_slist_next (node)) { - - other = (jack_port_t *) node->data; - - if (other->shared->id == event->y.other_id) { - control_port->connections = - jack_slist_remove_link ( - control_port->connections, - node); - break; - } - } - - pthread_mutex_unlock (&control_port->connection_lock); - - if (node) { - if (client->control->port_connect) { - client->control->port_connect (control_port, other, 0, client->control->port_connect_arg); + switch (event->type) { + case PortConnected: + other = jack_port_new (client, event->y.other_id, + client->engine); + /* jack_port_by_id_int() always returns an internal + * port that does not need to be deallocated + */ + control_port = jack_port_by_id_int (client, event->x.self_id, + &need_free); + pthread_mutex_lock (&control_port->connection_lock); + control_port->connections = + jack_slist_prepend (control_port->connections, + (void *) other); + pthread_mutex_unlock (&control_port->connection_lock); + break; + + case PortDisconnected: + /* jack_port_by_id_int() always returns an internal + * port that does not need to be deallocated + */ + control_port = jack_port_by_id_int (client, event->x.self_id, + &need_free); + pthread_mutex_lock (&control_port->connection_lock); + + for (node = control_port->connections; node; + node = jack_slist_next (node)) { + + other = (jack_port_t *) node->data; + + if (other->shared->id == event->y.other_id) { + control_port->connections = + jack_slist_remove_link ( + control_port->connections, + node); + jack_slist_free_1 (node); + free (other); + break; + } } - jack_slist_free_1 (node); - free (other); + + pthread_mutex_unlock (&control_port->connection_lock); + break; + + default: + /* impossible */ + break; } + } - break; - - default: - /* impossible */ - break; + if (client->control->port_connect) { + client->control->port_connect (event->x.self_id, event->y.other_id, + (event->type == PortConnected ? 1 : 0), + client->control->port_connect_arg); } return 0;