Browse Source

more changes to support CoreAudio (external callback), added monitoring port option to alsa driver, removed vestiges of non-usec based time

git-svn-id: svn+ssh://jackaudio.org/trunk/jack@370 0c269be4-1314-0410-8aa9-9f06e86f4224
tags/0.109.0
pbd 22 years ago
parent
commit
b09cf5162d
6 changed files with 216 additions and 163 deletions
  1. +1
    -1
      configure.in
  2. +52
    -19
      drivers/alsa/alsa_driver.c
  3. +8
    -7
      jack/alsa_driver.h
  4. +12
    -3
      jack/driver.h
  5. +140
    -130
      jackd/engine.c
  6. +3
    -3
      libjack/client.c

+ 1
- 1
configure.in View File

@@ -14,7 +14,7 @@ dnl changes are made
dnl --- dnl ---
JACK_MAJOR_VERSION=0 JACK_MAJOR_VERSION=0
JACK_MINOR_VERSION=67 JACK_MINOR_VERSION=67
JACK_MICRO_VERSION=2
JACK_MICRO_VERSION=3


dnl --- dnl ---
dnl HOWTO: updating the jack protocal version dnl HOWTO: updating the jack protocal version


+ 52
- 19
drivers/alsa/alsa_driver.c View File

@@ -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->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) { if (driver->engine) {
driver->engine->set_buffer_size (driver->engine, driver->frames_per_cycle); 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_capture;
int need_playback; int need_playback;
unsigned int i; unsigned int i;
unsigned long long poll_enter, poll_ret;
jack_time_t poll_enter, poll_ret;


*status = -1; *status = -1;
*delayed_usecs = 0; *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 (); 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) { if (errno == EINTR) {
printf ("poll interrupt\n"); printf ("poll interrupt\n");
// this happens mostly when run // 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 (extra_fd < 0) {
if (driver->poll_next && poll_ret > driver->poll_next) { 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_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; driver->engine->control->current_time.usecs = poll_ret;
} }


#ifdef DEBUG_WAKEUP #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 #endif


/* check to see if it was the extra FD that caused us to return from poll /* 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)) && if ((p_timed_out && (p_timed_out == driver->playback_nfds)) &&
(c_timed_out && (c_timed_out == driver->capture_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; *status = -5;
return 0; return 0;
} }
@@ -1010,6 +1012,7 @@ alsa_driver_wait (alsa_driver_t *driver, int extra_fd, int *status, float *delay
} }


*status = 0; *status = 0;
driver->last_wait_ust = poll_ret;


avail = capture_avail < playback_avail ? capture_avail : playback_avail; 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; jack_nframes_t nf;
snd_pcm_uframes_t offset; snd_pcm_uframes_t offset;
snd_pcm_uframes_t contiguous; 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) { if (driver->capture_handle) {
nf = nframes; nf = nframes;
@@ -1073,6 +1073,10 @@ alsa_driver_null_cycle (alsa_driver_t* driver, jack_nframes_t nframes)
return -1; 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) { if (snd_pcm_mmap_commit (driver->playback_handle, offset, contiguous) < 0) {
return -1; return -1;
} }
@@ -1192,9 +1196,14 @@ alsa_driver_write (alsa_driver_t* driver, jack_nframes_t nframes)
buf = jack_port_get_buffer (port, contiguous); 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) { if (!driver->hw_monitoring) {
alsa_driver_copy_channel (driver, chn, chn, contiguous); 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 { } else {
alsa_driver_write_to_channel (driver, chn, buf + nwritten, contiguous); 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; port_flags = JackPortIsInput|JackPortIsPhysical|JackPortIsTerminal;


for (chn = 0; chn < driver->playback_nchannels; chn++) { for (chn = 0; chn < driver->playback_nchannels; chn++) {
jack_port_t *monitor_port;

snprintf (buf, sizeof(buf) - 1, "playback_%lu", chn+1); 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) { 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); jack_port_set_latency (port, driver->frames_per_cycle * driver->nfragments);


driver->playback_ports = jack_slist_append (driver->playback_ports, port); 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); jack_activate (driver->client);
@@ -1429,7 +1450,8 @@ alsa_driver_new (char *name, char *alsa_device,
int capturing, int capturing,
int playing, int playing,
DitherAlgorithm dither, DitherAlgorithm dither,
int soft_mode)
int soft_mode,
int monitor)
{ {
int err; int err;


@@ -1466,7 +1488,7 @@ alsa_driver_new (char *name, char *alsa_device,
driver->capture_addr = 0; driver->capture_addr = 0;
driver->silent = 0; driver->silent = 0;
driver->all_monitor_in = FALSE; driver->all_monitor_in = FALSE;
driver->cpu_mhz = jack_get_mhz();
driver->with_monitor_ports = monitor;


driver->clock_mode = ClockMaster; /* XXX is it? */ driver->clock_mode = ClockMaster; /* XXX is it? */
driver->input_monitor_mask = 0; /* XXX is it? */ driver->input_monitor_mask = 0; /* XXX is it? */
@@ -1668,6 +1690,7 @@ alsa_usage ()
" -C,--capture \tcapture input (default: duplex)\n" " -C,--capture \tcapture input (default: duplex)\n"
" -P,--playback\tplayback output (default: duplex)\n" " -P,--playback\tplayback output (default: duplex)\n"
" -s,--softmode\tsoft-mode, no xrun handling (default: off)\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 \tdithering mode:\n"
" -z-,--dither (off, the default)\n" " -z-,--dither (off, the default)\n"
" -zr,--dither=rectangular\n" " -zr,--dither=rectangular\n"
@@ -1727,6 +1750,7 @@ driver_initialize (jack_client_t *client, int argc, char **argv)
int capture = FALSE; int capture = FALSE;
int playback = FALSE; int playback = FALSE;
int soft_mode = FALSE; int soft_mode = FALSE;
int monitor = FALSE;
DitherAlgorithm dither = None; DitherAlgorithm dither = None;
int opt; int opt;
char *envvar; char *envvar;
@@ -1745,6 +1769,7 @@ driver_initialize (jack_client_t *client, int argc, char **argv)
{ "nperiods", 1, NULL, 'n' }, { "nperiods", 1, NULL, 'n' },
{ "softmode", 1, NULL, 's' }, { "softmode", 1, NULL, 's' },
{ "dither", 2, NULL, 'z' }, { "dither", 2, NULL, 'z' },
{ "monitor", 0, NULL, 'm' },
{ 0, 0, 0, 0 } { 0, 0, 0, 0 }
}; };


