git-svn-id: svn+ssh://jackaudio.org/trunk/jack@589 0c269be4-1314-0410-8aa9-9f06e86f4224tags/0.109.0
| @@ -14,8 +14,8 @@ dnl micro version = incremented when implementation-only | |||||
| dnl changes are made | dnl changes are made | ||||
| dnl --- | dnl --- | ||||
| JACK_MAJOR_VERSION=0 | JACK_MAJOR_VERSION=0 | ||||
| JACK_MINOR_VERSION=91 | |||||
| JACK_MICRO_VERSION=4 | |||||
| JACK_MINOR_VERSION=92 | |||||
| JACK_MICRO_VERSION=0 | |||||
| dnl --- | dnl --- | ||||
| dnl HOWTO: updating the jack protocal version | dnl HOWTO: updating the jack protocal version | ||||
| @@ -25,7 +25,7 @@ dnl made to the way libjack communicates with jackd | |||||
| dnl that would break applications linked with an older | dnl that would break applications linked with an older | ||||
| dnl version of libjack. | dnl version of libjack. | ||||
| dnl --- | dnl --- | ||||
| JACK_PROTOCOL_VERSION=11 | |||||
| JACK_PROTOCOL_VERSION=12 | |||||
| dnl --- | dnl --- | ||||
| dnl HOWTO: updating the libjack interface version | dnl HOWTO: updating the libjack interface version | ||||
| @@ -126,6 +126,20 @@ void signal_handler(int sig) | |||||
| /* Command functions: see commands[] table following. */ | /* Command functions: see commands[] table following. */ | ||||
| void com_activate(char *arg) | |||||
| { | |||||
| if (jack_activate(client)) { | |||||
| fprintf(stderr, "cannot activate client"); | |||||
| } | |||||
| } | |||||
| void com_deactivate(char *arg) | |||||
| { | |||||
| if (jack_deactivate(client)) { | |||||
| fprintf(stderr, "cannot deactivate client"); | |||||
| } | |||||
| } | |||||
| void com_exit(char *arg) | void com_exit(char *arg) | ||||
| { | { | ||||
| done = 1; | done = 1; | ||||
| @@ -203,7 +217,9 @@ typedef struct { | |||||
| /* command table must be in alphabetical order */ | /* command table must be in alphabetical order */ | ||||
| command_t commands[] = { | command_t commands[] = { | ||||
| {"activate", com_activate, "Call jack_activate()"}, | |||||
| {"exit", com_exit, "Exit transport program"}, | {"exit", com_exit, "Exit transport program"}, | ||||
| {"deactivate", com_deactivate, "Call jack_deactivate()"}, | |||||
| {"help", com_help, "Display help text [<command>]"}, | {"help", com_help, "Display help text [<command>]"}, | ||||
| {"locate", com_locate, "Locate to frame <position>"}, | {"locate", com_locate, "Locate to frame <position>"}, | ||||
| {"master", com_master, "Become timebase master " | {"master", com_master, "Become timebase master " | ||||
| @@ -96,7 +96,7 @@ typedef struct { | |||||
| int8_t new_pos; /* new position this cycle */ | int8_t new_pos; /* new position this cycle */ | ||||
| int8_t pending_pos; /* new position request pending */ | int8_t pending_pos; /* new position request pending */ | ||||
| jack_nframes_t pending_frame; /* pending frame number */ | jack_nframes_t pending_frame; /* pending frame number */ | ||||
| uint32_t sync_clients; /* number of is_slowsync clients */ | |||||
| uint32_t sync_clients; /* number of active slowsync clients */ | |||||
| uint32_t sync_remain; /* number of them with sync_poll */ | uint32_t sync_remain; /* number of them with sync_poll */ | ||||
| jack_time_t sync_timeout; | jack_time_t sync_timeout; | ||||
| jack_time_t sync_time_left; | jack_time_t sync_time_left; | ||||
| @@ -170,6 +170,7 @@ typedef volatile struct { | |||||
| volatile int8_t dead : 1; /* r/w: engine */ | volatile int8_t dead : 1; /* r/w: engine */ | ||||
| volatile int8_t timed_out : 1; /* r/w: engine */ | volatile int8_t timed_out : 1; /* r/w: engine */ | ||||
| volatile int8_t is_timebase : 1; /* w: engine, r: engine and client */ | volatile int8_t is_timebase : 1; /* w: engine, r: engine and client */ | ||||
| volatile int8_t timebase_new : 1; /* w: engine and client, r: engine */ | |||||
| volatile int8_t is_slowsync : 1; /* w: engine, r: engine and client */ | volatile int8_t is_slowsync : 1; /* w: engine, r: engine and client */ | ||||
| volatile int8_t sync_poll : 1; /* w: engine and client, r: engine */ | volatile int8_t sync_poll : 1; /* w: engine and client, r: engine */ | ||||
| volatile int8_t sync_new : 1; /* w: engine and client, r: engine */ | volatile int8_t sync_new : 1; /* w: engine and client, r: engine */ | ||||
| @@ -1447,12 +1447,13 @@ jack_client_activate (jack_engine_t *engine, jack_client_id_t id) | |||||
| client = (jack_client_internal_t *) node->data; | client = (jack_client_internal_t *) node->data; | ||||
| client->control->active = TRUE; | client->control->active = TRUE; | ||||
| /* we call this to make sure the | |||||
| FIFO is built+ready by the time | |||||
| the client needs it. we don't | |||||
| care about the return value at | |||||
| this point. | |||||
| */ | |||||
| jack_transport_activate(engine, client); | |||||
| /* we call this to make sure the FIFO is | |||||
| * built+ready by the time the client needs | |||||
| * it. we don't care about the return value at | |||||
| * this point. | |||||
| */ | |||||
| jack_get_fifo_fd (engine, | jack_get_fifo_fd (engine, | ||||
| ++engine->external_client_cnt); | ++engine->external_client_cnt); | ||||
| @@ -1476,6 +1477,8 @@ jack_client_do_deactivate (jack_engine_t *engine, | |||||
| * cleared all connections held by client. */ | * cleared all connections held by client. */ | ||||
| client->control->active = FALSE; | client->control->active = FALSE; | ||||
| jack_transport_client_exit (engine, client); | |||||
| if (!jack_client_is_internal (client) && | if (!jack_client_is_internal (client) && | ||||
| engine->external_client_cnt > 0) { | engine->external_client_cnt > 0) { | ||||
| engine->external_client_cnt--; | engine->external_client_cnt--; | ||||
| @@ -1527,16 +1530,13 @@ jack_client_deactivate (jack_engine_t *engine, jack_client_id_t id) | |||||
| JSList *portnode; | JSList *portnode; | ||||
| jack_port_internal_t *port; | jack_port_internal_t *port; | ||||
| jack_transport_client_exit (engine, client); | |||||
| for (portnode = client->ports; portnode; | for (portnode = client->ports; portnode; | ||||
| portnode = jack_slist_next (portnode)) { | portnode = jack_slist_next (portnode)) { | ||||
| port = (jack_port_internal_t *) portnode->data; | port = (jack_port_internal_t *) portnode->data; | ||||
| jack_port_clear_connections (engine, port); | jack_port_clear_connections (engine, port); | ||||
| } | } | ||||
| ret = jack_client_do_deactivate (engine, node->data, | |||||
| TRUE); | |||||
| ret = jack_client_do_deactivate (engine, client, TRUE); | |||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| @@ -68,8 +68,6 @@ jack_sync_poll_exit (jack_engine_t *engine, jack_client_internal_t *client) | |||||
| VERBOSE (engine, "sync poll interrupted for client %" | VERBOSE (engine, "sync poll interrupted for client %" | ||||
| PRIu32 "\n", client->control->id); | PRIu32 "\n", client->control->id); | ||||
| } | } | ||||
| client->control->is_slowsync = 0; | |||||
| engine->control->sync_clients--; | |||||
| } | } | ||||
| /* stop polling all the slow-sync clients | /* stop polling all the slow-sync clients | ||||
| @@ -85,6 +83,7 @@ jack_sync_poll_stop (jack_engine_t *engine) | |||||
| jack_client_internal_t *client = | jack_client_internal_t *client = | ||||
| (jack_client_internal_t *) node->data; | (jack_client_internal_t *) node->data; | ||||
| if (client->control->is_slowsync && | if (client->control->is_slowsync && | ||||
| client->control->active && | |||||
| client->control->sync_poll) { | client->control->sync_poll) { | ||||
| client->control->sync_poll = 0; | client->control->sync_poll = 0; | ||||
| poll_count++; | poll_count++; | ||||
| @@ -114,7 +113,8 @@ jack_sync_poll_start (jack_engine_t *engine) | |||||
| for (node = engine->clients; node; node = jack_slist_next (node)) { | for (node = engine->clients; node; node = jack_slist_next (node)) { | ||||
| jack_client_internal_t *client = | jack_client_internal_t *client = | ||||
| (jack_client_internal_t *) node->data; | (jack_client_internal_t *) node->data; | ||||
| if (client->control->is_slowsync) { | |||||
| if (client->control->is_slowsync && | |||||
| client->control->active) { | |||||
| client->control->sync_poll = 1; | client->control->sync_poll = 1; | ||||
| sync_count++; | sync_count++; | ||||
| } | } | ||||
| @@ -122,7 +122,7 @@ jack_sync_poll_start (jack_engine_t *engine) | |||||
| //JOQ: check invariant for debugging... | //JOQ: check invariant for debugging... | ||||
| assert (sync_count == engine->control->sync_clients); | assert (sync_count == engine->control->sync_clients); | ||||
| engine->control->sync_remain = engine->control->sync_clients; | |||||
| engine->control->sync_remain = sync_count; | |||||
| engine->control->sync_time_left = engine->control->sync_timeout; | engine->control->sync_time_left = engine->control->sync_timeout; | ||||
| VERBOSE (engine, "transport Starting, sync poll of %" PRIu32 | VERBOSE (engine, "transport Starting, sync poll of %" PRIu32 | ||||
| " clients for %8.6f secs\n", engine->control->sync_remain, | " clients for %8.6f secs\n", engine->control->sync_remain, | ||||
| @@ -177,6 +177,7 @@ jack_timebase_reset (jack_engine_t *engine, jack_client_id_t client_id) | |||||
| client = jack_client_internal_by_id (engine, client_id); | client = jack_client_internal_by_id (engine, client_id); | ||||
| if (client && (client == engine->timebase_client)) { | if (client && (client == engine->timebase_client)) { | ||||
| client->control->is_timebase = 0; | client->control->is_timebase = 0; | ||||
| client->control->timebase_new = 0; | |||||
| engine->timebase_client = NULL; | engine->timebase_client = NULL; | ||||
| ectl->pending_time.valid = 0; | ectl->pending_time.valid = 0; | ||||
| VERBOSE (engine, "%s resigned as timebase master\n", | VERBOSE (engine, "%s resigned as timebase master\n", | ||||
| @@ -223,10 +224,14 @@ jack_timebase_set (jack_engine_t *engine, | |||||
| } else { | } else { | ||||
| if (engine->timebase_client) | |||||
| if (engine->timebase_client) { | |||||
| engine->timebase_client->control->is_timebase = 0; | engine->timebase_client->control->is_timebase = 0; | ||||
| engine->timebase_client->control->timebase_new = 0; | |||||
| } | |||||
| engine->timebase_client = client; | engine->timebase_client = client; | ||||
| client->control->is_timebase = 1; | client->control->is_timebase = 1; | ||||
| if (client->control->active) | |||||
| client->control->timebase_new = 1; | |||||
| VERBOSE (engine, "new timebase master: %s\n", | VERBOSE (engine, "new timebase master: %s\n", | ||||
| client->control->name); | client->control->name); | ||||
| } | } | ||||
| @@ -236,6 +241,22 @@ jack_timebase_set (jack_engine_t *engine, | |||||
| return ret; | return ret; | ||||
| } | } | ||||
| /* for client activation | |||||
| * | |||||
| * precondition: caller holds the graph lock. */ | |||||
| void | |||||
| jack_transport_activate (jack_engine_t *engine, jack_client_internal_t *client) | |||||
| { | |||||
| if (client->control->is_slowsync) { | |||||
| engine->control->sync_clients++; | |||||
| jack_sync_poll_new (engine, client); | |||||
| } | |||||
| if (client->control->is_timebase) { | |||||
| client->control->timebase_new = 1; | |||||
| } | |||||
| } | |||||
| /* for engine initialization */ | /* for engine initialization */ | ||||
| void | void | ||||
| jack_transport_init (jack_engine_t *engine) | jack_transport_init (jack_engine_t *engine) | ||||
| @@ -260,7 +281,7 @@ jack_transport_init (jack_engine_t *engine) | |||||
| ectl->sync_time_left = 0; | ectl->sync_time_left = 0; | ||||
| } | } | ||||
| /* when any client exits the graph | |||||
| /* when any client exits the graph (either dead or not active) | |||||
| * | * | ||||
| * precondition: caller holds the graph lock */ | * precondition: caller holds the graph lock */ | ||||
| void | void | ||||
| @@ -268,15 +289,22 @@ jack_transport_client_exit (jack_engine_t *engine, | |||||
| jack_client_internal_t *client) | jack_client_internal_t *client) | ||||
| { | { | ||||
| if (client == engine->timebase_client) { | if (client == engine->timebase_client) { | ||||
| engine->timebase_client->control->is_timebase = 0; | |||||
| engine->timebase_client = NULL; | |||||
| if (client->control->dead) { | |||||
| engine->timebase_client->control->is_timebase = 0; | |||||
| engine->timebase_client->control->timebase_new = 0; | |||||
| engine->timebase_client = NULL; | |||||
| VERBOSE (engine, "timebase master exit\n"); | |||||
| } | |||||
| engine->control->current_time.valid = 0; | engine->control->current_time.valid = 0; | ||||
| engine->control->pending_time.valid = 0; | engine->control->pending_time.valid = 0; | ||||
| VERBOSE (engine, "timebase master exit\n"); | |||||
| } | } | ||||
| if (client->control->is_slowsync) | |||||
| if (client->control->is_slowsync) { | |||||
| jack_sync_poll_exit(engine, client); | jack_sync_poll_exit(engine, client); | ||||
| engine->control->sync_clients--; | |||||
| if (client->control->dead) | |||||
| client->control->is_slowsync = 0; | |||||
| } | |||||
| } | } | ||||
| /* when a new client is being created */ | /* when a new client is being created */ | ||||
| @@ -284,6 +312,7 @@ void | |||||
| jack_transport_client_new (jack_client_internal_t *client) | jack_transport_client_new (jack_client_internal_t *client) | ||||
| { | { | ||||
| client->control->is_timebase = 0; | client->control->is_timebase = 0; | ||||
| client->control->timebase_new = 0; | |||||
| client->control->is_slowsync = 0; | client->control->is_slowsync = 0; | ||||
| client->control->sync_poll = 0; | client->control->sync_poll = 0; | ||||
| client->control->sync_new = 0; | client->control->sync_new = 0; | ||||
| @@ -307,6 +336,9 @@ jack_transport_client_reset_sync (jack_engine_t *engine, | |||||
| if (client && (client->control->is_slowsync)) { | if (client && (client->control->is_slowsync)) { | ||||
| jack_sync_poll_exit(engine, client); | jack_sync_poll_exit(engine, client); | ||||
| client->control->is_slowsync = 0; | |||||
| if (client->control->active) | |||||
| engine->control->sync_clients--; | |||||
| ret = 0; | ret = 0; | ||||
| } else | } else | ||||
| ret = EINVAL; | ret = EINVAL; | ||||
| @@ -332,11 +364,13 @@ jack_transport_client_set_sync (jack_engine_t *engine, | |||||
| if (client) { | if (client) { | ||||
| if (!client->control->is_slowsync) { | if (!client->control->is_slowsync) { | ||||
| client->control->is_slowsync = 1; | client->control->is_slowsync = 1; | ||||
| engine->control->sync_clients++; | |||||
| if (client->control->active) | |||||
| engine->control->sync_clients++; | |||||
| } | } | ||||
| /* force poll of the new slow-sync client */ | |||||
| jack_sync_poll_new (engine, client); | |||||
| /* force poll of the new slow-sync client, if active */ | |||||
| if (client->control->active) | |||||
| jack_sync_poll_new (engine, client); | |||||
| ret = 0; | ret = 0; | ||||
| } else | } else | ||||
| ret = EINVAL; | ret = EINVAL; | ||||
| @@ -23,6 +23,8 @@ int jack_timebase_reset (jack_engine_t *engine, | |||||
| jack_client_id_t client_id); | jack_client_id_t client_id); | ||||
| int jack_timebase_set (jack_engine_t *engine, | int jack_timebase_set (jack_engine_t *engine, | ||||
| jack_client_id_t client_id, int conditional); | jack_client_id_t client_id, int conditional); | ||||
| void jack_transport_activate (jack_engine_t *engine, | |||||
| jack_client_internal_t *client); | |||||
| void jack_transport_init (jack_engine_t *engine); | void jack_transport_init (jack_engine_t *engine); | ||||
| void jack_transport_client_exit (jack_engine_t *engine, | void jack_transport_client_exit (jack_engine_t *engine, | ||||
| jack_client_internal_t *client); | jack_client_internal_t *client); | ||||
| @@ -29,7 +29,6 @@ struct _jack_client { | |||||
| void *on_shutdown_arg; | void *on_shutdown_arg; | ||||
| char thread_ok : 1; | char thread_ok : 1; | ||||
| char first_active : 1; | char first_active : 1; | ||||
| char new_timebase : 1; | |||||
| pthread_t thread_id; | pthread_t thread_id; | ||||
| #if defined(__APPLE__) && defined(__POWERPC__) | #if defined(__APPLE__) && defined(__POWERPC__) | ||||
| @@ -175,8 +175,8 @@ jack_call_timebase_master (jack_client_t *client) | |||||
| * critical section; timebase_cb is not. */ | * critical section; timebase_cb is not. */ | ||||
| if (control->is_timebase) { | if (control->is_timebase) { | ||||
| if (client->new_timebase) { /* first callback? */ | |||||
| client->new_timebase = 0; | |||||
| if (control->timebase_new) { /* first callback? */ | |||||
| control->timebase_new = 0; | |||||
| new_pos = 1; | new_pos = 1; | ||||
| } | } | ||||
| @@ -194,7 +194,6 @@ jack_call_timebase_master (jack_client_t *client) | |||||
| } else { | } else { | ||||
| /* another master took over, so resign */ | /* another master took over, so resign */ | ||||
| client->new_timebase = 0; | |||||
| control->timebase_cb = NULL; | control->timebase_cb = NULL; | ||||
| control->timebase_arg = NULL; | control->timebase_arg = NULL; | ||||
| } | } | ||||
| @@ -300,7 +299,6 @@ jack_release_timebase (jack_client_t *client) | |||||
| rc = jack_client_deliver_request (client, &req); | rc = jack_client_deliver_request (client, &req); | ||||
| if (rc == 0) { | if (rc == 0) { | ||||
| client->new_timebase = 0; | |||||
| ctl->timebase_cb = NULL; | ctl->timebase_cb = NULL; | ||||
| ctl->timebase_arg = NULL; | ctl->timebase_arg = NULL; | ||||
| } | } | ||||
| @@ -354,7 +352,6 @@ jack_set_timebase_callback (jack_client_t *client, int conditional, | |||||
| rc = jack_client_deliver_request (client, &req); | rc = jack_client_deliver_request (client, &req); | ||||
| if (rc == 0) { | if (rc == 0) { | ||||
| client->new_timebase = 1; | |||||
| ctl->timebase_arg = arg; | ctl->timebase_arg = arg; | ||||
| ctl->timebase_cb = timebase_cb; | ctl->timebase_cb = timebase_cb; | ||||
| } | } | ||||