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++) { | for (i = 0; i < nfds; i++) { | ||||
driver->pfd[nfds].events |= POLLERR; | driver->pfd[nfds].events |= POLLERR; | ||||
} | } | ||||
if (poll (driver->pfd, nfds, 1000) < 0) { | if (poll (driver->pfd, nfds, 1000) < 0) { | ||||
if (errno == EINTR) { | if (errno == EINTR) { | ||||
printf ("poll interrupt\n"); | printf ("poll interrupt\n"); | ||||
@@ -789,7 +789,7 @@ alsa_driver_wait (alsa_driver_t *driver) | |||||
} | } | ||||
} | } | ||||
xrun_detected = FALSE; | xrun_detected = FALSE; | ||||
if ((capture_avail = snd_pcm_avail_update (driver->capture_handle)) < 0) { | if ((capture_avail = snd_pcm_avail_update (driver->capture_handle)) < 0) { | ||||
@@ -72,7 +72,7 @@ struct _jack_client { | |||||
GSList *port_segments; | GSList *port_segments; | ||||
GSList *ports; | GSList *ports; | ||||
pthread_t thread; | pthread_t thread; | ||||
char fifo_prefix[FIFO_NAME_SIZE+1]; | |||||
char fifo_prefix[PATH_MAX+1]; | |||||
void (*on_shutdown)(void *arg); | void (*on_shutdown)(void *arg); | ||||
void *on_shutdown_arg; | void *on_shutdown_arg; | ||||
char thread_ok : 1; | char thread_ok : 1; | ||||
@@ -141,25 +141,6 @@ jack_port_by_id (jack_client_t *client, jack_port_id_t id) | |||||
return NULL; | 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_t * | ||||
jack_port_by_name (jack_client_t *client, const char *port_name) | 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 | static int | ||||
jack_handle_reorder (jack_client_t *client, jack_event_t *event) | 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) { | if (client->graph_wait_fd >= 0) { | ||||
close (client->graph_wait_fd); | 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_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; | return -1; | ||||
} | } | ||||
@@ -1363,6 +1341,30 @@ jack_port_request_monitor (jack_port_t *port, int onoff) | |||||
} else if (port->shared->monitor_requests) { | } else if (port->shared->monitor_requests) { | ||||
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; | return 0; | ||||
} | } | ||||
@@ -1416,12 +1418,6 @@ jack_port_type (const jack_port_t *port) | |||||
return port->shared->type_info.type_name; | 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 | int | ||||
jack_port_set_name (jack_port_t *port, const char *new_name) | 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; | client->on_shutdown_arg = arg; | ||||
} | } | ||||
char * const * | |||||
const char ** | |||||
jack_get_ports (jack_client_t *client, | jack_get_ports (jack_client_t *client, | ||||
const char *port_name_pattern, | const char *port_name_pattern, | ||||
const char *type_name_pattern, | const char *type_name_pattern, | ||||
unsigned long flags) | unsigned long flags) | ||||
{ | { | ||||
jack_control_t *engine; | jack_control_t *engine; | ||||
char **matching_ports; | |||||
const char **matching_ports; | |||||
unsigned long match_cnt; | unsigned long match_cnt; | ||||
jack_port_shared_t *psp; | jack_port_shared_t *psp; | ||||
unsigned long i; | unsigned long i; | ||||
@@ -1469,7 +1465,7 @@ jack_get_ports (jack_client_t *client, | |||||
psp = engine->ports; | psp = engine->ports; | ||||
match_cnt = 0; | 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++) { | for (i = 0; i < engine->port_max; i++) { | ||||
matching = 1; | 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 | int | ||||
jack_port_connected (const jack_port_t *port) | 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); | pthread_mutex_unlock (&((jack_port_t *) port)->connection_lock); | ||||
return ret; | 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(.) | AC_CONFIG_AUX_DIR(.) | ||||
JACK_MAJOR_VERSION=0 | JACK_MAJOR_VERSION=0 | ||||
JACK_MINOR_VERSION=8 | |||||
JACK_MINOR_VERSION=9 | |||||
JACK_MICRO_VERSION=0 | JACK_MICRO_VERSION=0 | ||||
BETA= | BETA= | ||||
@@ -298,7 +298,7 @@ jack_cleanup_files () | |||||
char fullpath[PATH_MAX+1]; | char fullpath[PATH_MAX+1]; | ||||
sprintf (fullpath, "%s/%s", jack_temp_dir, dirent->d_name); | sprintf (fullpath, "%s/%s", jack_temp_dir, dirent->d_name); | ||||
unlink (fullpath); | unlink (fullpath); | ||||
} | |||||
} | |||||
} | } | ||||
closedir (dir); | closedir (dir); | ||||
@@ -1138,7 +1138,7 @@ jack_engine_new (int realtime, int rtpriority) | |||||
engine->control->time.frame_rate = 0; | engine->control->time.frame_rate = 0; | ||||
engine->control->time.frame = 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); | (void) jack_get_fifo_fd (engine, 0); | ||||
jack_start_server (engine); | jack_start_server (engine); | ||||
@@ -1810,22 +1810,24 @@ jack_port_do_connect (jack_engine_t *engine, | |||||
} | } | ||||
if ((dstport->shared->flags & JackPortIsInput) == 0) { | 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; | return -1; | ||||
} | } | ||||
if ((srcport->shared->flags & JackPortIsOutput) == 0) { | 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; | return -1; | ||||
} | } | ||||
if (srcport->shared->locked) { | 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; | return -1; | ||||
} | } | ||||
if (dstport->shared->locked) { | 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; | return -1; | ||||
} | } | ||||
@@ -2018,7 +2020,7 @@ static int | |||||
jack_get_fifo_fd (jack_engine_t *engine, int which_fifo) | 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; | struct stat statbuf; | ||||
sprintf (path, "%s-%d", engine->fifo_prefix, which_fifo); | sprintf (path, "%s-%d", engine->fifo_prefix, which_fifo); | ||||
@@ -68,7 +68,7 @@ struct _jack_engine { | |||||
struct pollfd *pfd; | struct pollfd *pfd; | ||||
struct _jack_client_internal *timebase_client; | struct _jack_client_internal *timebase_client; | ||||
jack_port_buffer_info_t *silent_buffer; | jack_port_buffer_info_t *silent_buffer; | ||||
char fifo_prefix[FIFO_NAME_SIZE+1]; | |||||
char fifo_prefix[PATH_MAX+1]; | |||||
int *fifo; | int *fifo; | ||||
unsigned long fifo_size; | unsigned long fifo_size; | ||||
unsigned long external_client_cnt; | unsigned long external_client_cnt; | ||||
@@ -34,8 +34,6 @@ | |||||
#include <jack/types.h> | #include <jack/types.h> | ||||
#include <jack/port.h> | #include <jack/port.h> | ||||
#define FIFO_NAME_SIZE 32 | |||||
typedef void * dlhandle; | typedef void * dlhandle; | ||||
typedef struct { | typedef struct { | ||||
@@ -161,7 +159,7 @@ typedef struct { | |||||
int client_key; | int client_key; | ||||
int control_key; | int control_key; | ||||
char fifo_prefix[FIFO_NAME_SIZE+1]; | |||||
char fifo_prefix[PATH_MAX+1]; | |||||
int realtime; | int realtime; | ||||
int realtime_priority; | 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 | /* register a function (and argument) to be called if and when the | ||||
JACK server shuts down the client thread. the function must | JACK server shuts down the client thread. the function must | ||||
be written as if it were an asynchonrous POSIX signal | 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 | is executed from another thread. a typical function might | ||||
set a flag or write to a pipe so that the rest of the | set a flag or write to a pipe so that the rest of the | ||||
application knows that the JACK client thread has shut | 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(). | 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_process_callback (jack_client_t *, JackProcessCallback, void *arg); | ||||
int jack_set_buffer_size_callback (jack_client_t *, JackBufferSizeCallback, 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 | Clients that do not control physical interfaces | ||||
should never create ports with this bit set. | 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" | #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 flags, | ||||
unsigned long buffer_size); | 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 *); | 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); | const char * jack_port_short_name (const jack_port_t *port); | ||||
int jack_port_flags (const jack_port_t *port); | int jack_port_flags (const jack_port_t *port); | ||||
const char * jack_port_type (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); | 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 | containing the data from the port's connection(s), or | ||||
zero-filled. if there are multiple inbound connections, the data | zero-filled. if there are multiple inbound connections, the data | ||||
will be mixed appropriately. | 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); | 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); | 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); | 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); | 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 *); | unsigned long jack_get_sample_rate (jack_client_t *); | ||||
/* this returns the current maximum size that will | /* this returns the current maximum size that will | ||||
ever be passed to the "process" callback. it should only | 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 *); | 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 | flags: a value used to select ports by their flags. if | ||||
zero, no selection based on flags will be carried out. | 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 *port_name_pattern, | ||||
const char *type_name_pattern, | const char *type_name_pattern, | ||||
unsigned long flags); | unsigned long flags); | ||||
jack_port_t *jack_port_by_name (jack_client_t *, const char *portname); | 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 *); | int jack_engine_takeover_timebase (jack_client_t *); | ||||
void jack_update_time (jack_client_t *, nframes_t); | void jack_update_time (jack_client_t *, nframes_t); | ||||
/* this estimates the time that has passed since the | /* 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 *); | nframes_t jack_frames_since_cycle_start (jack_client_t *); | ||||