Browse Source

use driver wait function when waiting for subgraphs

git-svn-id: svn+ssh://jackaudio.org/trunk/jack@114 0c269be4-1314-0410-8aa9-9f06e86f4224
tags/0.109.0
pbd 24 years ago
parent
commit
5577043352
5 changed files with 134 additions and 113 deletions
  1. +78
    -59
      alsa_driver.c
  2. +1
    -1
      configure.in
  3. +3
    -1
      driver.c
  4. +45
    -47
      engine.c
  5. +7
    -5
      jack/driver.h

+ 78
- 59
alsa_driver.c View File

@@ -565,7 +565,7 @@ alsa_driver_audio_start (alsa_driver_t *driver)
if (driver->pfd)
free (driver->pfd);
driver->pfd = (struct pollfd *) malloc (sizeof (struct pollfd) *
(driver->playback_nfds + driver->capture_nfds + 1));
(driver->playback_nfds + driver->capture_nfds + 2));

return 0;
}
@@ -648,28 +648,25 @@ alsa_driver_set_clock_sync_status (alsa_driver_t *driver, channel_t chn, ClockSy
}

static int under_gdb = FALSE;
static int waitcnt = 0;


static int
alsa_driver_wait (alsa_driver_t *driver)

static nframes_t
alsa_driver_wait (alsa_driver_t *driver, int fd, int *status)
{
snd_pcm_sframes_t avail = 0;
snd_pcm_sframes_t contiguous = 0;
snd_pcm_sframes_t capture_avail = 0;
snd_pcm_sframes_t playback_avail = 0;
snd_pcm_uframes_t capture_offset = 0;
snd_pcm_uframes_t playback_offset = 0;
int xrun_detected;
channel_t chn;
GSList *node;
int need_capture = 1;
int need_playback = 1;
jack_engine_t *engine = driver->engine;
int need_capture;
int need_playback;
int i;
static unsigned long long last = 0;
unsigned long long start;

*status = -1;
need_capture = 1;
if (fd >= 0) {
need_playback = 0;
} else {
need_playback = 1;
}

again:
@@ -698,6 +695,12 @@ alsa_driver_wait (alsa_driver_t *driver)
driver->pfd[nfds].events |= POLLERR;
}

if (fd >= 0) {
driver->pfd[nfds].fd = fd;
driver->pfd[nfds].events = POLLIN|POLLERR|POLLHUP|POLLNVAL;
nfds++;
}

if (poll (driver->pfd, nfds, 1000) < 0) {
if (errno == EINTR) {
printf ("poll interrupt\n");
@@ -706,16 +709,27 @@ alsa_driver_wait (alsa_driver_t *driver)
if (under_gdb) {
goto again;
}
return 1;
return 0;
}
jack_error ("ALSA::Device: poll call failed (%s)", strerror (errno));
return -1;
return 0;
}

rdtscll (start);
// fprintf (stderr, "engine cycle %.6f msecs\n", (((float) (start - last))/450000.0f));
last = start;
/* check to see if it was the extra FD that caused us to return from poll
*/

if (fd >= 0) {
if (driver->pfd[nfds-1].revents == 0) {
/* we timed out on the extra fd */
return -1;
} else {
/* if POLLIN was the only bit set, we're OK */
*status = 0;
return (driver->pfd[nfds-1].revents == POLLIN) ? 0 : -1;
}
}

