diff --git a/configure.ac b/configure.ac index f060c4a..e09b470 100644 --- a/configure.ac +++ b/configure.ac @@ -17,7 +17,7 @@ dnl changes are made dnl --- JACK_MAJOR_VERSION=0 JACK_MINOR_VERSION=111 -JACK_MICRO_VERSION=1 +JACK_MICRO_VERSION=2 dnl --- dnl HOWTO: updating the jack protocol version diff --git a/drivers/sun/sun_driver.c b/drivers/sun/sun_driver.c index c5f8f67..e3f3d55 100644 --- a/drivers/sun/sun_driver.c +++ b/drivers/sun/sun_driver.c @@ -175,10 +175,7 @@ sun_driver_write_silence (sun_driver_t *driver, jack_nframes_t nframes) return; } - printf("sun_driver: writing %ld bytes of silence: " - "nframes = %ld, bits = %d, channels = %d\n", - (long)localsize, (long)nframes, driver->bits, - driver->playback_channels); + printf("sun_driver: writing %ld frames of silence\n", (long)nframes); bzero(localbuf, localsize); io_res = write(driver->outfd, localbuf, localsize); @@ -208,10 +205,7 @@ sun_driver_read_silence (sun_driver_t *driver, jack_nframes_t nframes) return; } - printf("sun_driver: reading %ld bytes of silence: " - "nframes = %ld, bits = %d, channels = %d\n", - (long)localsize, (long)nframes, driver->bits, - driver->capture_channels); + printf("sun_driver: reading %ld frames of silence\n", (long)nframes); io_res = read(driver->infd, localbuf, localsize); if (io_res < (ssize_t) localsize) @@ -232,14 +226,12 @@ sun_driver_wait (sun_driver_t *driver, int *status, float *iodelay) float delay; jack_time_t poll_enter; jack_time_t poll_ret = 0; - int capture_avail = 0; - int playback_avail = 0; int need_capture = 0; int need_playback = 0; int capture_errors = 0; int playback_errors = 0; - *status = 0; + *status = -1; *iodelay = 0; if (driver->infd >= 0) @@ -248,6 +240,13 @@ sun_driver_wait (sun_driver_t *driver, int *status, float *iodelay) if (driver->outfd >= 0) need_playback = 1; + poll_enter = jack_get_microseconds(); + if (poll_enter > driver->poll_next) + { + /* late. don't count as wakeup delay. */ + driver->poll_next = 0; + } + while (need_capture || need_playback) { pfd[0].fd = driver->infd; @@ -255,13 +254,6 @@ sun_driver_wait (sun_driver_t *driver, int *status, float *iodelay) pfd[1].fd = driver->outfd; pfd[1].events = POLLOUT; - poll_enter = jack_get_microseconds(); - if (poll_enter > driver->poll_next) - { - /* late. don't count as wakeup delay. */ - driver->poll_next = 0; - } - nfds = poll(pfd, 2, driver->poll_timeout); if ( nfds == -1 || ((pfd[0].revents | pfd[1].revents) & @@ -269,37 +261,34 @@ sun_driver_wait (sun_driver_t *driver, int *status, float *iodelay) { jack_error("sun_driver: poll() error: %s: %s@%i", strerror(errno), __FILE__, __LINE__); - *status = -1; + *status = -3; return 0; } - poll_ret = jack_get_microseconds(); - - if (driver->poll_next && poll_ret > driver->poll_next) - *iodelay = poll_ret - driver->poll_next; - driver->poll_last = poll_ret; - driver->poll_next = poll_ret + driver->period_usecs; - driver->engine->transport_cycle_start(driver->engine, poll_ret); if (nfds == 0) { - jack_error("sun_driver: poll() timeout, waited " - "%" PRIu64 " usecs: %s@%i", - poll_ret - poll_enter, __FILE__, __LINE__); + jack_error("sun_driver: poll() timeout: %s@%i", + __FILE__, __LINE__); + *status = -5; return 0; } if (need_capture && (pfd[0].revents & POLLIN)) - { - capture_avail = 1; need_capture = 0; - } + if (need_playback && (pfd[1].revents & POLLOUT)) - { - playback_avail = 1; need_playback = 0; - } } + poll_ret = jack_get_microseconds(); + + if (driver->poll_next && poll_ret > driver->poll_next) + *iodelay = poll_ret - driver->poll_next; + + driver->poll_last = poll_ret; + driver->poll_next = poll_ret + driver->period_usecs; + driver->engine->transport_cycle_start(driver->engine, poll_ret); + if (driver->infd >= 0) { if (ioctl(driver->infd, AUDIO_RERROR, &capture_errors) < 0) @@ -314,11 +303,11 @@ sun_driver_wait (sun_driver_t *driver, int *status, float *iodelay) if (capture_errors > 0) { delay = (capture_errors * 1000.0) / driver->sample_rate; - jack_error("sun_driver: capture xrun of %d frames (%f msec)", + printf("sun_driver: capture xrun of %d frames (%f msec)\n", capture_errors, delay); delay = (driver->capture_drops * 1000.0) / driver->sample_rate; - jack_error("sun_driver: total cpature xruns: %d frames " - "(%f msec)", driver->capture_drops, delay); + printf("sun_driver: total cpature xruns: %d frames " + "(%f msec)\n", driver->capture_drops, delay); } if (driver->outfd >= 0) @@ -335,15 +324,26 @@ sun_driver_wait (sun_driver_t *driver, int *status, float *iodelay) if (playback_errors > 0) { delay = (playback_errors * 1000.0) / driver->sample_rate; - jack_error("sun_driver: playback xrun of %d frames (%f msec)", + printf("sun_driver: playback xrun of %d frames (%f msec)\n", playback_errors, delay); delay = (driver->playback_drops * 1000.0) / driver->sample_rate; - jack_error("sun_driver: total playback xruns: %d frames " - "(%f msec)", driver->playback_drops, delay); + printf("sun_driver: total playback xruns: %d frames " + "(%f msec)\n", driver->playback_drops, delay); } + /* if the capture buffer overruns in duplex mode, the playback + * buffer has underrun as well, and has no chance of catching + * back up to realtime because the capture buffer no longer + * represents realtime. write enough silence to resync the + * buffers. + */ + if ((driver->outfd == driver->infd) && (capture_errors > 0)) + sun_driver_write_silence(driver, capture_errors); + driver->last_wait_ust = poll_ret; + *status = 0; + return driver->period_size; } @@ -352,13 +352,30 @@ static inline int sun_driver_run_cycle (sun_driver_t *driver) { jack_nframes_t nframes; + jack_time_t now; int wait_status; float iodelay; nframes = sun_driver_wait (driver, &wait_status, &iodelay); if (wait_status < 0) - return -1; + { + switch (wait_status) + { + case -3: + /* poll() error */ + return -1; + case -5: + /* poll() timeout */ + now = jack_get_microseconds(); + iodelay = now - driver->poll_next; + driver->poll_next = now + driver->period_usecs; + driver->engine->delay(driver->engine, iodelay); + return 0; + default: + return -1; + } + } return driver->engine->run_cycle(driver->engine, nframes, iodelay); } @@ -568,6 +585,45 @@ sun_driver_start (sun_driver_t *driver) { audio_info_t audio_if; + if (driver->infd >= 0) + { + if (ioctl(driver->infd, AUDIO_FLUSH, NULL) < 0) + { + jack_error("sun_driver: capture flush failed: %s: " + "%s@%i", strerror(errno), __FILE__, __LINE__); + return -1; + } + AUDIO_INITINFO(&audio_if); + audio_if.record.pause = 1; + if (driver->outfd == driver->infd) + audio_if.play.pause = 1; + if (ioctl(driver->infd, AUDIO_SETINFO, &audio_if) < 0) + { + jack_error("sun_driver: pause capture failed: %s: " + "%s@%i", strerror(errno), __FILE__, __LINE__); + return -1; + } + } + if ((driver->outfd >= 0) && (driver->outfd != driver->infd)) + { + if (ioctl(driver->outfd, AUDIO_FLUSH, NULL) < 0) + { + jack_error("sun_driver: playback flush failed: %s: " + "%s@%i", strerror(errno), __FILE__, __LINE__); + return -1; + } + AUDIO_INITINFO(&audio_if); + audio_if.play.pause = 1; + if (ioctl(driver->outfd, AUDIO_SETINFO, &audio_if) < 0) + { + jack_error("sun_driver: pause playback failed: %s: " + "%s@%i", strerror(errno), __FILE__, __LINE__); + return -1; + } + } + + driver->playback_drops = driver->capture_drops = 0; + if (driver->outfd >= 0) { /* "prime" the playback buffer */ @@ -579,15 +635,16 @@ sun_driver_start (sun_driver_t *driver) { AUDIO_INITINFO(&audio_if); audio_if.record.pause = 0; + if (driver->outfd == driver->infd) + audio_if.play.pause = 0; if (ioctl(driver->infd, AUDIO_SETINFO, &audio_if) < 0) { - jack_error("sun_driver: trigger capture failed: %s: " + jack_error("sun_driver: start capture failed: %s: " "%s@%i", strerror(errno), __FILE__, __LINE__); return -1; } } - - if (driver->outfd >= 0) + if ((driver->outfd >= 0) && (driver->outfd != driver->infd)) { AUDIO_INITINFO(&audio_if); audio_if.play.pause = 0; @@ -1194,7 +1251,7 @@ sun_driver_new (char *indev, char *outdev, jack_client_t *client, driver->outdev = strdup(SUN_DRIVER_DEF_DEV); driver->infd = -1; driver->outfd = -1; - driver->format = AUDIO_ENCODING_SLINEAR_LE; + driver->format = AUDIO_ENCODING_SLINEAR; driver->indevbuf = driver->outdevbuf = NULL;