git-svn-id: svn+ssh://jackaudio.org/trunk/jack@96 0c269be4-1314-0410-8aa9-9f06e86f4224tags/0.109.0
| @@ -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) { | |||
| @@ -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; | |||
| } | |||
| @@ -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= | |||
| @@ -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); | |||
| @@ -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; | |||
| @@ -34,8 +34,6 @@ | |||
| #include <jack/types.h> | |||
| #include <jack/port.h> | |||
| #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; | |||
| @@ -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 *); | |||