git-svn-id: svn+ssh://jackaudio.org/trunk/jack@370 0c269be4-1314-0410-8aa9-9f06e86f4224tags/0.109.0
@@ -14,7 +14,7 @@ dnl changes are made | |||
dnl --- | |||
JACK_MAJOR_VERSION=0 | |||
JACK_MINOR_VERSION=67 | |||
JACK_MICRO_VERSION=2 | |||
JACK_MICRO_VERSION=3 | |||
dnl --- | |||
dnl HOWTO: updating the jack protocal version | |||
@@ -565,7 +565,8 @@ alsa_driver_set_parameters (alsa_driver_t *driver, jack_nframes_t frames_per_cyc | |||
(driver->capture_nchannels > driver->playback_nchannels ? | |||
driver->capture_nchannels : driver->playback_nchannels)); | |||
driver->period_usecs = (((float) driver->frames_per_cycle) / driver->frame_rate) * 1000000.0f; | |||
driver->period_usecs = (jack_time_t) floor ((((float) driver->frames_per_cycle) / driver->frame_rate) * 1000000.0f); | |||
driver->poll_timeout = (int) floor (1.5f * driver->period_usecs); | |||
if (driver->engine) { | |||
driver->engine->set_buffer_size (driver->engine, driver->frames_per_cycle); | |||
@@ -821,7 +822,7 @@ alsa_driver_wait (alsa_driver_t *driver, int extra_fd, int *status, float *delay | |||
int need_capture; | |||
int need_playback; | |||
unsigned int i; | |||
unsigned long long poll_enter, poll_ret; | |||
jack_time_t poll_enter, poll_ret; | |||
*status = -1; | |||
*delayed_usecs = 0; | |||
@@ -869,7 +870,8 @@ alsa_driver_wait (alsa_driver_t *driver, int extra_fd, int *status, float *delay | |||
poll_enter = jack_get_microseconds (); | |||
if (poll (driver->pfd, nfds, (int) floor ((1.5f * driver->period_usecs) / 1000.0f)) < 0) { | |||
if (poll (driver->pfd, nfds, driver->poll_timeout) < 0) { | |||
if (errno == EINTR) { | |||
printf ("poll interrupt\n"); | |||
// this happens mostly when run | |||
@@ -891,18 +893,18 @@ alsa_driver_wait (alsa_driver_t *driver, int extra_fd, int *status, float *delay | |||
if (extra_fd < 0) { | |||
if (driver->poll_next && poll_ret > driver->poll_next) { | |||
*delayed_usecs = (float) (poll_ret - driver->poll_next) / driver->cpu_mhz; | |||
*delayed_usecs = poll_ret - driver->poll_next; | |||
} | |||
driver->poll_last = poll_ret; | |||
driver->poll_next = poll_ret + (unsigned long long) floor ((driver->period_usecs * driver->cpu_mhz)); | |||
driver->poll_next = poll_ret + driver->period_usecs; | |||
driver->engine->control->current_time.usecs = poll_ret; | |||
} | |||
#ifdef DEBUG_WAKEUP | |||
fprintf (stderr, "%Lu: checked %d fds, %.9f usecs since poll entered\n", | |||
poll_ret, | |||
nfds, | |||
(float) (poll_ret - poll_enter) / driver->cpu_mhz); | |||
fprintf (stderr, "%Lu: checked %d fds, %Lu usecs since poll entered\n", | |||
poll_ret, | |||
nfds, | |||
poll_ret - poll_enter); | |||
#endif | |||
/* check to see if it was the extra FD that caused us to return from poll | |||
@@ -973,7 +975,7 @@ alsa_driver_wait (alsa_driver_t *driver, int extra_fd, int *status, float *delay | |||
if ((p_timed_out && (p_timed_out == driver->playback_nfds)) && | |||
(c_timed_out && (c_timed_out == driver->capture_nfds))){ | |||
jack_error ("ALSA: poll time out polled for %.6f", ((float) (poll_ret - poll_enter) / driver->cpu_mhz)); | |||
jack_error ("ALSA: poll time out, polled for %Lu usecs", poll_ret - poll_enter); | |||
*status = -5; | |||
return 0; | |||
} | |||
@@ -1010,6 +1012,7 @@ alsa_driver_wait (alsa_driver_t *driver, int extra_fd, int *status, float *delay | |||
} | |||
*status = 0; | |||
driver->last_wait_ust = poll_ret; | |||
avail = capture_avail < playback_avail ? capture_avail : playback_avail; | |||
@@ -1035,10 +1038,7 @@ alsa_driver_null_cycle (alsa_driver_t* driver, jack_nframes_t nframes) | |||
jack_nframes_t nf; | |||
snd_pcm_uframes_t offset; | |||
snd_pcm_uframes_t contiguous; | |||
fprintf (stderr, "C: %p area %p P: %p area %p\n", | |||
driver->capture_handle, driver->capture_areas, | |||
driver->playback_handle, driver->playback_areas); | |||
int chn; | |||
if (driver->capture_handle) { | |||
nf = nframes; | |||
@@ -1073,6 +1073,10 @@ alsa_driver_null_cycle (alsa_driver_t* driver, jack_nframes_t nframes) | |||
return -1; | |||
} | |||
for (chn = 0; chn < driver->playback_nchannels; chn++) { | |||
alsa_driver_silence_on_channel (driver, chn, contiguous); | |||
} | |||
if (snd_pcm_mmap_commit (driver->playback_handle, offset, contiguous) < 0) { | |||
return -1; | |||
} | |||
@@ -1192,9 +1196,14 @@ alsa_driver_write (alsa_driver_t* driver, jack_nframes_t nframes) | |||
buf = jack_port_get_buffer (port, contiguous); | |||
if (driver->all_monitor_in || (driver->input_monitor_mask & (1<<chn))) { | |||
if (driver->all_monitor_in || (driver->input_monitor_mask & (1<<chn))) { | |||
if (!driver->hw_monitoring) { | |||
alsa_driver_copy_channel (driver, chn, chn, contiguous); | |||
} else { | |||
/* allow systems with mixdown for monitoring to playback | |||
the stream even if monitoring is enabled (e.g. ice1712, hdsp) | |||
*/ | |||
alsa_driver_write_to_channel (driver, chn, buf + nwritten, contiguous); | |||
} | |||
} else { | |||
alsa_driver_write_to_channel (driver, chn, buf + nwritten, contiguous); | |||
@@ -1262,6 +1271,8 @@ alsa_driver_attach (alsa_driver_t *driver, jack_engine_t *engine) | |||
port_flags = JackPortIsInput|JackPortIsPhysical|JackPortIsTerminal; | |||
for (chn = 0; chn < driver->playback_nchannels; chn++) { | |||
jack_port_t *monitor_port; | |||
snprintf (buf, sizeof(buf) - 1, "playback_%lu", chn+1); | |||
if ((port = jack_port_register (driver->client, buf, JACK_DEFAULT_AUDIO_TYPE, port_flags, 0)) == NULL) { | |||
@@ -1280,6 +1291,16 @@ alsa_driver_attach (alsa_driver_t *driver, jack_engine_t *engine) | |||
jack_port_set_latency (port, driver->frames_per_cycle * driver->nfragments); | |||
driver->playback_ports = jack_slist_append (driver->playback_ports, port); | |||
if (driver->with_monitor_ports) { | |||
snprintf (buf, sizeof(buf) - 1, "monitor_%lu", chn+1); | |||
if ((monitor_port = jack_port_register (driver->client, buf, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0)) == NULL) { | |||
jack_error ("ALSA: cannot register monitor port for %s", buf); | |||
} else { | |||
jack_port_tie (port, monitor_port); | |||
} | |||
} | |||
} | |||
jack_activate (driver->client); | |||
@@ -1429,7 +1450,8 @@ alsa_driver_new (char *name, char *alsa_device, | |||
int capturing, | |||
int playing, | |||
DitherAlgorithm dither, | |||
int soft_mode) | |||
int soft_mode, | |||
int monitor) | |||
{ | |||
int err; | |||
@@ -1466,7 +1488,7 @@ alsa_driver_new (char *name, char *alsa_device, | |||
driver->capture_addr = 0; | |||
driver->silent = 0; | |||
driver->all_monitor_in = FALSE; | |||
driver->cpu_mhz = jack_get_mhz(); | |||
driver->with_monitor_ports = monitor; | |||
driver->clock_mode = ClockMaster; /* XXX is it? */ | |||
driver->input_monitor_mask = 0; /* XXX is it? */ | |||
@@ -1668,6 +1690,7 @@ alsa_usage () | |||
" -C,--capture \tcapture input (default: duplex)\n" | |||
" -P,--playback\tplayback output (default: duplex)\n" | |||
" -s,--softmode\tsoft-mode, no xrun handling (default: off)\n" | |||
" -m,--monitor \tprovide monitor ports for the output (default: off)\n" | |||
" -z,--dither \tdithering mode:\n" | |||
" -z-,--dither (off, the default)\n" | |||
" -zr,--dither=rectangular\n" | |||
@@ -1727,6 +1750,7 @@ driver_initialize (jack_client_t *client, int argc, char **argv) | |||
int capture = FALSE; | |||
int playback = FALSE; | |||
int soft_mode = FALSE; | |||
int monitor = FALSE; | |||
DitherAlgorithm dither = None; | |||
int opt; | |||
char *envvar; | |||
@@ -1745,6 +1769,7 @@ driver_initialize (jack_client_t *client, int argc, char **argv) | |||
{ "nperiods", 1, NULL, 'n' }, | |||
{ "softmode", 1, NULL, 's' }, | |||
{ "dither", 2, NULL, 'z' }, | |||
{ "monitor", 0, NULL, 'm' }, | |||
{ 0, 0, 0, 0 } | |||
}; | |||
@@ -1790,6 +1815,10 @@ driver_initialize (jack_client_t *client, int argc, char **argv) | |||
playback = atoi (envvar); | |||
} | |||
if ((envvar = getenv ("JACK_ALSA_MONITOR")) != NULL) { | |||
monitor = atoi (envvar); | |||
} | |||
/* | |||
* Setting optind back to zero is a hack to reinitialize a new | |||
* getopts() loop. See declaration in <getopt.h>. | |||
@@ -1798,7 +1827,7 @@ driver_initialize (jack_client_t *client, int argc, char **argv) | |||
optind = 0; | |||
opterr = 0; | |||
while ((opt = getopt_long(argc, argv, "-CDd:HMPp:r:n:sz::", | |||
while ((opt = getopt_long(argc, argv, "-CDd:HMPp:r:n:msz::", | |||
long_options, NULL)) | |||
!= EOF) { | |||
switch (opt) { | |||
@@ -1824,6 +1853,10 @@ driver_initialize (jack_client_t *client, int argc, char **argv) | |||
alsa_usage(); | |||
return NULL; | |||
case 'm': | |||
monitor = TRUE; | |||
break; | |||
case 'M': | |||
hw_metering = TRUE; | |||
break; | |||
@@ -1879,7 +1912,7 @@ driver_initialize (jack_client_t *client, int argc, char **argv) | |||
return alsa_driver_new ("alsa_pcm", pcm_name, client, frames_per_interrupt, | |||
user_nperiods, srate, hw_monitoring, hw_metering, capture, | |||
playback, dither, soft_mode); | |||
playback, dither, soft_mode, monitor); | |||
} | |||
void | |||
@@ -45,8 +45,9 @@ typedef struct { | |||
JACK_DRIVER_DECL | |||
unsigned long long poll_last; | |||
unsigned long long poll_next; | |||
int poll_timeout; | |||
jack_time_t poll_last; | |||
jack_time_t poll_next; | |||
char **playback_addr; | |||
char **capture_addr; | |||
const snd_pcm_channel_area_t *capture_areas; | |||
@@ -63,11 +64,10 @@ typedef struct { | |||
channel_t capture_nchannels; | |||
unsigned long sample_bytes; | |||
jack_nframes_t frame_rate; | |||
jack_nframes_t frames_per_cycle; | |||
float cpu_mhz; | |||
jack_nframes_t capture_frame_latency; | |||
jack_nframes_t playback_frame_latency; | |||
jack_nframes_t frame_rate; | |||
jack_nframes_t frames_per_cycle; | |||
jack_nframes_t capture_frame_latency; | |||
jack_nframes_t playback_frame_latency; | |||
unsigned long *silent; | |||
char *alsa_name; | |||
@@ -102,6 +102,7 @@ typedef struct { | |||
char all_monitor_in : 1; | |||
char capture_and_playback_not_synced : 1; | |||
char interleaved : 1; | |||
char with_monitor_ports : 1; | |||
ReadCopyFunction read_via_copy; | |||
WriteCopyFunction write_via_copy; | |||
@@ -80,9 +80,17 @@ typedef jack_nframes_t (*JackDriverWaitFunction)(struct _jack_driver *, int fd, | |||
#define JACK_DRIVER_DECL | |||
/* the driver should set this to be the interval it expects to elapse | |||
between returning from the `wait' function. | |||
between returning from the `wait' function. if set to zero, it | |||
implies that the driver does not expect regular periodic wakeups. | |||
*/ | |||
nframes_t period_usecs; | |||
jack_time_t period_usecs; | |||
/* the driver should set this within its "wait" function to indicate | |||
the UST of the most recent determination that the engine cycle | |||
should run. it should not be set if the "extra_fd" argument of | |||
the wait function is set to a non-zero value. | |||
*/ | |||
jack_time_t last_wait_ust; | |||
/* this is not used by the driver. it should not be written to or | |||
modified in any way | |||
@@ -180,7 +188,8 @@ typedef jack_nframes_t (*JackDriverWaitFunction)(struct _jack_driver *, int fd, | |||
#else | |||
#define JACK_DRIVER_DECL \ | |||
jack_nframes_t period_usecs; \ | |||
jack_time_t period_usecs; \ | |||
jack_time_t last_wait_ust; \ | |||
void *handle; \ | |||
void (*finish)(struct _jack_driver *);\ | |||
JackDriverAttachFunction attach; \ | |||
@@ -126,9 +126,6 @@ static void jack_port_registration_notify (jack_engine_t *, jack_port_id_t, int) | |||
static int jack_send_connection_notification (jack_engine_t *, jack_client_id_t, jack_port_id_t, jack_port_id_t, int); | |||
static int jack_deliver_event (jack_engine_t *, jack_client_internal_t *, jack_event_t *); | |||
static void jack_deliver_event_to_all (jack_engine_t *engine, jack_event_t *event); | |||
static int jack_engine_process_lock (jack_engine_t *); | |||
static void jack_engine_process_unlock (jack_engine_t *); | |||
static int jack_engine_post_process (jack_engine_t *); | |||
static int internal_client_request (void*, jack_request_t *); | |||
@@ -156,15 +153,22 @@ jack_client_is_internal (jack_client_internal_t *client) | |||
return (client->control->type == ClientInternal) || (client->control->type == ClientDriver); | |||
} | |||
#define jack_lock_graph(engine) do { \ | |||
DEBUG ("acquiring graph lock"); \ | |||
pthread_mutex_lock (&engine->client_lock); \ | |||
} while(0) | |||
static inline void jack_lock_graph (jack_engine_t* engine) { | |||
DEBUG ("acquiring graph lock"); | |||
pthread_mutex_lock (&engine->client_lock); | |||
} | |||
#define jack_unlock_graph(engine) do { \ | |||
DEBUG ("releasing graph lock"); \ | |||
pthread_mutex_unlock (&engine->client_lock); \ | |||
} while(0) | |||
static inline int jack_try_lock_graph (jack_engine_t *engine) | |||
{ | |||
DEBUG ("TRYING to acquiring graph lock"); | |||
return pthread_mutex_trylock (&engine->client_lock); | |||
} | |||
static inline void jack_unlock_graph (jack_engine_t* engine) | |||
{ | |||
DEBUG ("releasing graph lock"); | |||
pthread_mutex_unlock (&engine->client_lock); | |||
} | |||
static inline void | |||
jack_engine_reset_rolling_usecs (jack_engine_t *engine) | |||
@@ -510,18 +514,6 @@ jack_set_sample_rate (jack_engine_t *engine, jack_nframes_t nframes) | |||
return 0; | |||
} | |||
int | |||
jack_engine_process_lock (jack_engine_t *engine) | |||
{ | |||
return pthread_mutex_trylock (&engine->client_lock); | |||
} | |||
void | |||
jack_engine_process_unlock (jack_engine_t *engine) | |||
{ | |||
pthread_mutex_unlock (&engine->client_lock); | |||
} | |||
static JSList * | |||
jack_process_internal(jack_engine_t *engine, JSList *node, jack_nframes_t nframes) | |||
{ | |||
@@ -628,15 +620,16 @@ jack_process_external(jack_engine_t *engine, JSList *node) | |||
if (status != 0) { | |||
if (engine->verbose) { | |||
fprintf (stderr, "at %Lu client waiting on %d took %Lu usecs, status = %d sig = %Lu awa = %Lu fin = %Lu dur=%Lu\n", | |||
now, | |||
client->subgraph_wait_fd, | |||
now - then, | |||
status, | |||
ctl->signalled_at, | |||
ctl->awake_at, | |||
ctl->finished_at, | |||
ctl->finished_at - ctl->signalled_at); | |||
fprintf (stderr, "at %Lu client waiting on %d took %Lu usecs, status = %d sig = %Lu " | |||
"awa = %Lu fin = %Lu dur=%Lu\n", | |||
now, | |||
client->subgraph_wait_fd, | |||
now - then, | |||
status, | |||
ctl->signalled_at, | |||
ctl->awake_at, | |||
ctl->finished_at, | |||
ctl->finished_at ? ctl->finished_at - ctl->signalled_at : 0); | |||
} | |||
/* we can only consider the timeout a client error if it actually woke up. | |||
@@ -750,6 +743,66 @@ jack_calc_cpu_load(jack_engine_t *engine) | |||
} | |||
static void* | |||
jack_removal_thread (void *arg) | |||
{ | |||
JSList *tmp, *node; | |||
int need_sort = FALSE; | |||
jack_engine_t* engine = (jack_engine_t*) arg; | |||
jack_client_internal_t *client; | |||
fprintf (stderr, "@_@_@_@_@ REMOVAL THREAD\n"); | |||
/* remove all dead clients */ | |||
for (node = engine->clients; node; ) { | |||
tmp = jack_slist_next (node); | |||
client = (jack_client_internal_t *) node->data; | |||
if (client->error) { | |||
/* if we have a communication problem with the client, | |||
remove it. otherwise, turn it into a zombie. the client | |||
will/should realize this and will close it sockets. | |||
then we'll end up back here again and will finally | |||
remove the client. | |||
*/ | |||
if (client->error >= JACK_ERROR_WITH_SOCKETS) { | |||
if (engine->verbose) { | |||
fprintf (stderr, "removing failed client %s state = %s errors = %d\n", | |||
client->control->name, client_state_names[client->control->state], | |||
client->error); | |||
} | |||
jack_remove_client (engine, (jack_client_internal_t *) node->data); | |||
} else { | |||
if (engine->verbose) { | |||
fprintf (stderr, "zombifying failed client %s state = %s errors = %d\n", | |||
client->control->name, client_state_names[client->control->state], | |||
client->error); | |||
} | |||
jack_zombify_client (engine, (jack_client_internal_t *) node->data); | |||
client->error = 0; | |||
} | |||
need_sort = TRUE; | |||
} | |||
node = tmp; | |||
} | |||
if (need_sort) { | |||
jack_sort_graph (engine); | |||
} | |||
jack_engine_reset_rolling_usecs (engine); | |||
jack_unlock_graph (engine); | |||
return 0; | |||
} | |||
static int | |||
jack_engine_post_process (jack_engine_t *engine) | |||
{ | |||
@@ -757,7 +810,8 @@ jack_engine_post_process (jack_engine_t *engine) | |||
jack_client_internal_t *client; | |||
JSList *node; | |||
int need_remove = FALSE; | |||
int ret; | |||
/* maintain the current_time.usecs and frame_rate values, since clients | |||
are not permitted to set these. | |||
*/ | |||
@@ -792,63 +846,19 @@ jack_engine_post_process (jack_engine_t *engine) | |||
need_remove = TRUE; | |||
} | |||
} | |||
if (need_remove) { | |||
JSList *tmp; | |||
int need_sort = FALSE; | |||
/* remove all dead clients */ | |||
for (node = engine->clients; node; ) { | |||
tmp = jack_slist_next (node); | |||
client = (jack_client_internal_t *) node->data; | |||
if (client->error) { | |||
/* if we have a communication problem with the client, | |||
remove it. otherwise, turn it into a zombie. the client | |||
will/should realize this and will close it sockets. | |||
then we'll end up back here again and will finally | |||
remove the client. | |||
*/ | |||
if (client->error >= JACK_ERROR_WITH_SOCKETS) { | |||
if (engine->verbose) { | |||
fprintf (stderr, "removing failed client %s state = %s errors = %d\n", | |||
client->control->name, client_state_names[client->control->state], | |||
client->error); | |||
} | |||
jack_remove_client (engine, (jack_client_internal_t *) node->data); | |||
} else { | |||
if (engine->verbose) { | |||
fprintf (stderr, "zombifying failed client %s state = %s errors = %d\n", | |||
client->control->name, client_state_names[client->control->state], | |||
client->error); | |||
} | |||
jack_zombify_client (engine, (jack_client_internal_t *) node->data); | |||
client->error = 0; | |||
} | |||
need_sort = TRUE; | |||
} | |||
node = tmp; | |||
} | |||
if (need_sort) { | |||
jack_sort_graph (engine); | |||
} | |||
jack_engine_reset_rolling_usecs (engine); | |||
pthread_t removal_thread; | |||
pthread_create (&removal_thread, NULL, jack_removal_thread, engine); | |||
pthread_detach (removal_thread); | |||
ret = 1; | |||
} else { | |||
ret = 0; | |||
} | |||
jack_calc_cpu_load(engine); | |||
jack_calc_cpu_load (engine); | |||
return 0; | |||
return ret; | |||
} | |||
static int | |||
@@ -1997,6 +2007,12 @@ jack_engine_notify_clients_about_delay (jack_engine_t *engine) | |||
jack_unlock_graph (engine); | |||
} | |||
#if defined(linux) | |||
static inline jack_time_t jack_get_wait_timestamp (jack_engine_t *engine) { | |||
return engine->driver->last_wait_ust; | |||
} | |||
#endif | |||
static inline void | |||
jack_inc_frame_time (jack_engine_t *engine, jack_nframes_t amount) | |||
{ | |||
@@ -2007,7 +2023,7 @@ jack_inc_frame_time (jack_engine_t *engine, jack_nframes_t amount) | |||
time->guard1++; | |||
time->frames += amount; | |||
time->stamp = jack_get_microseconds (); | |||
time->stamp = jack_get_wait_timestamp (engine); | |||
// atomic_inc (&time->guard2, 1); | |||
// might need a memory barrier here | |||
@@ -2015,26 +2031,19 @@ jack_inc_frame_time (jack_engine_t *engine, jack_nframes_t amount) | |||
} | |||
static int | |||
jack_engine_wait (jack_engine_t *engine, jack_nframes_t* nframes) | |||
jack_run_cycle (jack_engine_t *engine, jack_nframes_t nframes, float delayed_usecs) | |||
{ | |||
jack_driver_t *driver = engine->driver; | |||
float delayed_usecs; | |||
int status; | |||
int restart = 0; | |||
jack_driver_t* driver = engine->driver; | |||
int ret = -1; | |||
static int consecutive_excessive_delays = 0; | |||
if ((*nframes = driver->wait (driver, -1, &status, &delayed_usecs)) == 0) { | |||
/* the driver detected an xrun, and restarted */ | |||
return 1; /* will continue */ | |||
} | |||
jack_inc_frame_time (engine, *nframes); | |||
engine->watchdog_check = 1; | |||
#define WORK_SCALE 1.0f | |||
if (engine->control->real_time != 0 && engine->spare_usecs && ((WORK_SCALE * engine->spare_usecs) <= delayed_usecs)) { | |||
if (engine->control->real_time && engine->spare_usecs && ((WORK_SCALE * engine->spare_usecs) <= delayed_usecs)) { | |||
fprintf (stderr, "delay of %.3f usecs exceeds estimated spare time of %.3f; restart ...\n", | |||
delayed_usecs, WORK_SCALE * engine->spare_usecs); | |||
@@ -2055,29 +2064,23 @@ jack_engine_wait (jack_engine_t *engine, jack_nframes_t* nframes) | |||
return -1; /* will exit the thread loop */ | |||
} | |||
return 1; /* will continue */ | |||
return 0; | |||
} else { | |||
consecutive_excessive_delays = 0; | |||
} | |||
return status; | |||
} | |||
static int | |||
jack_run_cycle (jack_engine_t *engine, jack_nframes_t nframes) | |||
{ | |||
int restart = 0; | |||
jack_driver_t* driver = engine->driver; | |||
if (jack_engine_process_lock (engine)) { | |||
jack_inc_frame_time (engine, nframes); | |||
if (jack_try_lock_graph (engine)) { | |||
/* engine can't run. just throw away an entire cycle */ | |||
fprintf (stderr, "#*#*#*#*# NULL CYCLE\n"); | |||
driver->null_cycle (driver, nframes); | |||
return 0; | |||
} | |||
if (driver->read (driver, nframes)) { | |||
return -1; | |||
goto unlock; | |||
} | |||
if (jack_engine_process (engine, nframes)) { | |||
@@ -2086,25 +2089,36 @@ jack_run_cycle (jack_engine_t *engine, jack_nframes_t nframes) | |||
fprintf (stderr, "restart\n"); | |||
} else { | |||
if (driver->write (driver, nframes)) { | |||
return -1; | |||
goto unlock; | |||
} | |||
} | |||
jack_engine_post_process (engine); | |||
jack_engine_process_unlock (engine); | |||
if ((ret = jack_engine_post_process (engine)) > 0) { | |||
ret = 0; | |||
goto maybe_restart; /* leave engine locked */ | |||
} | |||
ret = 0; | |||
unlock: | |||
jack_unlock_graph (engine); | |||
maybe_restart: | |||
if (restart) { | |||
driver->start (driver); | |||
} | |||
return 0; | |||
return ret; | |||
} | |||
static void * | |||
jack_main_thread (void *arg) | |||
{ | |||
jack_engine_t *engine = (jack_engine_t *) arg; | |||
jack_driver_t *driver = engine->driver; | |||
int wait_status; | |||
jack_nframes_t nframes; | |||
float delayed_usecs; | |||
if (engine->control->real_time) { | |||
@@ -2119,28 +2133,24 @@ jack_main_thread (void *arg) | |||
pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, NULL); | |||
engine->watchdog_check = 1; /* really needed here ? */ | |||
nframes = 0; /* really needed here ? */ | |||
engine->watchdog_check = 1; | |||
while (1) { | |||
int wait_status = jack_engine_wait (engine, &nframes); | |||
if (wait_status == -1) { | |||
break; | |||
} else if (wait_status == 0) { | |||
if (jack_run_cycle (engine, nframes)) { | |||
if ((nframes = driver->wait (driver, -1, &wait_status, &delayed_usecs)) == 0) { | |||
/* the driver detected an xrun, and restarted */ | |||
continue; | |||
} | |||
if (wait_status == 0) { | |||
if (jack_run_cycle (engine, nframes, delayed_usecs)) { | |||
jack_error ("cycle execution failure, exiting"); | |||
break; | |||
} | |||
} else if (wait_status < 0) { | |||
break; | |||
} else { | |||
/* driver restarted, just continue */ | |||
} | |||
} | |||
@@ -784,7 +784,7 @@ jack_client_thread (void *arg) | |||
jack_reset_timestamps (); | |||
#endif | |||
DEBUG ("client %d signalled at %Lu, awake for process at %Lu (delay = %f usecs) (wakeup on graph_wait_fd==%d)", | |||
DEBUG ("client %d signalled at %Lu, awake for process at %Lu (delay = %Lu usecs) (wakeup on graph_wait_fd==%d)", | |||
getpid(), | |||
control->signalled_at, | |||
control->awake_at, | |||
@@ -808,9 +808,9 @@ jack_client_thread (void *arg) | |||
#endif | |||
/* pass the execution token along */ | |||
DEBUG ("client finished processing at %Lu (elapsed = %f usecs), writing on graph_next_fd==%d", | |||
DEBUG ("client finished processing at %Lu (elapsed = %Lu usecs), writing on graph_next_fd==%d", | |||
control->finished_at, | |||
((float)(control->finished_at - control->awake_at)/client->cpu_mhz), | |||
control->finished_at - control->awake_at, | |||
client->graph_next_fd); | |||
if (write (client->graph_next_fd, &c, sizeof (c)) != sizeof (c)) { | |||