Behold: The JACK audio connection kit version 0.109.10 (SVN).
authorbjs <bjs>
Sun, 16 Mar 2008 09:26:46 +0000 (09:26 +0000)
committerbjs <bjs>
Sun, 16 Mar 2008 09:26:46 +0000 (09:26 +0000)
This update was long overdue from version 0.100.0.  Especially of note:
native audio(4) support (OSS driver initially converted by
jakemsr@openbsd.org), with certain changes/fixups by me (both in the
driver code and elsewhere ... it is very much still a work in progress,
but it is a work that does work, heh).

Also, some patches to do the "right thing" throughout, i.e. press the
"we are not linux" button.  More fixes/enhancements coming soon.

One outstanding issue I know of:  an mmap failure when trying to run
with realtime scheduling that I haven't been able to look into enough yet.

A good player which supports this is audio/moc ... I hope to add
a gstreamer plugin and much more shortly.

I am in the planning stages of a rewrite of the driver using kqueue, also.

19 files changed:
audio/jack-devel/DESCR [new file with mode: 0644]
audio/jack-devel/MESSAGE [new file with mode: 0644]
audio/jack-devel/Makefile [new file with mode: 0644]
audio/jack-devel/PLIST [new file with mode: 0644]
audio/jack-devel/buildlink3.mk [new file with mode: 0644]
audio/jack-devel/distinfo [new file with mode: 0644]
audio/jack-devel/patches/patch-ab [new file with mode: 0644]
audio/jack-devel/patches/patch-ac [new file with mode: 0644]
audio/jack-devel/patches/patch-ad [new file with mode: 0644]
audio/jack-devel/patches/patch-ae [new file with mode: 0644]
audio/jack-devel/patches/patch-af [new file with mode: 0644]
audio/jack-devel/patches/patch-ag [new file with mode: 0644]
audio/jack-devel/patches/patch-ah [new file with mode: 0644]
audio/jack-devel/patches/patch-ai [new file with mode: 0644]
audio/jack-devel/patches/patch-aj [new file with mode: 0644]
audio/jack-devel/patches/patch-ak [new file with mode: 0644]
audio/jack-devel/patches/patch-al [new file with mode: 0644]
audio/jack-devel/patches/patch-am [new file with mode: 0644]
audio/jack-devel/patches/patch-an [new file with mode: 0644]

