git-svn-id: svn+ssh://jackaudio.org/trunk/jack@1047 0c269be4-1314-0410-8aa9-9f06e86f4224tags/0.109.0
@@ -17,7 +17,7 @@ dnl changes are made | |||||
dnl --- | dnl --- | ||||
JACK_MAJOR_VERSION=0 | JACK_MAJOR_VERSION=0 | ||||
JACK_MINOR_VERSION=107 | JACK_MINOR_VERSION=107 | ||||
JACK_MICRO_VERSION=0 | |||||
JACK_MICRO_VERSION=1 | |||||
dnl --- | dnl --- | ||||
dnl HOWTO: updating the jack protocol version | dnl HOWTO: updating the jack protocol version | ||||
@@ -30,6 +30,12 @@ port_callback (jack_port_id_t port, int yn, void* arg) | |||||
printf ("Port %d %s\n", port, (yn ? "registered" : "unregistered")); | 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 | void | ||||
client_callback (const char* client, int yn, void* arg) | 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"); | fprintf (stderr, "cannot set port registration callback\n"); | ||||
return 1; | 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)) { | if (jack_set_client_registration_callback (client, client_callback, NULL)) { | ||||
fprintf (stderr, "cannot set client registration callback\n"); | fprintf (stderr, "cannot set client registration callback\n"); | ||||
return 1; | return 1; | ||||
@@ -71,7 +81,6 @@ main (int argc, char *argv[]) | |||||
fprintf (stderr, "cannot set graph order registration callback\n"); | fprintf (stderr, "cannot set graph order registration callback\n"); | ||||
return 1; | return 1; | ||||
} | } | ||||
if (jack_activate (client)) { | if (jack_activate (client)) { | ||||
fprintf (stderr, "cannot activate client"); | fprintf (stderr, "cannot activate client"); | ||||
return 1; | return 1; | ||||
@@ -311,7 +311,7 @@ int jack_set_port_registration_callback (jack_client_t *, | |||||
/** | /** | ||||
* Tell the JACK server to call @a connect_callback whenever a | * 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 | * @return 0 on success, otherwise a non-zero error code | ||||
*/ | */ | ||||
@@ -182,7 +182,7 @@ typedef void (*JackClientRegistrationCallback)(const char* name, int register, v | |||||
* zero if ports were disconnected | * zero if ports were disconnected | ||||
* @param arg pointer to a client supplied data | * @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 | * Prototype for the client supplied function that is called | ||||
@@ -108,6 +108,10 @@ static int jack_deliver_event (jack_engine_t *, jack_client_internal_t *, | |||||
jack_event_t *); | jack_event_t *); | ||||
static void jack_deliver_event_to_all (jack_engine_t *engine, | static void jack_deliver_event_to_all (jack_engine_t *engine, | ||||
jack_event_t *event); | 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 void jack_engine_post_process (jack_engine_t *); | ||||
static int jack_use_driver (jack_engine_t *engine, jack_driver_t *driver); | 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, | 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); | 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 | static int | ||||
jack_deliver_event (jack_engine_t *engine, jack_client_internal_t *client, | jack_deliver_event (jack_engine_t *engine, jack_client_internal_t *client, | ||||
jack_event_t *event) | jack_event_t *event) | ||||
@@ -3128,10 +3160,16 @@ jack_port_do_connect (jack_engine_t *engine, | |||||
jack_send_connection_notification (engine, | jack_send_connection_notification (engine, | ||||
srcport->shared->client_id, | srcport->shared->client_id, | ||||
src_id, dst_id, TRUE); | src_id, dst_id, TRUE); | ||||
jack_send_connection_notification (engine, | jack_send_connection_notification (engine, | ||||
dstport->shared->client_id, | dstport->shared->client_id, | ||||
dst_id, src_id, TRUE); | 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); | jack_sort_graph (engine); | ||||
} | } | ||||
@@ -3193,6 +3231,10 @@ jack_port_disconnect_internal (jack_engine_t *engine, | |||||
engine, dstport->shared->client_id, dst_id, | engine, dstport->shared->client_id, dst_id, | ||||
src_id, FALSE); | 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) { | if (connect->dir) { | ||||
jack_client_internal_t *src; | jack_client_internal_t *src; | ||||
@@ -3812,8 +3854,8 @@ jack_send_connection_notification (jack_engine_t *engine, | |||||
{ | { | ||||
jack_client_internal_t *client; | jack_client_internal_t *client; | ||||
jack_event_t event; | |||||
jack_event_t event; | |||||
if ((client = jack_client_internal_by_id (engine, client_id)) == NULL) { | if ((client = jack_client_internal_by_id (engine, client_id)) == NULL) { | ||||
jack_error ("no such client %" PRIu32 | jack_error ("no such client %" PRIu32 | ||||
" during connection notification", client_id); | " during connection notification", client_id); | ||||
@@ -426,62 +426,64 @@ jack_client_handle_port_connection (jack_client_t *client, jack_event_t *event) | |||||
JSList *node; | JSList *node; | ||||
int need_free = FALSE; | 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; | return 0; | ||||