@@ -1790,6 +1815,10 @@ driver_initialize (jack_client_t *client, int argc, char **argv)
playback = atoi (envvar); 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 * Setting optind back to zero is a hack to reinitialize a new
* getopts() loop. See declaration in <getopt.h>. * getopts() loop. See declaration in <getopt.h>.
@@ -1798,7 +1827,7 @@ driver_initialize (jack_client_t *client, int argc, char **argv)
optind = 0; optind = 0;
opterr = 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)) long_options, NULL))
!= EOF) { != EOF) {
switch (opt) { switch (opt) {
@@ -1824,6 +1853,10 @@ driver_initialize (jack_client_t *client, int argc, char **argv)
alsa_usage(); alsa_usage();
return NULL; return NULL;


case 'm':
monitor = TRUE;
break;

case 'M': case 'M':
hw_metering = TRUE; hw_metering = TRUE;
break; 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, return alsa_driver_new ("alsa_pcm", pcm_name, client, frames_per_interrupt,
user_nperiods, srate, hw_monitoring, hw_metering, capture, user_nperiods, srate, hw_monitoring, hw_metering, capture,
playback, dither, soft_mode);
playback, dither, soft_mode, monitor);
} }


void void


+ 8
- 7
jack/alsa_driver.h View File

@@ -45,8 +45,9 @@ typedef struct {


JACK_DRIVER_DECL 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 **playback_addr;
char **capture_addr; char **capture_addr;
const snd_pcm_channel_area_t *capture_areas; const snd_pcm_channel_area_t *capture_areas;
@@ -63,11 +64,10 @@ typedef struct {
channel_t capture_nchannels; channel_t capture_nchannels;
unsigned long sample_bytes; 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; unsigned long *silent;
char *alsa_name; char *alsa_name;
@@ -102,6 +102,7 @@ typedef struct {
char all_monitor_in : 1; char all_monitor_in : 1;
char capture_and_playback_not_synced : 1; char capture_and_playback_not_synced : 1;
char interleaved : 1; char interleaved : 1;
char with_monitor_ports : 1;


ReadCopyFunction read_via_copy; ReadCopyFunction read_via_copy;
WriteCopyFunction write_via_copy; WriteCopyFunction write_via_copy;


+ 12
- 3
jack/driver.h View File

@@ -80,9 +80,17 @@ typedef jack_nframes_t (*JackDriverWaitFunction)(struct _jack_driver *, int fd,
#define JACK_DRIVER_DECL #define JACK_DRIVER_DECL


/* the driver should set this to be the interval it expects to elapse /* 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 /* this is not used by the driver. it should not be written to or
modified in any way modified in any way
@@ -180,7 +188,8 @@ typedef jack_nframes_t (*JackDriverWaitFunction)(struct _jack_driver *, int fd,
#else #else


#define JACK_DRIVER_DECL \ #define JACK_DRIVER_DECL \
jack_nframes_t period_usecs; \
jack_time_t period_usecs; \
jack_time_t last_wait_ust; \
void *handle; \ void *handle; \
void (*finish)(struct _jack_driver *);\ void (*finish)(struct _jack_driver *);\
JackDriverAttachFunction attach; \ JackDriverAttachFunction attach; \


+ 140
- 130
jackd/engine.c View File

@@ -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_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 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 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 jack_engine_post_process (jack_engine_t *);


static int internal_client_request (void*, jack_request_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); 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 static inline void
jack_engine_reset_rolling_usecs (jack_engine_t *engine) 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; 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 * static JSList *
jack_process_internal(jack_engine_t *engine, JSList *node, jack_nframes_t nframes) 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 (status != 0) {
if (engine->verbose) { 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. /* 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 static int
jack_engine_post_process (jack_engine_t *engine) 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; jack_client_internal_t *client;
JSList *node; JSList *node;
int need_remove = FALSE; int need_remove = FALSE;
int ret;

/* maintain the current_time.usecs and frame_rate values, since clients /* maintain the current_time.usecs and frame_rate values, since clients
are not permitted to set these. are not permitted to set these.
*/ */
@@ -792,63 +846,19 @@ jack_engine_post_process (jack_engine_t *engine)
need_remove = TRUE; need_remove = TRUE;
} }
} }
if (need_remove) { 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 static int
@@ -1997,6 +2007,12 @@ jack_engine_notify_clients_about_delay (jack_engine_t *engine)
jack_unlock_graph (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 static inline void
jack_inc_frame_time (jack_engine_t *engine, jack_nframes_t amount) 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->guard1++;
time->frames += amount; time->frames += amount;
time->stamp = jack_get_microseconds ();
time->stamp = jack_get_wait_timestamp (engine);


// atomic_inc (&time->guard2, 1); // atomic_inc (&time->guard2, 1);
// might need a memory barrier here // might need a memory barrier here
@@ -2015,26 +2031,19 @@ jack_inc_frame_time (jack_engine_t *engine, jack_nframes_t amount)
} }


