From 5577043352c848bf09a290d93bbfc5d3304b681a Mon Sep 17 00:00:00 2001 From: pbd Date: Sat, 16 Feb 2002 21:28:47 +0000 Subject: [PATCH] use driver wait function when waiting for subgraphs git-svn-id: svn+ssh://jackaudio.org/trunk/jack@114 0c269be4-1314-0410-8aa9-9f06e86f4224 --- alsa_driver.c | 137 ++++++++++++++++++++++++++++---------------------- configure.in | 2 +- driver.c | 4 +- engine.c | 92 +++++++++++++++++---------------- jack/driver.h | 12 +++-- 5 files changed, 134 insertions(+), 113 deletions(-) diff --git a/alsa_driver.c b/alsa_driver.c index 6f58a3a..7f1e625 100644 --- a/alsa_driver.c +++ b/alsa_driver.c @@ -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; diff --git a/configure.in b/configure.in index 5df172a..ec17d9e 100644 --- a/configure.in +++ b/configure.in @@ -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= diff --git a/driver.c b/driver.c index 907a7ec..d447a81 100644 --- a/driver.c +++ b/driver.c @@ -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; } diff --git a/engine.c b/engine.c index 0180bad..fdac5b9 100644 --- a/engine.c +++ b/engine.c @@ -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; } diff --git a/jack/driver.h b/jack/driver.h index 69dcaf2..75ec0d6 100644 --- a/jack/driver.h +++ b/jack/driver.h @@ -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;