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 *); | |||