if (driver->engine) {
struct timeval tv;
@@ -729,7 +743,7 @@ alsa_driver_wait (alsa_driver_t *driver)
for (i = 0; i < driver->playback_nfds; i++) {
if (driver->pfd[i].revents & POLLERR) {
jack_error ("ALSA: poll reports error on playback stream.");
return -1;
return 0;
}
if (driver->pfd[i].revents == 0) {
@@ -748,7 +762,7 @@ alsa_driver_wait (alsa_driver_t *driver)
for (i = ci; i < nfds; i++) {
if (driver->pfd[i].revents & POLLERR) {
jack_error ("ALSA: poll reports error on capture stream.");
return -1;
return 0;
}
if (driver->pfd[i].revents == 0) {
@@ -763,7 +777,7 @@ alsa_driver_wait (alsa_driver_t *driver)
if (p_timed_out == driver->playback_nfds && c_timed_out == driver->capture_nfds) {
jack_error ("ALSA: poll time out");
return -1;
return 0;
}

}
@@ -787,23 +801,37 @@ alsa_driver_wait (alsa_driver_t *driver)
}

if (xrun_detected) {
return alsa_driver_xrun_recovery (driver);
*status = alsa_driver_xrun_recovery (driver);
return 0;
}

*status = 0;

avail = capture_avail < playback_avail ? capture_avail : playback_avail;
/* constrain the available count to the nearest (round down) number of
periods.
*/

avail = avail - (avail % driver->frames_per_cycle);
return avail - (avail % driver->frames_per_cycle);
}

while (avail) {
static int
alsa_driver_process (alsa_driver_t *driver, nframes_t nframes)
{
snd_pcm_sframes_t contiguous = 0;
snd_pcm_sframes_t capture_avail = 0;
snd_pcm_sframes_t playback_avail = 0;
snd_pcm_uframes_t capture_offset = 0;
snd_pcm_uframes_t playback_offset = 0;
channel_t chn;
GSList *node;
jack_engine_t *engine = driver->engine;

waitcnt++;
while (nframes) {

capture_avail = (avail > driver->frames_per_cycle) ? driver->frames_per_cycle : avail;
playback_avail = (avail > driver->frames_per_cycle) ? driver->frames_per_cycle : avail;
capture_avail = (nframes > driver->frames_per_cycle) ? driver->frames_per_cycle : nframes;
playback_avail = (nframes > driver->frames_per_cycle) ? driver->frames_per_cycle : nframes;
if (alsa_driver_get_channel_addresses (driver,
(snd_pcm_uframes_t *) &capture_avail,
@@ -817,9 +845,25 @@ alsa_driver_wait (alsa_driver_t *driver)
driver->channels_not_done = driver->channel_done_bits;

if (engine->process_lock (engine) == 0) {

channel_t chn;
jack_port_t *port;
GSList *node;
int ret;
GSList *prev;

for (chn = 0, node = driver->capture_ports; node; node = g_slist_next (node), chn++) {
port = (jack_port_t *) node->data;
if (!jack_port_connected (port)) {
continue;
}
alsa_driver_read_from_channel (driver, chn, jack_port_get_buffer (port, nframes), nframes);
}

snd_pcm_mmap_commit (driver->capture_handle, capture_offset, contiguous);
if ((ret = engine->process (engine, contiguous)) != 0) {
engine->process_unlock (engine);
alsa_driver_audio_stop (driver);
@@ -831,7 +875,7 @@ alsa_driver_wait (alsa_driver_t *driver)

/* now move data from ports to channels */
for (chn = 0, prev = 0, node = driver->playback_ports; node; prev = node, node = g_slist_next (node), chn++) {
for (chn = 0, node = driver->playback_ports; node; node = g_slist_next (node), chn++) {
jack_port_t *port = (jack_port_t *) node->data;

@@ -880,39 +924,15 @@ alsa_driver_wait (alsa_driver_t *driver)
alsa_driver_silence_untouched_channels (driver, contiguous);
}

snd_pcm_mmap_commit (driver->capture_handle, capture_offset, contiguous);
snd_pcm_mmap_commit (driver->playback_handle, playback_offset, contiguous);

avail -= contiguous;
nframes -= contiguous;
}
engine->post_process (engine);
return 0;
}

static int
alsa_driver_process (nframes_t nframes, void *arg)

{
alsa_driver_t *driver = (alsa_driver_t *) arg;
channel_t chn;
jack_port_t *port;
GSList *node;

for (chn = 0, node = driver->capture_ports; node; node = g_slist_next (node), chn++) {

port = (jack_port_t *) node->data;
if (!jack_port_connected (port)) {
continue;
}
alsa_driver_read_from_channel (driver, chn, jack_port_get_buffer (port, nframes), nframes);
}

return 0;
}

static void
alsa_driver_attach (alsa_driver_t *driver, jack_engine_t *engine)

@@ -933,8 +953,6 @@ alsa_driver_attach (alsa_driver_t *driver, jack_engine_t *engine)
return;
}

jack_set_process_callback (driver->client, alsa_driver_process, driver);

for (chn = 0; chn < driver->capture_nchannels; chn++) {
snprintf (buf, sizeof(buf) - 1, "in_%lu", chn+1);
port = jack_port_register (driver->client, buf,
@@ -1128,6 +1146,7 @@ alsa_driver_new (char *name, char *alsa_device,
driver->attach = (JackDriverAttachFunction) alsa_driver_attach;
driver->detach = (JackDriverDetachFunction) alsa_driver_detach;
driver->wait = (JackDriverWaitFunction) alsa_driver_wait;
driver->process = (JackDriverProcessFunction) alsa_driver_process;
driver->start = (JackDriverStartFunction) alsa_driver_audio_start;
driver->stop = (JackDriverStopFunction) alsa_driver_audio_stop;



+ 1
- 1
configure.in View File

@@ -5,7 +5,7 @@ AC_CONFIG_AUX_DIR(.)

JACK_MAJOR_VERSION=0
JACK_MINOR_VERSION=11
JACK_MICRO_VERSION=6
JACK_MICRO_VERSION=7

BETA=



+ 3
- 1
driver.c View File

@@ -28,7 +28,8 @@

static int dummy_attach (jack_driver_t *drv, jack_engine_t *eng) { return 0; }
static int dummy_detach (jack_driver_t *drv, jack_engine_t *eng) { return 0; }
static int dummy_wait (jack_driver_t *drv) { return 0; }
static nframes_t dummy_wait (jack_driver_t *drv, int fd, int *status) { *status = 0; return 0; }
static int dummy_process (jack_driver_t *drv, nframes_t nframes) { return 0; }
static int dummy_stop (jack_driver_t *drv) { return 0; }
static int dummy_start (jack_driver_t *drv) { return 0; }

@@ -41,6 +42,7 @@ jack_driver_init (jack_driver_t *driver)
driver->attach = dummy_attach;
driver->detach = dummy_detach;
driver->wait = dummy_wait;
driver->process = dummy_process;
driver->start = dummy_start;
driver->stop = dummy_stop;
}


+ 45
- 47
engine.c View File

@@ -368,7 +368,7 @@ jack_add_port_segment (jack_engine_t *engine, unsigned long nports)

/* convert the first chunk of the segment into a zero-filled area */

if (engine->silent_buffer == 0) {
if (engine->silent_buffer == NULL) {
engine->silent_buffer = (jack_port_buffer_info_t *) engine->port_buffer_freelist->data;

engine->port_buffer_freelist = g_slist_remove_link (engine->port_buffer_freelist, engine->port_buffer_freelist);
@@ -420,12 +420,11 @@ jack_engine_process_unlock (jack_engine_t *engine)
static int
jack_process (jack_engine_t *engine, nframes_t nframes)
{
int err = 0;
jack_client_internal_t *client;
jack_client_control_t *ctl;
GSList *node;
struct pollfd pollfd[1];
char c;
int status;

engine->process_errors = 0;

@@ -439,7 +438,7 @@ jack_process (jack_engine_t *engine, nframes_t nframes)
engine->control->time.frame = engine->timebase_client->control->frame_time;
}

for (node = engine->clients; err == 0 && node; ) {
for (node = engine->clients; engine->process_errors == 0 && node; ) {

client = (jack_client_internal_t *) node->data;

@@ -454,14 +453,20 @@ jack_process (jack_engine_t *engine, nframes_t nframes)

/* in-process client ("plugin") */

ctl->state = Running;
if (ctl->process) {

ctl->state = Running;

if (ctl->process (nframes, ctl->process_arg) == 0) {
ctl->state = Finished;
} else {
jack_error ("in-process client %s failed", client->control->name);
engine->process_errors++;
break;
}

if (ctl->process (nframes, ctl->process_arg) == 0) {
ctl->state = Finished;
} else {
jack_error ("in-process client %s failed", client->control->name);
engine->process_errors++;
break;
ctl->state = Finished;
}

node = g_slist_next (node);
@@ -478,28 +483,11 @@ jack_process (jack_engine_t *engine, nframes_t nframes)
break;
}

/* now wait for the result. use poll instead of read so that we
can timeout effectively.
*/

pollfd[0].fd = client->subgraph_wait_fd;
pollfd[0].events = POLLIN|POLLERR|POLLHUP|POLLNVAL;

if (poll (pollfd, 1, engine->driver->period_interval) < 0) {
if (errno == EINTR) {
continue;
}
jack_error ("engine cannot poll for graph completion (%s)", strerror (errno));
engine->process_errors++;
break;
}

if (pollfd[0].revents == 0) {
jack_error ("subgraph starting at %s timed out (state = %d)", client->control->name, client->control->state);
engine->process_errors++;
break;
} else if (pollfd[0].revents & ~POLLIN) {
jack_error ("error/hangup on graph wait fd");
engine->driver->wait (engine->driver, client->subgraph_wait_fd, &status);
if (status != 0) {
jack_error ("subgraph starting at %s timed out (status = %d, state = %d)",
client->control->name, status, client->control->state);
engine->process_errors++;
break;
} else {
@@ -542,7 +530,7 @@ jack_load_client (jack_engine_t *engine, jack_client_internal_t *client, const c

handle = dlopen (path_to_so, RTLD_NOW|RTLD_GLOBAL);
if (handle == 0) {
if (handle == NULL) {
if ((errstr = dlerror ()) != 0) {
jack_error ("can't load \"%s\": %s", path_to_so, errstr);
} else {
@@ -844,8 +832,8 @@ handle_client_jack_error (jack_engine_t *engine, int fd)
}
}

if (client == 0) {
jack_error ("no client found for fd %d\n", fd);
if (client == NULL) {
/* client removed by driver thread */
pthread_mutex_unlock (&engine->graph_lock);
return -1;
}
@@ -875,7 +863,7 @@ handle_client_io (jack_engine_t *engine, int fd)

pthread_mutex_unlock (&engine->graph_lock);

if (client == 0) {
if (client == NULL) {
jack_error ("client input on unknown fd %d!", fd);
return -1;
}
@@ -1214,10 +1202,20 @@ jack_main_thread (void *arg)
}

while (1) {
switch (driver->wait (driver)) {
case -1:
int status;
nframes_t nframes;

nframes = driver->wait (driver, -1, &status);

if (status != 0) {
jack_error ("driver wait function failed, exiting");
pthread_exit (0);
}

switch (driver->process (driver, nframes)) {
case -1:
jack_error ("driver process function failed, exiting");
pthread_exit (0);
break;

case 1:
@@ -1239,7 +1237,7 @@ int
jack_run (jack_engine_t *engine)

{
if (engine->driver == 0) {
if (engine->driver == NULL) {
jack_error ("engine driver not set; cannot start");
return -1;
}
@@ -1626,7 +1624,7 @@ jack_rechain_graph (jack_engine_t *engine, int take_lock)
} else {
if (subgraph_client == 0) {
if (subgraph_client == NULL) {
/* start a new subgraph. the engine will start the chain
by writing to the nth FIFO.
@@ -1667,7 +1665,7 @@ jack_trace_terminal (jack_client_internal_t *c1, jack_client_internal_t *rbase)
GSList *existing;
GSList *node;

if (c1->fed_by == 0) {
if (c1->fed_by == NULL) {
return;
}

@@ -1893,12 +1891,12 @@ jack_port_do_connect (jack_engine_t *engine,
jack_port_internal_t *srcport, *dstport;
jack_port_id_t src_id, dst_id;

if ((srcport = jack_get_port_by_name (engine, source_port)) == 0) {
if ((srcport = jack_get_port_by_name (engine, source_port)) == NULL) {
jack_error ("unknown source port in attempted connection [%s]", source_port);
return -1;
}

if ((dstport = jack_get_port_by_name (engine, destination_port)) == 0) {
if ((dstport = jack_get_port_by_name (engine, destination_port)) == NULL) {
jack_error ("unknown destination port in attempted connection [%s]", destination_port);
return -1;
}
@@ -2053,12 +2051,12 @@ jack_port_do_disconnect (jack_engine_t *engine,
jack_port_internal_t *srcport, *dstport;
int ret = -1;

if ((srcport = jack_get_port_by_name (engine, source_port)) == 0) {
if ((srcport = jack_get_port_by_name (engine, source_port)) == NULL) {
jack_error ("unknown source port in attempted disconnection [%s]", source_port);
return -1;
}

if ((dstport = jack_get_port_by_name (engine, destination_port)) == 0) {
if ((dstport = jack_get_port_by_name (engine, destination_port)) == NULL) {
jack_error ("unknown destination port in attempted connection [%s]", destination_port);
return -1;
}
@@ -2281,7 +2279,7 @@ jack_port_do_register (jack_engine_t *engine, jack_request_t *req)
jack_client_internal_t *client;

pthread_mutex_lock (&engine->graph_lock);
if ((client = jack_client_internal_by_id (engine, req->x.port_info.client_id)) == 0) {
if ((client = jack_client_internal_by_id (engine, req->x.port_info.client_id)) == NULL) {
jack_error ("unknown client id in port registration request");
return -1;
}
@@ -2466,7 +2464,7 @@ jack_send_connection_notification (jack_engine_t *engine, jack_client_id_t clien
jack_client_internal_t *client;
jack_event_t event;

if ((client = jack_client_internal_by_id (engine, client_id)) == 0) {
if ((client = jack_client_internal_by_id (engine, client_id)) == NULL) {
jack_error ("no such client %d during connection notification", client_id);
return -1;
}


+ 7
- 5
jack/driver.h View File

@@ -37,11 +37,12 @@ typedef struct {
struct _jack_engine;
struct _jack_driver;

typedef int (*JackDriverAttachFunction)(struct _jack_driver *, struct _jack_engine *);
typedef int (*JackDriverDetachFunction)(struct _jack_driver *, struct _jack_engine *);
typedef int (*JackDriverWaitFunction)(struct _jack_driver *);
typedef int (*JackDriverStopFunction)(struct _jack_driver *);
typedef int (*JackDriverStartFunction)(struct _jack_driver *);
typedef int (*JackDriverAttachFunction)(struct _jack_driver *, struct _jack_engine *);
typedef int (*JackDriverDetachFunction)(struct _jack_driver *, struct _jack_engine *);
typedef nframes_t (*JackDriverWaitFunction)(struct _jack_driver *, int fd, int *status);
typedef int (*JackDriverProcessFunction)(struct _jack_driver *, nframes_t);
typedef int (*JackDriverStopFunction)(struct _jack_driver *);
typedef int (*JackDriverStartFunction)(struct _jack_driver *);

#define JACK_DRIVER_DECL \
nframes_t period_interval; \
@@ -50,6 +51,7 @@ typedef int (*JackDriverStartFunction)(struct _jack_driver *);
JackDriverAttachFunction attach; \
JackDriverDetachFunction detach; \
JackDriverWaitFunction wait; \
JackDriverProcessFunction process; \
JackDriverStartFunction stop; \
JackDriverStopFunction start;



Loading…
Cancel
Save