From 02b141f674444e259f83f5fa3918a74cd8c153ed Mon Sep 17 00:00:00 2001 From: pbd Date: Wed, 6 Feb 2002 02:59:15 +0000 Subject: [PATCH] latest changes related to ardour (DAW) support git-svn-id: svn+ssh://jackaudio.org/trunk/jack@96 0c269be4-1314-0410-8aa9-9f06e86f4224 --- alsa_driver.c | 4 +- client.c | 121 +++++++++++++++++++++++++++++++++--------------- configure.in | 2 +- engine.c | 16 ++++--- jack/engine.h | 2 +- jack/internal.h | 4 +- jack/jack.h | 101 +++++++++++++++++++++++++++++++--------- 7 files changed, 175 insertions(+), 75 deletions(-) diff --git a/alsa_driver.c b/alsa_driver.c index 4993535..357a19f 100644 --- a/alsa_driver.c +++ b/alsa_driver.c @@ -723,7 +723,7 @@ alsa_driver_wait (alsa_driver_t *driver) for (i = 0; i < nfds; i++) { driver->pfd[nfds].events |= POLLERR; } - + if (poll (driver->pfd, nfds, 1000) < 0) { if (errno == EINTR) { printf ("poll interrupt\n"); @@ -789,7 +789,7 @@ alsa_driver_wait (alsa_driver_t *driver) } } - + xrun_detected = FALSE; if ((capture_avail = snd_pcm_avail_update (driver->capture_handle)) < 0) { diff --git a/client.c b/client.c index cc2873d..1f04ca6 100644 --- a/client.c +++ b/client.c @@ -72,7 +72,7 @@ struct _jack_client { GSList *port_segments; GSList *ports; pthread_t thread; - char fifo_prefix[FIFO_NAME_SIZE+1]; + char fifo_prefix[PATH_MAX+1]; void (*on_shutdown)(void *arg); void *on_shutdown_arg; char thread_ok : 1; @@ -141,25 +141,6 @@ jack_port_by_id (jack_client_t *client, jack_port_id_t id) return NULL; } -static jack_port_shared_t * -jack_shared_port_by_name (jack_client_t *client, const char *port_name) - -{ - unsigned long i, limit; - jack_port_shared_t *port; - - limit = client->engine->port_max; - port = &client->engine->ports[0]; - - for (i = 0; i < limit; i++) { - if (port[i].in_use && strcmp (port[i].name, port_name) == 0) { - return &port[i]; - } - } - - return NULL; -} - jack_port_t * jack_port_by_name (jack_client_t *client, const char *port_name) { @@ -252,7 +233,7 @@ jack_client_handle_port_connection (jack_client_t *client, jack_event_t *event) static int jack_handle_reorder (jack_client_t *client, jack_event_t *event) { - char path[FIFO_NAME_SIZE+1]; + char path[PATH_MAX+1]; if (client->graph_wait_fd >= 0) { close (client->graph_wait_fd); @@ -1341,16 +1322,13 @@ int jack_port_request_monitor_by_name (jack_client_t *client, const char *port_name, int onoff) { - jack_port_shared_t *port; + jack_port_t *port; - if ((port = jack_shared_port_by_name (client, port_name)) != NULL) { - if (onoff) { - port->monitor_requests++; - } else if (port->monitor_requests) { - port->monitor_requests--; - } - return 0; + if ((port = jack_port_by_name (client, port_name)) != NULL) { + return jack_port_request_monitor (port, onoff); + free (port); } + return -1; } @@ -1363,6 +1341,30 @@ jack_port_request_monitor (jack_port_t *port, int onoff) } else if (port->shared->monitor_requests) { port->shared->monitor_requests--; } + + if ((port->shared->flags & JackPortIsOutput) == 0) { + + GSList *node; + + /* this port is for input, so recurse over each of the + connected ports. + */ + + pthread_mutex_lock (&port->connection_lock); + for (node = port->connections; node; node = g_slist_next (node)) { + + /* drop the lock because if there is a feedback loop, + we will deadlock. XXX much worse things will + happen if there is a feedback loop !!! + */ + + pthread_mutex_unlock (&port->connection_lock); + jack_port_request_monitor ((jack_port_t *) node->data, onoff); + pthread_mutex_lock (&port->connection_lock); + } + pthread_mutex_unlock (&port->connection_lock); + } + return 0; } @@ -1416,12 +1418,6 @@ jack_port_type (const jack_port_t *port) return port->shared->type_info.type_name; } -int -jack_port_equal (const jack_port_t *a, const jack_port_t *b) -{ - return a->shared == b->shared; -} - int jack_port_set_name (jack_port_t *port, const char *new_name) { @@ -1442,14 +1438,14 @@ jack_on_shutdown (jack_client_t *client, void (*function)(void *arg), void *arg) client->on_shutdown_arg = arg; } -char * const * +const char ** jack_get_ports (jack_client_t *client, const char *port_name_pattern, const char *type_name_pattern, unsigned long flags) { jack_control_t *engine; - char **matching_ports; + const char **matching_ports; unsigned long match_cnt; jack_port_shared_t *psp; unsigned long i; @@ -1469,7 +1465,7 @@ jack_get_ports (jack_client_t *client, psp = engine->ports; match_cnt = 0; - matching_ports = (char **) malloc (sizeof (char *) * engine->port_max); + matching_ports = (const char **) malloc (sizeof (char *) * engine->port_max); for (i = 0; i < engine->port_max; i++) { matching = 1; @@ -1582,6 +1578,33 @@ jack_audio_port_mixdown (jack_port_t *port, nframes_t nframes) } } +const char ** +jack_port_get_connections (const jack_port_t *port) +{ + const char **ret; + GSList *node; + unsigned int n; + + pthread_mutex_lock (&((jack_port_t *) port)->connection_lock); + + if (port->connections == NULL) { + pthread_mutex_unlock (&((jack_port_t *) port)->connection_lock); + return NULL; + } + + ret = (const char **) malloc (sizeof (char *) * (g_slist_length (port->connections) + 1)); + + for (n = 0, node = port->connections; node; node = g_slist_next (node), n++) { + ret[n] = ((jack_port_t *) node->data)->shared->name; + } + + ret[n] = NULL; + + pthread_mutex_unlock (&((jack_port_t *) port)->connection_lock); + + return ret; +} + int jack_port_connected (const jack_port_t *port) { @@ -1608,3 +1631,25 @@ jack_port_connected_to (const jack_port_t *port, const char *portname) pthread_mutex_unlock (&((jack_port_t *) port)->connection_lock); return ret; } + +int +jack_port_connected_to_port (const jack_port_t *port, const jack_port_t *other_port) +{ + GSList *node; + int ret = FALSE; + + pthread_mutex_lock (&((jack_port_t *) port)->connection_lock); + + for (node = port->connections; node; node = g_slist_next (node)) { + + jack_port_t *this_port = (jack_port_t *) node->data; + + if (other_port->shared == this_port->shared) { + ret = TRUE; + break; + } + } + + pthread_mutex_unlock (&((jack_port_t *) port)->connection_lock); + return ret; +} diff --git a/configure.in b/configure.in index aeb6b04..d0315a0 100644 --- a/configure.in +++ b/configure.in @@ -4,7 +4,7 @@ AC_INIT(client.c) AC_CONFIG_AUX_DIR(.) JACK_MAJOR_VERSION=0 -JACK_MINOR_VERSION=8 +JACK_MINOR_VERSION=9 JACK_MICRO_VERSION=0 BETA= diff --git a/engine.c b/engine.c index 9ba8926..74441b7 100644 --- a/engine.c +++ b/engine.c @@ -298,7 +298,7 @@ jack_cleanup_files () char fullpath[PATH_MAX+1]; sprintf (fullpath, "%s/%s", jack_temp_dir, dirent->d_name); unlink (fullpath); - } + } } closedir (dir); @@ -1138,7 +1138,7 @@ jack_engine_new (int realtime, int rtpriority) engine->control->time.frame_rate = 0; engine->control->time.frame = 0; - sprintf (engine->fifo_prefix, "%s/ack_fifo_%d", jack_temp_dir, getpid()); + snprintf (engine->fifo_prefix, sizeof (engine->fifo_prefix), "%s/jack-ack-fifo-%d", jack_temp_dir, getpid()); (void) jack_get_fifo_fd (engine, 0); jack_start_server (engine); @@ -1810,22 +1810,24 @@ jack_port_do_connect (jack_engine_t *engine, } if ((dstport->shared->flags & JackPortIsInput) == 0) { - jack_error ("destination port in attempted connection is not an input port"); + jack_error ("destination port in attempted connection of %s and %s is not an input port", + source_port, destination_port); return -1; } if ((srcport->shared->flags & JackPortIsOutput) == 0) { - jack_error ("source port in attempted connection is not an output port"); + jack_error ("source port in attempted connection of %s and %s is not an output port", + source_port, destination_port); return -1; } if (srcport->shared->locked) { - jack_error ("source port is locked against connection changes"); + jack_error ("source port %s is locked against connection changes", source_port); return -1; } if (dstport->shared->locked) { - jack_error ("destination port is locked against connection changes"); + jack_error ("destination port %s is locked against connection changes", destination_port); return -1; } @@ -2018,7 +2020,7 @@ static int jack_get_fifo_fd (jack_engine_t *engine, int which_fifo) { - char path[FIFO_NAME_SIZE+1]; + char path[PATH_MAX+1]; struct stat statbuf; sprintf (path, "%s-%d", engine->fifo_prefix, which_fifo); diff --git a/jack/engine.h b/jack/engine.h index a97f412..5f1dd27 100644 --- a/jack/engine.h +++ b/jack/engine.h @@ -68,7 +68,7 @@ struct _jack_engine { struct pollfd *pfd; struct _jack_client_internal *timebase_client; jack_port_buffer_info_t *silent_buffer; - char fifo_prefix[FIFO_NAME_SIZE+1]; + char fifo_prefix[PATH_MAX+1]; int *fifo; unsigned long fifo_size; unsigned long external_client_cnt; diff --git a/jack/internal.h b/jack/internal.h index e1086c6..91a5b33 100644 --- a/jack/internal.h +++ b/jack/internal.h @@ -34,8 +34,6 @@ #include #include -#define FIFO_NAME_SIZE 32 - typedef void * dlhandle; typedef struct { @@ -161,7 +159,7 @@ typedef struct { int client_key; int control_key; - char fifo_prefix[FIFO_NAME_SIZE+1]; + char fifo_prefix[PATH_MAX+1]; int realtime; int realtime_priority; diff --git a/jack/jack.h b/jack/jack.h index 6c6facd..716abb5 100644 --- a/jack/jack.h +++ b/jack/jack.h @@ -34,7 +34,7 @@ int jack_client_close (jack_client_t *client); /* register a function (and argument) to be called if and when the JACK server shuts down the client thread. the function must be written as if it were an asynchonrous POSIX signal - handler - use only async functions, and remember that it + handler - use only async-safe functions, and remember that it is executed from another thread. a typical function might set a flag or write to a pipe so that the rest of the application knows that the JACK client thread has shut @@ -45,7 +45,10 @@ int jack_client_close (jack_client_t *client); on. if called, it must be called before jack_client_activate(). */ -void jack_on_shutdown (jack_client_t *, void (*function)(void *arg), void *arg); +void jack_on_shutdown (jack_client_t *, void (*function)(void *arg), void *arg); + +/* see simple_client.c to understand what these do. + */ int jack_set_process_callback (jack_client_t *, JackProcessCallback, void *arg); int jack_set_buffer_size_callback (jack_client_t *, JackBufferSizeCallback, void *arg); @@ -97,13 +100,27 @@ enum JackPortFlags { Clients that do not control physical interfaces should never create ports with this bit set. + */ + + JackPortCanMonitor = 0x8, + + /* JackPortIsTerminal means: + + for an input port: the data received by the port + will not be passed on or made + available at any other port + + for an output port: the data available at the port + does not originate from any + other port - Clients that do set this bit must have provided a - port_monitor callback before creating any ports with - this bit set. + Audio synthesizers, i/o h/w interface clients, HDR + systems are examples of things that would set this + flag for their ports. */ - JackPortCanMonitor = 0x8 + JackPortIsTerminal = 0x10 + }; #define JACK_DEFAULT_AUDIO_TYPE "32 bit float mono audio" @@ -115,7 +132,9 @@ jack_port_register (jack_client_t *, unsigned long flags, unsigned long buffer_size); -/* this removes the port from the client */ +/* this removes the port from the client, disconnecting + any existing connections at the same time. +*/ int jack_port_unregister (jack_client_t *, jack_port_t *); @@ -125,9 +144,34 @@ const char * jack_port_name (const jack_port_t *port); const char * jack_port_short_name (const jack_port_t *port); int jack_port_flags (const jack_port_t *port); const char * jack_port_type (const jack_port_t *port); -int jack_port_connected (const jack_port_t *port); -int jack_port_connected_to (const jack_port_t *port, const char *portname); -int jack_port_equal (const jack_port_t *a, const jack_port_t *b); + +/* this returns TRUE or FALSE to indicate if there are + any connections to/from the port argument. +*/ + +int jack_port_connected (const jack_port_t *port); + +/* this returns TRUE or FALSE if the port argument is + DIRECTLY connected to the port with the name given in + `portname' +*/ + +int jack_port_connected_to (const jack_port_t *port, const char *portname); +int jack_port_connected_to_port (const jack_port_t *port, const jack_port_t *other_port); + +/* this returns a null-terminated array of port names to + which the argument port is connected. if there are no + connections, it returns NULL. + + the caller is responsible for calling free(3) on any + non-NULL returned value. +*/ + +const char ** jack_port_get_connections (const jack_port_t *port); + +/* this modifies a port's name, and may be called at any + time. +*/ int jack_port_set_name (jack_port_t *port, const char *name); @@ -138,6 +182,10 @@ int jack_port_set_name (jack_port_t *port, const char *name); containing the data from the port's connection(s), or zero-filled. if there are multiple inbound connections, the data will be mixed appropriately. + + You may not cache the values returned across process() callbacks. + There is no guarantee that the values will not change from + process() callback to process() callback. */ void *jack_port_get_buffer (jack_port_t *, nframes_t); @@ -232,9 +280,9 @@ nframes_t jack_port_get_latency (jack_port_t *port); void jack_port_set_latency (jack_port_t *, nframes_t); -/* if JackPortCanMonitor is set for a port, then this function will - turn on/off input monitoring for the port. if JackPortCanMonitor - is not set, then this function will do nothing. +/* if JackPortCanMonitor is set for a port, then these 2 functions will + turn on/off input monitoring for the port. if JackPortCanMonitor + is not set, then these functions will have no effect. */ int jack_port_request_monitor (jack_port_t *port, int onoff); @@ -254,13 +302,15 @@ int jack_port_ensure_monitor (jack_port_t *port, int onoff); int jack_port_monitoring_input (jack_port_t *port); -/* this returns the sample rate of the jack */ +/* this returns the sample rate of the jack system */ unsigned long jack_get_sample_rate (jack_client_t *); /* this returns the current maximum size that will ever be passed to the "process" callback. it should only - be used *before* the client has been activated. + be used *before* the client has been activated. after activation, + the client will be notified of buffer size changes if it + registers a buffer_size callback. */ nframes_t jack_get_buffer_size (jack_client_t *); @@ -278,28 +328,33 @@ nframes_t jack_get_buffer_size (jack_client_t *); flags: a value used to select ports by their flags. if zero, no selection based on flags will be carried out. + + The caller is responsible for calling free(3) any non-NULL returned + value. */ -char * const * jack_get_ports (jack_client_t *, +const char ** jack_get_ports (jack_client_t *, const char *port_name_pattern, const char *type_name_pattern, unsigned long flags); jack_port_t *jack_port_by_name (jack_client_t *, const char *portname); -/* If a client is told to become the timebase for the entire system, - it calls this function. If it returns zero, then the client has - the responsibility to call jack_update_time() at the end - of its process() callback. Whatever time it provides (in frames - since its reference zero time) becomes the current timebase - for the entire system. +/* If a client is told (by the user) to become the timebase + for the entire system, it calls this function. If it + returns zero, then the client has the responsibility to + call jack_update_time() at the end of its process() + callback. Whatever time it provides (in frames since its + reference zero time) becomes the current timebase for the + entire system. */ int jack_engine_takeover_timebase (jack_client_t *); void jack_update_time (jack_client_t *, nframes_t); /* this estimates the time that has passed since the - start of the current cycle. + start jack server started calling the process() + callbacks of all its clients. */ nframes_t jack_frames_since_cycle_start (jack_client_t *);