static int 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; 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; engine->watchdog_check = 1;


#define WORK_SCALE 1.0f #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", fprintf (stderr, "delay of %.3f usecs exceeds estimated spare time of %.3f; restart ...\n",
delayed_usecs, WORK_SCALE * engine->spare_usecs); 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 exit the thread loop */
} }


return 1; /* will continue */
return 0;


} else { } else {
consecutive_excessive_delays = 0; 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 */ /* engine can't run. just throw away an entire cycle */
fprintf (stderr, "#*#*#*#*# NULL CYCLE\n");
driver->null_cycle (driver, nframes); driver->null_cycle (driver, nframes);
return 0; return 0;
} }
if (driver->read (driver, nframes)) { if (driver->read (driver, nframes)) {
return -1;
goto unlock;
} }


if (jack_engine_process (engine, nframes)) { 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"); fprintf (stderr, "restart\n");
} else { } else {
if (driver->write (driver, nframes)) { 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) { if (restart) {
driver->start (driver); driver->start (driver);
} }
return 0;
return ret;
} }


static void * static void *
jack_main_thread (void *arg) jack_main_thread (void *arg)
{ {
jack_engine_t *engine = (jack_engine_t *) arg; jack_engine_t *engine = (jack_engine_t *) arg;
jack_driver_t *driver = engine->driver;
int wait_status;
jack_nframes_t nframes; jack_nframes_t nframes;
float delayed_usecs;


if (engine->control->real_time) { if (engine->control->real_time) {


@@ -2119,28 +2133,24 @@ jack_main_thread (void *arg)


pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, NULL); pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, NULL);


engine->watchdog_check = 1; /* really needed here ? */
nframes = 0; /* really needed here ? */
engine->watchdog_check = 1;


while (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"); jack_error ("cycle execution failure, exiting");
break; break;
} }

} else if (wait_status < 0) {
break;
} else { } else {

/* driver restarted, just continue */ /* driver restarted, just continue */
} }
} }




+ 3
- 3
libjack/client.c View File

@@ -784,7 +784,7 @@ jack_client_thread (void *arg)
jack_reset_timestamps (); jack_reset_timestamps ();
#endif #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(), getpid(),
control->signalled_at, control->signalled_at,
control->awake_at, control->awake_at,
@@ -808,9 +808,9 @@ jack_client_thread (void *arg)
#endif #endif
/* pass the execution token along */ /* 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, control->finished_at,
((float)(control->finished_at - control->awake_at)/client->cpu_mhz),
control->finished_at - control->awake_at,
client->graph_next_fd); client->graph_next_fd);


if (write (client->graph_next_fd, &c, sizeof (c)) != sizeof (c)) { if (write (client->graph_next_fd, &c, sizeof (c)) != sizeof (c)) {


Loading…
Cancel
Save