diff --git a/audio/jack-devel/DESCR b/audio/jack-devel/DESCR
new file mode 100644 (file)
index 0000000..f3b1144
--- /dev/null
@@ -0,0 +1,6 @@
+JACK is a low-latency audio server, written for POSIX conformant
+operating systems such as GNU/Linux and Apple's OS X. It can connect a
+number of different applications to an audio device, as well as allowing
+them to share audio between themselves. Its clients can run in their own
+processes (ie. as normal applications), or can they can run within the
+JACK server (ie. as a "plugin").
diff --git a/audio/jack-devel/MESSAGE b/audio/jack-devel/MESSAGE
new file mode 100644 (file)
index 0000000..fd82164
--- /dev/null
@@ -0,0 +1,18 @@
+===========================================================================
+$NetBSD$
+
+NOTE:  Unfortunately, JACK wants to use a linux /proc filesystem to
+perform shared memory housekeeping tasks.  Therefore, if your platform
+supports a "Linux-compliant" proc filesystem, we recommend mounting one
+prior to using jack.  On NetBSD, this can be accomplished with the
+following command:
+
+               mount_procfs -orw,linux /proc <mount point>
+
+Conventionally, the mount point is /proc.  If you wish to use a different
+pathname for this filesystem, you may define the JACKD_PROCFS_PATH
+variable in your build environment or mk.conf as shown below.
+
+               JACKD_PROCFS_PATH= /emul/linux/proc
+
+===========================================================================
diff --git a/audio/jack-devel/Makefile b/audio/jack-devel/Makefile
new file mode 100644 (file)
index 0000000..5236f34
--- /dev/null
@@ -0,0 +1,71 @@
+# $NetBSD$
+#
+
+DISTNAME=      jack-0.109.10
+PKGNAME=       ${DISTNAME:C/jack/&-devel/}
+CATEGORIES=    audio
+MASTER_SITES=  ${MASTER_SITE_LOCAL}
+EXTRACT_SUFX=  .tar.bz2
+
+MAINTAINER=    bjs@NetBSD.org
+HOMEPAGE=      http://www.jackaudio.org/
+COMMENT=       JACK audio connection kit
+
+PKG_DESTDIR_SUPPORT=   user-destdir
+
+GNU_CONFIGURE=         yes
+USE_TOOLS+=            pkg-config
+USE_LIBTOOL=           yes
+
+CONFIGURE_ARGS+=       --disable-alsa
+CONFIGURE_ARGS+=       --disable-freebob
+CONFIGURE_ARGS+=       --disable-coreaudio
+CONFIGURE_ARGS+=       --disable-firewire
+CONFIGURE_ARGS+=       --disable-optimize
+CONFIGURE_ARGS+=       --disable-sse
+
+CONFIGURE_ARGS+=       --enable-resize
+CONFIGURE_ARGS+=       --enable-timestamps
+
+CONFIGURE_ARGS+=       --with-default-tmpdir=/tmp/
+
+.include "../../mk/bsd.prefs.mk"
+
+.if exists(/usr/include/sys/audioio.h)
+CONFIGURE_ARGS+=       --enable-sun
+PLIST_SUBST+=          SUN=""
+.else
+CONFIGURE_ARGS+=       --disable-sun
+PLIST_SUBST+=          SUN="@comment "
+.endif
+
+.include "../../mk/oss.buildlink3.mk"
+
+.if ${OSS_TYPE} != "none"
+CONFIGURE_ARGS+=       --enable-oss
+PLIST_SUBST+=          OSS=""
+MAKE_ENV+=             LIBOSSAUDIO=${LIBOSSAUDIO:Q}
+.else
+CONFIGURE_ARGS+=       --disable-oss
+PLIST_SUBST+=          OSS="@comment "
+.endif
+
+
+PKGCONFIG_OVERRIDE+=   jack.pc.in
+PTHREAD_OPTS+=         require native
+
+CFLAGS.NetBSD+=                -DJACKD_WATCHDOG_TIMEOUT=900
+
+JACKD_PROCFS_PATH?=    /proc
+
+SUBST_CLASSES+=        jacksrc
+SUBST_FILES.jacksrc=   libjack/unlock.c
+SUBST_MESSAGE.jacksrc= Peforming substitutions in JACK sources.
+SUBST_STAGE.jacksrc=   pre-build
+SUBST_VARS.jacksrc=    PREFIX JACKD_PROCFS_PATH
+
+.include "../../audio/libsamplerate/buildlink3.mk"
+.include "../../devel/readline/buildlink3.mk"
+.include "../../mk/dlopen.buildlink3.mk"
+.include "../../mk/pthread.buildlink3.mk"
+.include "../../mk/bsd.pkg.mk"
diff --git a/audio/jack-devel/PLIST b/audio/jack-devel/PLIST
new file mode 100644 (file)
index 0000000..509ef5d
--- /dev/null
@@ -0,0 +1,43 @@
+@comment $NetBSD$
+bin/jack_alias
+bin/jack_bufsize
+bin/jack_connect
+bin/jack_disconnect
+bin/jack_evmon
+bin/jack_freewheel
+bin/jack_impulse_grabber
+bin/jack_load
+bin/jack_lsp
+bin/jack_metro
+bin/jack_midiseq
+bin/jack_midisine
+bin/jack_monitor_client
+bin/jack_showtime
+bin/jack_simple_client
+bin/jack_transport
+bin/jack_unload
+bin/jackd
+bin/jackrec
+include/jack/intclient.h
+include/jack/jack.h
+include/jack/midiport.h
+include/jack/ringbuffer.h
+include/jack/statistics.h
+include/jack/thread.h
+include/jack/timestamps.h
+include/jack/transport.h
+include/jack/types.h
+lib/jack/inprocess.la
+lib/jack/intime.la
+lib/jack/jack_dummy.la
+lib/jack/jack_net.la
+lib/jack/jack_oss.la
+lib/jack/jack_sun.la
+lib/jack/netsource.la
+lib/libjack.la
+lib/libjackserver.la
+lib/pkgconfig/jack.pc
+man/man1/jackd.1
+man/man1/jackstart.1
+@dirrm lib/jack
+@dirrm include/jack
diff --git a/audio/jack-devel/buildlink3.mk b/audio/jack-devel/buildlink3.mk
new file mode 100644 (file)
index 0000000..a7aee30
--- /dev/null
@@ -0,0 +1,19 @@
+# $NetBSD$
+
+BUILDLINK_DEPTH:=              ${BUILDLINK_DEPTH}+
+JACK_DEVEL_BUILDLINK3_MK:=     ${JACK_DEVEL_BUILDLINK3_MK}+
+
+.if ${BUILDLINK_DEPTH} == "+"
+BUILDLINK_DEPENDS+=    jack-devel
+.endif
+
+BUILDLINK_PACKAGES:=   ${BUILDLINK_PACKAGES:Njack-devel}
+BUILDLINK_PACKAGES+=   jack-devel
+BUILDLINK_ORDER:=      ${BUILDLINK_ORDER} ${BUILDLINK_DEPTH}jack-devel
+
+.if ${JACK_DEVEL_BUILDLINK3_MK} == "+"
+BUILDLINK_API_DEPENDS.jack-devel+=     jack-devel>=0.109.10
+BUILDLINK_PKGSRCDIR.jack-devel?=       ../../audio/jack-devel
+.endif # JACK_DEVEL_BUILDLINK3_MK
+
+BUILDLINK_DEPTH:=              ${BUILDLINK_DEPTH:S/+$//}
diff --git a/audio/jack-devel/distinfo b/audio/jack-devel/distinfo
new file mode 100644 (file)
index 0000000..39ba764
--- /dev/null
@@ -0,0 +1,18 @@
+$NetBSD$
+
+SHA1 (jack-0.109.10.tar.bz2) = a82376dcb3610967eac82789dc543b64b9702e39
+RMD160 (jack-0.109.10.tar.bz2) = 20efa1e19cbe74718c07b262de9e8af5f2f72e58
+Size (jack-0.109.10.tar.bz2) = 577713 bytes
+SHA1 (patch-ab) = e7d7f7266afc5841ebf83ceb98fb7e4f0b821f05
+SHA1 (patch-ac) = 7052322d44700b0bf81642a5e68ae53a3da62df1
+SHA1 (patch-ad) = 9632ad3a03015688f02bc4b715d74e21ae293c8f
+SHA1 (patch-ae) = a18c44b803e340d2b1317a539ffb2123490badc3
+SHA1 (patch-af) = 6e7c16137434c601f09da982528f3f8c81bdd354
+SHA1 (patch-ag) = e7a5e878cdd47355f8d6213163b8560939708f32
+SHA1 (patch-ah) = b3445eea50978ff83b16fbe2cfe2f8d111fd67aa
+SHA1 (patch-ai) = aacea684a8d31cfb2e22087d425e5fd457ad215d
+SHA1 (patch-aj) = 46805c358c60a92d6d680a9ea847d32c15af1708
+SHA1 (patch-ak) = 7d1eaa5cecc5f1c3b725ff768089dfd4a133ea45
+SHA1 (patch-al) = fc7311171027b71cbd7572431f45d69ed81dcd92
+SHA1 (patch-am) = c4d1d5562dace10971ef7fba37ddfcf07ad2fdb5
+SHA1 (patch-an) = 90939c5e0a8a53bf701d93ba88a2900439866142
diff --git a/audio/jack-devel/patches/patch-ab b/audio/jack-devel/patches/patch-ab
new file mode 100644 (file)
index 0000000..9608aae
--- /dev/null
@@ -0,0 +1,49 @@
+$NetBSD$
+
+--- configure.orig     2008-03-15 02:20:31.000000000 -0400
++++ configure
+@@ -19793,7 +19793,7 @@ case "${host_os}" in
+     # barrier code, this may be fixed in 5.3, stay tuned.
+     USE_BARRIER="no"
+     ;;
+-  openbsd*)
++  openbsd*|netbsd*)
+     # pthread_barrier* not implemented
+     USE_BARRIER="no"
+     # need small realtime stack
+@@ -23039,8 +23039,7 @@ fi
+ JACK_CORE_CFLAGS="-I\$(top_srcdir)/config -I\$(top_srcdir) \
+ -I\$(top_srcdir) -D_REENTRANT -D_POSIX_PTHREAD_SEMANTICS -Wall -g"
+-JACK_OPT_CFLAGS="$JACK_CORE_CFLAGS -march=pentium2 -mcpu=pentium4 -O3 \
+--ffast-math -funroll-loops -fprefetch-loop-arrays"
++JACK_OPT_CFLAGS="$JACK_CORE_CFLAGS"
+ JACK_CFLAGS="$JACK_CORE_CFLAGS $CFLAGS"
+@@ -23122,7 +23121,7 @@ rm -f core conftest.err conftest.$ac_obj
+     fi
+-    JACK_OPT_CFLAGS="-D_REENTRANT -O2 -mcpu=7400 $ALTIVEC_OPT_FLAGS_FLAGS -mhard-float -mpowerpc-gfxopt"
++    JACK_OPT_CFLAGS="-D_REENTRANT -O2 $ALTIVEC_OPT_FLAGS_FLAGS -mhard-float -mpowerpc-gfxopt"
+ elif echo $target_cpu | egrep '(i.86|x86_64)' >/dev/null; then
+@@ -23294,14 +23293,14 @@ cat >>confdefs.h <<\_ACEOF
+ #define x86 1
+ _ACEOF
+-    COMMON_X86_OPT_FLAGS="-DREENTRANT -O3 -fomit-frame-pointer -ffast-math -funroll-loops"
++    COMMON_X86_OPT_FLAGS="-DREENTRANT"
+     if test "$target_cpu" = "i586"; then
+       JACK_OPT_CFLAGS="-march=i586 "
+     elif test "$target_cpu" = "i686"; then
+       JACK_OPT_CFLAGS="-march=i686"
+     elif test "$target_cpu" = "x86_64"; then
+-      JACK_OPT_CFLAGS="-march=k8"
++      JACK_OPT_CFLAGS=""
+     else
+       :
+     fi
diff --git a/audio/jack-devel/patches/patch-ac b/audio/jack-devel/patches/patch-ac
new file mode 100644 (file)
index 0000000..2ec49a3
--- /dev/null
@@ -0,0 +1,14 @@
+$NetBSD$
+
+--- drivers/netjack/net_source.c.orig  2008-03-11 09:37:32.000000000 -0400
++++ drivers/netjack/net_source.c
+@@ -11,7 +11,9 @@
+ #include <netinet/in.h>
+ #include <netdb.h>
++#ifdef HAVE_ALLOCA_H
+ #include <alloca.h>
++#endif
+ #include <jack/jack.h>
diff --git a/audio/jack-devel/patches/patch-ad b/audio/jack-devel/patches/patch-ad
new file mode 100644 (file)
index 0000000..c9fcc72
--- /dev/null
@@ -0,0 +1,16 @@
+$NetBSD$
+
+--- drivers/oss/oss_driver.h.orig      2007-06-12 16:46:40.000000000 -0400
++++ drivers/oss/oss_driver.h
+@@ -34,7 +34,11 @@
+ #include <jack/jack.h>
++#if defined(DEVOSSAUDIO)
++#define OSS_DRIVER_DEF_DEV    DEVOSSAUDIO
++#else
+ #define OSS_DRIVER_DEF_DEV    "/dev/dsp"
++#endif
+ #define OSS_DRIVER_DEF_FS     48000
+ #define OSS_DRIVER_DEF_BLKSIZE        1024
+ #define OSS_DRIVER_DEF_NPERIODS       2
diff --git a/audio/jack-devel/patches/patch-ae b/audio/jack-devel/patches/patch-ae
new file mode 100644 (file)
index 0000000..d5bf3f7
--- /dev/null
@@ -0,0 +1,15 @@
+$NetBSD$
+
+--- drivers/Makefile.in.orig   2008-03-15 02:20:34.000000000 -0400
++++ drivers/Makefile.in
+@@ -219,7 +219,9 @@ MAINTAINERCLEANFILES = Makefile.in
+ @HAVE_FREEBOB_TRUE@FREEBOB_DIR = freebob
+ @HAVE_FIREWIRE_FALSE@FIREWIRE_DIR = 
+ @HAVE_FIREWIRE_TRUE@FIREWIRE_DIR = firewire
+-SUBDIRS = $(ALSA_MIDI_DIR) $(ALSA_DIR) dummy $(OSS_DIR) $(SUN_DIR) $(PA_DIR) $(CA_DIR) $(FREEBOB_DIR) $(FIREWIRE_DIR)
++@HAVE_SAMPLERATE_TRUE@NETJACK_DIR = netjack
++@HAVE_SAMPLERATE_FALSE@NETJACK_DIR = 
++SUBDIRS = $(ALSA_MIDI_DIR) $(ALSA_DIR) dummy $(NETJACK_DIR) $(OSS_DIR) $(SUN_DIR) $(PA_DIR) $(CA_DIR) $(FREEBOB_DIR) $(FIREWIRE_DIR)
+ DIST_SUBDIRS = alsa alsa-midi dummy oss sun portaudio coreaudio freebob firewire
+ all: all-recursive
diff --git a/audio/jack-devel/patches/patch-af b/audio/jack-devel/patches/patch-af
new file mode 100644 (file)
index 0000000..a81a620
--- /dev/null
@@ -0,0 +1,15 @@
+$NetBSD$
+
+--- example-clients/transport.c.orig   2006-05-15 18:21:26.000000000 -0400
++++ example-clients/transport.c
+@@ -29,6 +29,10 @@
+ #include <jack/jack.h>
+ #include <jack/transport.h>
++#ifndef whitespace
++#define whitespace(c) (((c) == ' ') || ((c) == '\t'))
++#endif
++
+ char *package;                                /* program name */
+ int done = 0;
+ jack_client_t *client;
diff --git a/audio/jack-devel/patches/patch-ag b/audio/jack-devel/patches/patch-ag
new file mode 100644 (file)
index 0000000..2f7e74e
--- /dev/null
@@ -0,0 +1,12 @@
+$NetBSD$
+
+--- jack.pc.in.orig    2007-02-23 18:49:09.000000000 -0500
++++ jack.pc.in
+@@ -6,5 +6,5 @@ includedir=@includedir@
+ Name: jack
+ Description: the Jack Audio Connection Kit: a low-latency synchronous callback-based media server
+ Version: @JACK_VERSION@
+-Libs: -L${libdir} -ljack -lpthread @OS_LDFLAGS@
+-Cflags: -I${includedir}
++Libs: -L${libdir} -ljack @OS_LDFLAGS@
++Cflags: -I${includedir} @OS_CPPFLAGS@
diff --git a/audio/jack-devel/patches/patch-ah b/audio/jack-devel/patches/patch-ah
new file mode 100644 (file)
index 0000000..8fa59bc
--- /dev/null
@@ -0,0 +1,15 @@
+$NetBSD$
+
+--- jack/engine.h.orig 2008-01-10 16:34:30.000000000 -0500
++++ jack/engine.h
+@@ -51,8 +51,9 @@ typedef struct _jack_port_buffer_list {
+     jack_port_buffer_info_t *info;    /* jack_buffer_info_t array */
+ } jack_port_buffer_list_t;
++#ifndef JACKD_WATCHDOG_TIMEOUT
+ #define JACKD_WATCHDOG_TIMEOUT 10000
+-
++#endif
+ /* The main engine structure in local memory. */
+ struct _jack_engine {
+     jack_control_t        *control;
diff --git a/audio/jack-devel/patches/patch-ai b/audio/jack-devel/patches/patch-ai
new file mode 100644 (file)
index 0000000..e54f623
--- /dev/null
@@ -0,0 +1,50 @@
+$NetBSD$
+
+--- jackd/engine.c.orig        2008-03-14 03:08:35.000000000 -0400
++++ jackd/engine.c
+@@ -633,7 +633,8 @@ jack_process_external(jack_engine_t *eng
+       int status = 0;
+       char c = 0;
+       struct pollfd pfd[1];
+-      int poll_timeout;
++      struct timespec poll_timeout = { 0, 0 };
++
+       jack_client_internal_t *client;
+       jack_client_control_t *ctl;
+       jack_time_t now, then;
+@@ -666,11 +667,11 @@ jack_process_external(jack_engine_t *eng
+       then = jack_get_microseconds ();
+       if (engine->freewheeling) {
+-              poll_timeout = 10000; /* 10 seconds */
++              poll_timeout.tv_sec = 10;
+       } else {
+-              poll_timeout = (engine->client_timeout_msecs > 0 ?
+-                              engine->client_timeout_msecs :
+-                              1 + engine->driver->period_usecs/1000);
++              poll_timeout.tv_nsec = (engine->client_timeout_msecs > 0 ?
++                              engine->client_timeout_msecs * 1e6 :
++                              1000 + engine->driver->period_usecs);
+       }
+       pfd[0].fd = client->subgraph_wait_fd;
+@@ -679,8 +680,8 @@ jack_process_external(jack_engine_t *eng
+       DEBUG ("waiting on fd==%d for process() subgraph to finish",
+              client->subgraph_wait_fd);
+-      if (poll (pfd, 1, poll_timeout) < 0) {
+-              jack_error ("poll on subgraph processing failed (%s)",
++      if (pollts (pfd, 1, &poll_timeout) < 0) {
++              jack_error ("pollts on subgraph processing failed (%s)",
+                           strerror (errno));
+               status = -1; 
+       }
+@@ -1468,7 +1469,7 @@ jack_server_thread (void *arg)
+                                   (engine, pfd[i].fd)) {
+                                       jack_error ("could not handle external"
+                                                   " client request");
+-#ifdef JACK_USE_MACH_THREADS
++#if defined(JACK_USE_MACH_THREADS) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
+                                     /* poll is implemented using
+                                      select (see the macosx/fakepoll
+                                      code). When the socket is closed
diff --git a/audio/jack-devel/patches/patch-aj b/audio/jack-devel/patches/patch-aj
new file mode 100644 (file)
index 0000000..ce15b66
--- /dev/null
@@ -0,0 +1,21 @@
+$NetBSD$
+
+--- libjack/client.c.orig      2008-03-12 10:36:07.000000000 -0400
++++ libjack/client.c
+@@ -1896,14 +1896,14 @@ jack_activate (jack_client_t *client)
+        * pages are actually mapped (more important for mlockall(2)
+        * usage in jack_start_thread())
+        */
+-         
++#ifdef __gnu_linux__
+       char buf[JACK_THREAD_STACK_TOUCH];
+       int i;
+       for (i = 0; i < JACK_THREAD_STACK_TOUCH; i++) {
+               buf[i] = (char) (i & 0xff);
+       }
+-
++#endif
+       if (client->control->type == ClientInternal ||
+           client->control->type == ClientDriver) {
+               goto startit;
diff --git a/audio/jack-devel/patches/patch-ak b/audio/jack-devel/patches/patch-ak
new file mode 100644 (file)
index 0000000..84c227e
--- /dev/null
@@ -0,0 +1,21 @@
+$NetBSD$
+
+--- libjack/unlock.c.orig      2008-03-04 07:20:10.000000000 -0500
++++ libjack/unlock.c
+@@ -48,6 +48,7 @@ static char* library_roots[] = {
+       "/usr/X11R6/lib",
+       "/opt/lib",       /* solaris-y */   
+       "/opt/local/lib", /* common on OS X */
++      "@PREFIX@",       /* pkgsrc prefix */
+       NULL
+ };
+@@ -63,7 +64,7 @@ cleanup_mlock ()
+       int whoknows;
+       int looks_like_library;
+-      snprintf (path, sizeof(path), "/proc/%d/maps", getpid());
++      snprintf (path, sizeof(path), "@JACKD_PROCFS_PATH@/%d/maps", getpid());
+       if ((map = fopen (path, "r")) == NULL) {
+               jack_error ("can't open map file");
diff --git a/audio/jack-devel/patches/patch-al b/audio/jack-devel/patches/patch-al
new file mode 100644 (file)
index 0000000..27cc1ad
--- /dev/null
@@ -0,0 +1,48 @@
+$NetBSD$
+
+--- drivers/sun/sun_driver.h.orig      2008-03-13 05:05:16.000000000 -0400
++++ drivers/sun/sun_driver.h
+@@ -66,7 +66,7 @@ typedef struct _sun_driver
+       int outfd;
+       int format;
+       int ignorehwbuf;
+-      int trigger;
++      int verbose;
+       size_t indevbufsize;
+       size_t outdevbufsize;
+@@ -75,8 +75,8 @@ typedef struct _sun_driver
+       void *outdevbuf;
+       float iodelay;
+-      jack_time_t last_periodtime;
+-      jack_time_t next_periodtime;
++      jack_time_t poll_last;
++      jack_time_t poll_next;
+       jack_nframes_t sys_in_latency;
+       jack_nframes_t sys_out_latency;
+@@ -86,15 +86,15 @@ typedef struct _sun_driver
+       jack_engine_t *engine;
+       jack_client_t *client;
++      int playback_ready;
++      int capture_ready;
++
++      int playback_drops;
++      int capture_drops;
++
+       volatile int run;
+-      volatile int threads;
+-      pthread_t thread_in;
+-      pthread_t thread_out;
+-      pthread_mutex_t mutex_in;
+-      pthread_mutex_t mutex_out;
+-#     ifdef USE_BARRIER
+-      pthread_barrier_t barrier;
+-#     endif
++      pthread_t io_thread;
++      pthread_mutex_t io_mutex;
+       sem_t sem_start;
+ } sun_driver_t;
diff --git a/audio/jack-devel/patches/patch-am b/audio/jack-devel/patches/patch-am
new file mode 100644 (file)
index 0000000..5c6d78a
--- /dev/null
@@ -0,0 +1,13 @@
+$NetBSD$
+
+--- drivers/oss/Makefile.in.orig       2008-03-15 02:20:35.000000000 -0400
++++ drivers/oss/Makefile.in
+@@ -54,7 +54,7 @@ am__strip_dir = `echo $$p | sed -e 's|^.
+ am__installdirs = "$(DESTDIR)$(plugindir)"
+ pluginLTLIBRARIES_INSTALL = $(INSTALL)
+ LTLIBRARIES = $(plugin_LTLIBRARIES)
+-jack_oss_la_LIBADD =
++jack_oss_la_LIBADD = $(LIBOSSAUDIO)
+ am_jack_oss_la_OBJECTS = oss_driver.lo
+ jack_oss_la_OBJECTS = $(am_jack_oss_la_OBJECTS)
+ jack_oss_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
diff --git a/audio/jack-devel/patches/patch-an b/audio/jack-devel/patches/patch-an
new file mode 100644 (file)
index 0000000..9b1dce9
--- /dev/null
@@ -0,0 +1,871 @@
+$NetBSD$
+
+--- drivers/sun/sun_driver.c.orig      2008-03-13 05:05:16.000000000 -0400
++++ drivers/sun/sun_driver.c
+@@ -28,16 +28,6 @@
+ #include <config.h>
+-#ifdef USE_BARRIER
+-/*
+- * POSIX conformance level should be globally defined somewhere, possibly
+- * in config.h? Otherwise it's pre 1993/09 level, which leaves out significant
+- * parts of threading and realtime stuff. Note: most of the parts are still
+- * defined as optional by the standard, so OS conformance to this level
+- * doesn't necessarily mean everything exists.
+- */
+-#define _XOPEN_SOURCE 600
+-#endif
+ #ifndef _REENTRANT
+ #define _REENTRANT
+ #endif
+@@ -50,6 +40,7 @@
+ #include <sys/ioctl.h>
+ #include <sys/audioio.h>
++#include <poll.h>
+ #include <unistd.h>
+ #include <pthread.h>
+ #include <stdlib.h>
+@@ -72,7 +63,7 @@
+ #include "sun_driver.h"
+-#define SUN_DRIVER_N_PARAMS   11
++#define SUN_DRIVER_N_PARAMS   12
+ const static jack_driver_param_desc_t sun_params[SUN_DRIVER_N_PARAMS] = {
+       { "rate",
+         'r',
+@@ -150,6 +141,13 @@ const static jack_driver_param_desc_t su
+         { .ui = 0 },
+         "system output latency",
+         "system output latency"
++      },
++      { "verbose",
++        'v',
++        JackDriverParamBool,
++        { },
++        "enable verbose debugging output",
++        "enable verbose debugging output"
+       }
+ };
+@@ -167,37 +165,176 @@ static void set_period_size (sun_driver_
+               ((double) driver->period_size /
+               (double) driver->sample_rate) * 1e6;
+       driver->last_wait_ust = 0;
+-      driver->last_periodtime = jack_get_microseconds();
+-      driver->next_periodtime = 0;
++      driver->poll_last = jack_get_microseconds();
++      driver->poll_next = 0;
+       driver->iodelay = 0.0F;
+ }
+-static inline void update_times (sun_driver_t *driver)
++static jack_nframes_t
++sun_driver_wait (sun_driver_t *driver, int *status, float *iodelay)
+ {
+-      driver->last_periodtime = jack_get_microseconds();
+-      if (driver->next_periodtime > 0)
++      struct pollfd pfd[2];
++      jack_time_t poll_enter;
++      jack_time_t poll_ret = 0;
++      jack_nframes_t capture_avail = 0;
++      jack_nframes_t playback_avail = 0;
++      jack_nframes_t avail;
++      int need_capture = 0;
++      int need_playback = 0;
++      int capture_errors = 0;
++      int playback_errors = 0;
++      nfds_t nfds;
++      struct timespec ts = { 0, 0 };
++
++      *status = 0;
++      *iodelay = 0;
++
++      if (driver->infd >= 0)
++      {
++              driver->capture_ready = 0;
++              need_capture = 1;
++      }
++
++      if (driver->outfd >= 0)
+       {
+-              driver->iodelay = (float)
+-                      ((long double) driver->last_periodtime - 
+-                      (long double) driver->next_periodtime);
+-      }
+-      else driver->iodelay = 0.0F;
+-      driver->next_periodtime = 
+-              driver->last_periodtime +
+-              driver->period_usecs;
++              driver->playback_ready = 0;
++              need_playback = 1;
++      }
++
++      while (need_capture || need_playback)
++      {
++              bzero(&pfd[0], sizeof(struct pollfd));
++              bzero(&pfd[1], sizeof(struct pollfd));
++
++              if (driver->infd >= 0 )
++              {
++                      pfd[0].fd = driver->infd;
++                      pfd[0].events = POLLIN;
++              }
++
++              if (driver->outfd >= 0)
++              {
++                      pfd[1].fd = driver->outfd;
++                      pfd[1].events = POLLOUT;
++              }
++
++              poll_enter = jack_get_microseconds();
++
++              ts.tv_nsec = driver->period_usecs * 1000;
++
++              nfds = pollts(pfd, 2, &ts, NULL);
++              if ( nfds == -1 ||
++                  ((pfd[0].revents | pfd[1].revents) &
++                  (POLLERR | POLLHUP | POLLNVAL)) )
++              {
++                      jack_error("sun_driver: poll() error: %s, %s@%i",  
++                              strerror(errno), __FILE__, __LINE__);
++                      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__);
++                      return 0;
++              }
++
++              if (need_capture)
++              {
++                      if (ioctl(driver->infd, AUDIO_RERROR,
++                              &capture_errors) < 0)
++                      {
++                              jack_error("sun_driver: AUDIO_RERROR failed: "
++                                      "%s, %s@%i", strerror(errno),
++                                      __FILE__, __LINE__);
++                              return 0;
++                      }
++                      capture_errors /= driver->period_size;
++                      capture_errors -= driver->capture_drops;
++                      if ((capture_errors > 0) && driver->verbose)
++                      {
++                              printf("sun_driver: missed %d capture"
++                                      " cycles\n", capture_errors);
++                      }
++                      driver->capture_drops += capture_errors;
++                      if (pfd[0].revents & POLLIN)
++                      {
++                              capture_avail = driver->period_size;
++                              need_capture--;
++                      }
++              }
++
++              if (need_playback)
++              {
++                      if (ioctl(driver->outfd, AUDIO_PERROR,
++                              &playback_errors) < 0)
++                      {
++                              jack_error("sun_driver: AUDIO_PERROR failed: "
++                                      "%s: %s@%i", strerror(errno),
++                                      __FILE__, __LINE__);
++                              return 0;
++                      }
++                      playback_errors /= driver->period_size;
++                      playback_errors -= driver->playback_drops;
++                      if ((playback_errors > 0) && driver->verbose)
++                      {
++                              printf("sun_driver: missed %d playback"
++                                      " cycles\n", playback_errors);
++                      }
++                      driver->playback_drops += playback_errors;
++                      if (pfd[1].revents & POLLOUT)
++                      {
++                              playback_avail = driver->period_size;
++                              need_playback--;
++                      }
++              }
++      }
++
++      driver->last_wait_ust = poll_ret;
++
++      avail = capture_avail < playback_avail ?
++              (capture_avail > 0 ? capture_avail : playback_avail) :
++              (playback_avail > 0 ? playback_avail : capture_avail);
++
++      if (capture_avail > 0)
++              *status |= 1;
++      if (playback_avail > 0)
++              *status |= 2;
++
++      return avail - (avail % driver->period_size);
+ }
+ static inline void driver_cycle (sun_driver_t *driver)
+ {
+-      update_times(driver);
+-      driver->engine->transport_cycle_start(driver->engine,
+-              driver->last_periodtime);
+-
+-      driver->last_wait_ust = driver->last_periodtime;
+-      driver->engine->run_cycle(driver->engine, 
+-              driver->period_size, driver->iodelay);
++      jack_nframes_t ready_frames;
++      int ready_status;
++      float iodelay;
++
++      ready_frames = sun_driver_wait (driver, &ready_status, &iodelay);
++
++      if (ready_frames == 0)
++      {
++              driver->engine->delay (driver->engine, iodelay);
++      }
++
++      if (ready_status & 1)
++              driver->capture_ready = 1;
++      if (ready_status & 2)
++              driver->playback_ready = 1;
++
++      driver->engine->run_cycle(driver->engine, ready_frames, iodelay);
+ }
+@@ -337,8 +474,8 @@ static int sun_driver_attach (sun_driver
+                       JACK_DEFAULT_AUDIO_TYPE, port_flags, 0);
+               if (port == NULL)
+               {
+-                      jack_error("sun_driver: cannot register port for %s: %s@%i",
+-                              channel_name, __FILE__, __LINE__);
++                      jack_error("sun_driver: cannot register port for %s: "
++                              "%s@%i", channel_name, __FILE__, __LINE__);
+                       break;
+               }
+               jack_port_set_latency(port,
+@@ -356,8 +493,8 @@ static int sun_driver_attach (sun_driver
+                       JACK_DEFAULT_AUDIO_TYPE, port_flags, 0);
+               if (port == NULL)
+               {
+-                      jack_error("sun_driver: cannot register port for %s: %s@%i",
+-                              channel_name, __FILE__, __LINE__);
++                      jack_error("sun_driver: cannot register port for "
++                              "%s: %s@%i", channel_name, __FILE__, __LINE__);
+                       break;
+               }
+               jack_port_set_latency(port,
+@@ -417,8 +554,6 @@ static int sun_driver_start (sun_driver_
+       const char *indev = driver->indev;
+       const char *outdev = driver->outdev;
+-      driver->trigger = 0;
+-
+       if ((strcmp(indev, outdev) == 0) &&
+           ((driver->capture_channels > 0) && (driver->playback_channels > 0)))
+       {
+@@ -426,15 +561,17 @@ static int sun_driver_start (sun_driver_
+               if (infd < 0)
+               {
+                       jack_error(
+-                              "sun_driver: failed to open duplex device %s: %s@%i, errno=%d",
+-                              indev, __FILE__, __LINE__, errno);
++                              "sun_driver: failed to open duplex device "
++                              "%s: %s@%i, errno=%d", indev, __FILE__,
++                              __LINE__, errno);
+                       return -1;
+               }
+               if (ioctl(infd, AUDIO_SETFD, &s) < 0)
+               {
+                       jack_error(
+-                              "sun_driver: failed to enable full duplex for %s: %s@%i, errno=%d",
+-                              indev, __FILE__, __LINE__, errno);
++                              "sun_driver: failed to enable full duplex for "
++                              "%s: %s@%i, errno=%d", indev, __FILE__,
++                              __LINE__, errno);
+                       return -1;
+               }
+       }
+@@ -446,7 +583,8 @@ static int sun_driver_start (sun_driver_
+                       if (infd < 0)
+                       {
+                               jack_error(
+-                                      "sun_driver: failed to open input device %s: %s@%i, errno=%d",
++                                      "sun_driver: failed to open input "
++                                      "device %s: %s@%i, errno=%d",
+                                       indev, __FILE__, __LINE__, errno);
+                       }
+               }
+@@ -456,7 +594,8 @@ static int sun_driver_start (sun_driver_
+                       if (outfd < 0)
+                       {
+                               jack_error(
+-                                      "sun_driver: failed to open output device %s: %s@%i, errno=%d",
++                                      "sun_driver: failed to open output "
++                                      "device %s: %s@%i, errno=%d",
+                                       outdev, __FILE__, __LINE__, errno);
+                       }
+               }
+@@ -464,7 +603,8 @@ static int sun_driver_start (sun_driver_
+       if (infd == -1 && outfd == -1)
+       {
+               jack_error(
+-                      "sun_driver: no device was opened %s@%i", __FILE__, __LINE__);
++                      "sun_driver: no device was opened %s@%i", __FILE__,
++                      __LINE__);
+       }
+       driver->infd = infd;
+@@ -479,6 +619,7 @@ static int sun_driver_start (sun_driver_
+               audio_if_in.record.precision = driver->bits;
+               audio_if_in.record.channels = driver->capture_channels;
+               audio_if_in.record.sample_rate = driver->sample_rate;
++              audio_if_in.record.pause = 1;
+       }
+       if (outfd >= 0)
+@@ -487,6 +628,8 @@ static int sun_driver_start (sun_driver_
+               audio_if_out.play.precision = driver->bits;
+               audio_if_out.play.channels = driver->playback_channels;
+               audio_if_out.play.sample_rate = driver->sample_rate;
++              audio_if_out.play.pause = 1;
++
+       }
+       if (infd == outfd)
+               audio_if_in.play = audio_if_out.play;
+@@ -514,7 +657,8 @@ static int sun_driver_start (sun_driver_
+       {
+               if (ioctl(infd, AUDIO_SETINFO, &audio_if_in) < 0)
+                       jack_error(
+-                              "sun_driver: failed to set parameters for %s: %s@%i, errno=%d",
++                              "sun_driver: failed to set parameters for "
++                              "%s: %s@%i, errno=%d",
+                               indev, __FILE__, __LINE__, errno);
+       }
+@@ -522,7 +666,8 @@ static int sun_driver_start (sun_driver_
+       {
+               if (ioctl(outfd, AUDIO_SETINFO, &audio_if_out) < 0)
+                       jack_error(
+-                              "sun_driver: failed to set parameters for %s: %s@%i, errno=%d",
++                              "sun_driver: failed to set parameters for "
++                              "%s: %s@%i, errno=%d",
+                               outdev, __FILE__, __LINE__, errno);
+       }
+@@ -534,8 +679,8 @@ static int sun_driver_start (sun_driver_
+       {
+               if (ioctl(infd, AUDIO_GETINFO, &audio_if_in) < 0)
+               {
+-                      jack_error("sun_driver: AUDIO_GETINFO failed: %s@%i, errno=%d",
+-                              __FILE__, __LINE__, errno);
++                      jack_error("sun_driver: AUDIO_GETINFO failed: "
++                              "%s@%i, errno=%d", __FILE__, __LINE__, errno);
+               }
+               if (audio_if_in.record.encoding != driver->format ||
+@@ -543,12 +688,20 @@ static int sun_driver_start (sun_driver_
+                   audio_if_in.record.channels != driver->capture_channels ||
+                   audio_if_in.record.sample_rate != driver->sample_rate)
+               {
+-                      jack_error("sun_driver: setting capture parameters failed: %s@%i",
+-                              __FILE__, __LINE__);
++                      jack_error("sun_driver: setting capture parameters "
++                              "failed: %s@%i", __FILE__, __LINE__);
++                      jack_error("encoding = %d: format = %d",
++                              audio_if_in.record.encoding, driver->format);
++                      jack_error("precision = %d: bits = %d",
++                              audio_if_in.record.precision, driver->bits);
++                      jack_error("channels = %d: channels = %d",
++                              audio_if_in.record.channels, driver->capture_channels);
++                      jack_error("rate = %d: rate = %d",
++                              audio_if_in.record.sample_rate, driver->sample_rate);
+               }
+-              period_size = 8 * audio_if_in.blocksize / driver->capture_channels /
+-                      driver->bits;
++              period_size = 8 * audio_if_in.blocksize /
++                      driver->capture_channels / driver->bits;
+       }
+       if (outfd > 0)
+@@ -561,30 +714,38 @@ static int sun_driver_start (sun_driver_
+               {
+                       if (ioctl(outfd, AUDIO_GETINFO, &audio_if_out) < 0)
+                       {
+-                              jack_error("sun_driver: AUDIO_GETINFO failed: %s@%i, errno=%d",
+-                                      __FILE__, __LINE__, errno);
++                              jack_error("sun_driver: AUDIO_GETINFO failed: "
++                                      "%s@%i, errno=%d", __FILE__, __LINE__,
++                                      errno);
+                       }
+               }
+-              if (audio_if_in.play.encoding != driver->format ||
+-                  audio_if_in.play.precision != driver->bits ||
+-                  audio_if_in.play.channels != driver->playback_channels ||
+-                  audio_if_in.play.sample_rate != driver->sample_rate)
++              if (audio_if_out.play.encoding != driver->format ||
++                  audio_if_out.play.precision != driver->bits ||
++                  audio_if_out.play.channels != driver->playback_channels ||
++                  audio_if_out.play.sample_rate != driver->sample_rate)
+               {
+-                      jack_error("sun_driver: setting playback parameters failed: %s@%i",
++                      jack_error("sun_driver: playback settings failed: %s@%i",
+                               __FILE__, __LINE__);
++                      jack_error("encoding = %d: format = %d",
++                              audio_if_in.play.encoding, driver->format);
++                      jack_error("precision = %d: bits = %d",
++                              audio_if_in.play.precision, driver->bits);
++                      jack_error("channels = %d: channels = %d",
++                              audio_if_in.play.channels, driver->playback_channels);
++                      jack_error("rate = %d: rate = %d",
++                              audio_if_in.play.sample_rate, driver->sample_rate);
+               }
+-              period_size = 8 * audio_if_out.blocksize / driver->playback_channels /
+-                      driver->bits;
++              period_size = 8 * audio_if_out.blocksize /
++                      driver->playback_channels / driver->bits;
+       }
+       if (period_size != driver->period_size && !driver->ignorehwbuf)
+       {
+               printf("sun_driver: period size update: %u\n", period_size);
+-              driver->period_size = period_size;
+-              driver->period_usecs = ((double) driver->period_size / 
+-                               (double) driver->sample_rate) * 1e6;
++
++              set_period_size (driver, period_size);
+               driver->engine->set_buffer_size(driver->engine, 
+                       driver->period_size);
+@@ -631,50 +792,24 @@ static int sun_driver_start (sun_driver_
+       printf("sun_driver: indevbuf %zd B, outdevbuf %zd B\n",
+               driver->indevbufsize, driver->outdevbufsize);
+-      pthread_mutex_init(&driver->mutex_in, NULL);
+-      pthread_mutex_init(&driver->mutex_out, NULL);
+-#     ifdef USE_BARRIER
+-      puts("sun_driver: using barrier mode, (dual thread)");
+-      pthread_barrier_init(&driver->barrier, NULL, 2);
+-#     else
+-      puts("sun_driver: not using barrier mode, (single thread)");
+-#     endif
++      pthread_mutex_init(&driver->io_mutex, NULL);
++
+       sem_init(&driver->sem_start, 0, 0);
+       driver->run = 1;
+-      driver->threads = 0;
+-      if (infd >= 0)
+-      {
+-              if (jack_client_create_thread(NULL, &driver->thread_in, 
+-                      driver->engine->rtpriority, 
+-                      driver->engine->control->real_time, 
+-                      io_thread, driver) < 0)
+-              {
+-                      jack_error("sun_driver: jack_client_create_thread() failed: %s@%i",
+-                              __FILE__, __LINE__);
+-                      return -1;
+-              }
+-              driver->threads |= 1;
+-      }
+-      if ((outfd >= 0) && (infd < 0))
++      if (jack_client_create_thread(NULL, &driver->io_thread, 
++              driver->engine->rtpriority, driver->engine->control->real_time, 
++              io_thread, driver) < 0)
+       {
+-              if (jack_client_create_thread(NULL, &driver->thread_out, 
+-                      driver->engine->rtpriority, 
+-                      driver->engine->control->real_time, 
+-                      io_thread, driver) < 0)
+-              {
+-                      jack_error("sun_driver: jack_client_create_thread() failed: %s@%i",
+-                              __FILE__, __LINE__);
+-                      return -1;
+-              }
+-              driver->threads |= 2;
++              jack_error("sun_driver: jack_client_create_thread() "
++                      "failed: %s@%i", __FILE__, __LINE__);
++              return -1;
+       }
+-      if (driver->threads & 1) sem_post(&driver->sem_start);
+-      if (driver->threads & 2) sem_post(&driver->sem_start);
++      sem_post(&driver->sem_start);
+-      driver->last_periodtime = jack_get_microseconds();
+-      driver->next_periodtime = 0;
++      driver->poll_last = jack_get_microseconds();
++      driver->poll_next = 0;
+       driver->iodelay = 0.0F;
+       return 0;
+@@ -686,38 +821,25 @@ static int sun_driver_stop (sun_driver_t
+       void *retval;
+       driver->run = 0;
+-      if (driver->threads & 1)
+-      {
+-              if (pthread_join(driver->thread_in, &retval) < 0)
+-              {
+-                      jack_error("sun_driver: pthread_join() failed: %s@%i",
+-                              __FILE__, __LINE__);
+-                      return -1;
+-              }
+-      }
+-      if (driver->threads & 2)
++      if (pthread_join(driver->io_thread, &retval) < 0)
+       {
+-              if (pthread_join(driver->thread_out, &retval) < 0)
+-              {
+-                      jack_error("sun_driver: pthread_join() failed: %s@%i",
+-                              __FILE__, __LINE__);
+-                      return -1;
+-              }
++              jack_error("sun_driver: pthread_join() failed: %s@%i",
++                      __FILE__, __LINE__);
++              return -1;
+       }
++
+       sem_destroy(&driver->sem_start);
+-#     ifdef USE_BARRIER
+-      pthread_barrier_destroy(&driver->barrier);
+-#     endif
+-      pthread_mutex_destroy(&driver->mutex_in);
+-      pthread_mutex_destroy(&driver->mutex_out);
++      pthread_mutex_destroy(&driver->io_mutex);
+       if (driver->outfd >= 0 && driver->outfd != driver->infd)
+       {
++              ioctl(driver->outfd, AUDIO_DRAIN);
+               close(driver->outfd);
+               driver->outfd = -1;
+       }
+       if (driver->infd >= 0)
+       {
++              ioctl(driver->infd, AUDIO_DRAIN);
+               close(driver->infd);
+               driver->infd = -1;
+       }
+@@ -744,16 +866,19 @@ static int sun_driver_read (sun_driver_t
+       JSList *node;
+       jack_port_t *port;
+-      if (!driver->run) return 0;
++      if (!driver->run)
++              return 0;
++
+       if (nframes != driver->period_size)
+       {
+               jack_error(
+-                      "sun_driver: read failed nframes != period_size  (%u/%u): %s@%i",
+-                      nframes, driver->period_size, __FILE__, __LINE__);
++                      "sun_driver: read failed nframes != period_size: "
++                      "(%u/%u): %s@%i", nframes, driver->period_size,
++                      __FILE__, __LINE__);
+               return -1;
+       }
+-      pthread_mutex_lock(&driver->mutex_in);
++      pthread_mutex_lock(&driver->io_mutex);
+       node = driver->capture_ports;
+       channel = 0;
+@@ -774,7 +899,7 @@ static int sun_driver_read (sun_driver_t
+               channel++;
+       }
+-      pthread_mutex_unlock(&driver->mutex_in);
++      pthread_mutex_unlock(&driver->io_mutex);
+       return 0;
+ }
+@@ -787,16 +912,19 @@ static int sun_driver_write (sun_driver_
+       JSList *node;
+       jack_port_t *port;
+-      if (!driver->run) return 0;
++      if (!driver->run)
++              return 0;
++
+       if (nframes != driver->period_size)
+       {
+               jack_error(
+-                      "sun_driver: write failed nframes != period_size  (%u/%u): %s@%i",
+-                      nframes, driver->period_size, __FILE__, __LINE__);
++                      "sun_driver: write failed nframes != period_size "
++                      "(%u/%u): %s@%i", nframes, driver->period_size,
++                      __FILE__, __LINE__);
+               return -1;
+       }
+-      pthread_mutex_lock(&driver->mutex_out);
++      pthread_mutex_lock(&driver->io_mutex);
+       node = driver->playback_ports;
+       channel = 0;
+@@ -817,7 +945,7 @@ static int sun_driver_write (sun_driver_
+               channel++;
+       }
+-      pthread_mutex_unlock(&driver->mutex_out);
++      pthread_mutex_unlock(&driver->io_mutex);
+       return 0;
+ }
+@@ -825,13 +953,10 @@ static int sun_driver_write (sun_driver_
+ static int sun_driver_null_cycle (sun_driver_t *driver, jack_nframes_t nframes)
+ {
+-      pthread_mutex_lock(&driver->mutex_in);
++      pthread_mutex_lock(&driver->io_mutex);
+       memset(driver->indevbuf, 0x00, driver->indevbufsize);
+-      pthread_mutex_unlock(&driver->mutex_in);
+-
+-      pthread_mutex_lock(&driver->mutex_out);
+       memset(driver->outdevbuf, 0x00, driver->outdevbufsize);
+-      pthread_mutex_unlock(&driver->mutex_out);
++      pthread_mutex_unlock(&driver->io_mutex);
+       return 0;
+ }
+@@ -853,39 +978,19 @@ static int sun_driver_bufsize (sun_drive
+ /* internal driver thread */
+-
+-#ifdef USE_BARRIER
+-static inline void synchronize (sun_driver_t *driver)
+-{
+-      if (driver->threads == 3)
+-      {
+-              if (pthread_barrier_wait(&driver->barrier) ==
+-                      PTHREAD_BARRIER_SERIAL_THREAD)
+-              {
+-                      driver_cycle(driver);
+-              }
+-      }
+-      else
+-      {
+-              driver_cycle(driver);
+-      }
+-}
+-#endif
+-
+-
+ static void *io_thread (void *param)
+ {
+       size_t localsize;
+       ssize_t io_res;
+       void *localbuf;
+       sun_driver_t *driver = (sun_driver_t *) param;
++      audio_info_t audio_if;
++      int i;
+-      sem_wait(&driver->sem_start);
+-
+-#     ifdef USE_BARRIER
+-      if (pthread_self() == driver->thread_in)
++      if (driver->outfd >= 0 && driver->playback_channels > 0)
+       {
+-              localsize = driver->indevbufsize;
++              /* "prime" the playback buffer */
++              localsize = driver->outdevbufsize;
+               localbuf = malloc(localsize);
+               if (localbuf == NULL)
+               {
+@@ -894,113 +999,104 @@ static void *io_thread (void *param)
+                       return NULL;
+               }
+-              while (driver->run)
++              memset(localbuf, 0, localsize);
++              for (i = 0; i < driver->nperiods; i++)
+               {
+-                      io_res = read(driver->infd, localbuf, localsize);
++                      io_res = write(driver->outfd, localbuf, localsize);
+                       if (io_res < (ssize_t) localsize)
+                       {
+                               jack_error(
+-                                      "sun_driver: read() failed: %s@%i, count=%d/%d, errno=%d",
+-                                      __FILE__, __LINE__, io_res, localsize,
+-                                      errno);
++                                      "sun_driver: write() failed: %s@%i, "
++                                      "count=%d/%d, errno=%d", __FILE__,
++                                      __LINE__, io_res, localsize, errno);
+                               break;
+                       }
+-
+-                      pthread_mutex_lock(&driver->mutex_in);
+-                      memcpy(driver->indevbuf, localbuf, localsize);
+-                      pthread_mutex_unlock(&driver->mutex_in);
+-
+-                      synchronize(driver);
+               }
+-
+               free(localbuf);
+       }
+-      else if (pthread_self() == driver->thread_out)
+-      {
+-              localsize = driver->outdevbufsize;
+-              localbuf = malloc(localsize);
+-              if (localbuf == NULL)
+-              {
+-                      jack_error("sun_driver: malloc() failed: %s@%i",
+-                              __FILE__, __LINE__);
+-                      return NULL;
+-              }
+-              while (driver->run)
+-              {
+-                      pthread_mutex_lock(&driver->mutex_out);
+-                      memcpy(localbuf, driver->outdevbuf, localsize);
+-                      pthread_mutex_unlock(&driver->mutex_out);
+-                      io_res = write(driver->outfd, localbuf, localsize);
+-                      if (io_res < (ssize_t) localsize)
+-                      {
+-                              jack_error(
+-                                      "sun_driver: write() failed: %s@%i, count=%d/%d, errno=%d",
+-                                      __FILE__, __LINE__, io_res, localsize,
+-                                      errno);
+-                              break;
+-                      }
++      sem_wait(&driver->sem_start);
+-                      synchronize(driver);
+-              }
++      /* start DMA engine(s) */
+-              free(localbuf);
++      if (driver->infd >= 0)
++      {
++              AUDIO_INITINFO(&audio_if);
++              audio_if.record.pause = 0;
++              if (ioctl(driver->infd, AUDIO_SETINFO, &audio_if) < 0)
++                      jack_error(
++                              "sun_driver: failed to trigger capture: "
++                              "%s@%i, errno=%d", __FILE__, __LINE__, errno);
++              ioctl(driver->infd, AUDIO_FLUSH);
++      }
++
++      if (driver->outfd >= 0)
++      {
++              AUDIO_INITINFO(&audio_if);
++              audio_if.play.pause = 0;
++              if (ioctl(driver->outfd, AUDIO_SETINFO, &audio_if) < 0)
++                      jack_error(
++                              "sun_driver: failed to trigger playback: "
++                              "%s@%i, errno=%d", __FILE__, __LINE__, errno);
++              ioctl(driver->outfd, AUDIO_FLUSH);
+       }
+-#     else
++
+       localsize = (driver->indevbufsize >= driver->outdevbufsize) ?
+               driver->indevbufsize : driver->outdevbufsize;
+       localbuf = malloc(localsize);
+       if (localbuf == NULL)
+       {
+-              jack_error("sun_driver: malloc() failed: %s@%i", __FILE__, __LINE__);
++              jack_error("sun_driver: malloc() failed: %s@%i",
++                      __FILE__, __LINE__);
+               return NULL;
+       }
+       while (driver->run)
+       {
+-              if (driver->outfd >= 0 && driver->playback_channels > 0)
++              if (driver->playback_ready > 0)
+               {
+-                      pthread_mutex_lock(&driver->mutex_out);
++                      pthread_mutex_lock(&driver->io_mutex);
+                       memcpy(localbuf, driver->outdevbuf, 
+                               driver->outdevbufsize);
+-                      pthread_mutex_unlock(&driver->mutex_out);
++                      pthread_mutex_unlock(&driver->io_mutex);
+                       io_res = write(driver->outfd, localbuf, 
+                               driver->outdevbufsize);
+                       if (io_res < (ssize_t) driver->outdevbufsize)
+                       {
+                               jack_error(
+-                                      "sun_driver: write() failed: %s@%i, count=%d/%d, errno=%d",
++                                      "sun_driver: write() failed: %s@%i, "
++                                      "count=%d/%d, errno=%d",
+                                       __FILE__, __LINE__, io_res,
+                                       driver->outdevbufsize, errno);
+                               break;
+                       }
+               }
+-              if (driver->capture_channels > 0)
++              if (driver->capture_ready > 0)
+               {
+                       io_res = read(driver->infd, localbuf, 
+                               driver->indevbufsize);
+                       if (io_res < (ssize_t) driver->indevbufsize)
+                       {
+                               jack_error(
+-                                      "sun_driver: read() failed: %s@%i, count=%d/%d, errno=%d",
++                                      "sun_driver: read() failed: %s@%i, "
++                                      "count=%d/%d, errno=%d",
+                                       __FILE__, __LINE__, io_res,
+                                       driver->indevbufsize, errno);
+                               break;
+                       }
+-                      pthread_mutex_lock(&driver->mutex_in);
++                      pthread_mutex_lock(&driver->io_mutex);
+                       memcpy(driver->indevbuf, localbuf, 
+                               driver->indevbufsize);
+-                      pthread_mutex_unlock(&driver->mutex_in);
++                      pthread_mutex_unlock(&driver->io_mutex);
+               }
+               driver_cycle(driver);
+       }
+       free(localbuf);
+-#     endif
+       return NULL;
+ }
+@@ -1082,7 +1178,7 @@ jack_driver_t * driver_initialize (jack_
+       driver->indev = NULL;
+       driver->outdev = NULL;
+       driver->ignorehwbuf = 0;
+-      driver->trigger = 0;
++      driver->verbose = 0;
+       pnode = params;
+       while (pnode != NULL)
+@@ -1109,6 +1205,9 @@ jack_driver_t * driver_initialize (jack_
+                       case 'o':
+                               playback_channels = param->value.ui;
+                               break;
++                      case 'v':
++                              driver->verbose = 1;
++                              break;
+                       case 'C':
+                               driver->indev = strdup(param->value.str);
+                               break;
+@@ -1172,4 +1271,3 @@ void driver_finish (jack_driver_t *drive
+               free(sun_driver->outdev);
+       free(driver);
+ }
+-