--- Makefile.am.orig    2004-10-17 10:44:02.000000000 +0930
+++ Makefile.am 2004-10-17 10:45:06.000000000 +0930
@@ -54,11 +54,13 @@

_audio_oss_la_SOURCES =                \
       audio_oss.cc                    \
+       audio_oss_dev.cc                \
       audio_oss_sink.cc               \
       audio_oss_source.cc


grinclude_HEADERS =                    \
+       audio_oss_dev.h                 \
       audio_oss_sink.h                \
       audio_oss_source.h

--- /dev/null   2004-10-17 11:18:48.000000000 +0930
+++ audio_oss_dev.cc    2004-10-17 11:01:23.000000000 +0930
@@ -0,0 +1,137 @@
+#include <fcntl.h>
+#include <sys/audioio.h>
+#include <sys/ioctl.h>
+
+#include "audio_oss_dev.h"
+
+// A vector to manage the active devices
+static std::vector<audio_oss_dev_t> device_list;
+
+/*
+ *  If not already open, open device of requested type,
+ *  add it to the vector list, increment corresponding sink
+ *  or source counter by one, store and return its file descriptor.
+ *  The device can be opened multiple times as an audio source
+ *  but only once as an audio sink. On success, the cached
+ *  file descriptor stored for the device is returned to the
+ *  application.
+ */
+int
+audio_oss_dev::open(const std::string device, audio_oss_dev_type_t type)
+{
+  int fd;
+  std::vector<audio_oss_dev_t>::iterator vi;
+
+  // Check if device is already open
+  vi = get(device);
+
+  if(vi != device_list.end()) {
+    // Ensure that audio sink is only opened once
+    if(type == AUDIO_OSS_DEV_SINK && vi->count[type] > 0) {
+      errno = EBUSY;
+      return -1;
+    }
+
+    vi->count[type]++;
+    return vi->fdesc;
+  }
+
+  // Open device in read/write mode
+  // as NetBSD can only call open() once per device
+  fd = ::open(device.c_str(), O_RDWR);
+
+  if(fd < 0)
+    return fd;
+
+#if defined(__NetBSD__)
+  int audio_props = 0;
+
+  // Get device properties and enable fullduplex mode
+  // for devices that support it
+  if((ioctl(fd, AUDIO_GETPROPS, &audio_props)) != -1) {
+    audio_props &= AUDIO_PROP_FULLDUPLEX;
+    ioctl(fd, AUDIO_SETFD, &audio_props);
+  }
+#endif
+
+  // Create a temporary data structure
+  audio_oss_dev_t dev;
+
+  // Initialize counters
+  dev.count[AUDIO_OSS_DEV_SOURCE] = 0;
+  dev.count[AUDIO_OSS_DEV_SINK] = 0;
+
+  // Store device data
+  dev.fdesc = fd;
+  dev.name = device;
+  dev.count[type]++;
+  device_list.push_back(dev);
+
+  // Return device file descriptor
+  return fd;
+}
+
+/*
+ *  Check if device has an entry in the vector list. If so,
+ *  decrement the counter of the requested device type. Close
+ *  and erase device if both, the sink and source counter, are
+ *  zero.
+ */
+int
+audio_oss_dev::close(int fdesc, audio_oss_dev_type_t type)
+{
+  std::vector<audio_oss_dev_t>::iterator vi = get(fdesc);
+
+  if(vi != device_list.end()) {
+    if(vi->count[type] > 0) {
+
+      vi->count[type]--;
+
+      if(vi->count[AUDIO_OSS_DEV_SOURCE] == 0 &&
+         vi->count[AUDIO_OSS_DEV_SINK] == 0) {
+       device_list.erase(vi);
+        return ::close(fdesc);
+      }
+
+      return 0;
+    }
+  }
+
+   return -1;
+}
+
+/*
+ *  Search for device by name and return vector iterator
+ */
+std::vector<audio_oss_dev_t>::iterator
+audio_oss_dev::get(const std::string device)
+{
+  std::vector<audio_oss_dev_t>::iterator vi;
+
+  // Find device in list and return vector iterator
+  for(vi = device_list.begin(); vi != device_list.end(); vi++) {
+    if(vi->name == device)
+      return vi;
+  }
+
+  // Returns end of vector if unsuccessful
+  return vi;
+}
+
+/*
+ *  Search for device by file descriptor and return vector iterator
+ */
+std::vector<audio_oss_dev_t>::iterator
+audio_oss_dev::get(int fdesc)
+{
+  std::vector<audio_oss_dev_t>::iterator vi;
+
+  // Find device in list and return vector iterator
+  for(vi = device_list.begin(); vi != device_list.end(); vi++) {
+    if(vi->fdesc == fdesc)
+      return vi;
+  }
+
+  // Returns end of vector if unsuccessful
+  return vi;
+}
--- /dev/null   2004-10-17 11:18:48.000000000 +0930
+++ audio_oss_dev.h     2004-10-17 11:02:58.000000000 +0930
@@ -0,0 +1,21 @@
+#include <iostream>
+#include <vector>
+
+enum audio_oss_dev_type_t {AUDIO_OSS_DEV_SOURCE, AUDIO_OSS_DEV_SINK};
+
+struct audio_oss_dev_t {
+  std::string name;
+  int fdesc;
+  int count[2];
+};
+
+class audio_oss_dev
+{
+private:
+    static std::vector<audio_oss_dev_t>::iterator get(int fdesc);
+    static std::vector<audio_oss_dev_t>::iterator get(const std::string device);
+
+public:
+    static int open(const std::string device, audio_oss_dev_type_t type);
+    static int close(int fdesc, audio_oss_dev_type_t type);
+};
--- audio_oss_source.cc.orig    2004-10-04 04:27:39.000000000 +0930
+++ audio_oss_source.cc 2004-10-17 10:52:53.000000000 +0930
@@ -24,6 +24,7 @@
#include "config.h"
#endif

+#include <audio_oss_dev.h>
#include <audio_oss_source.h>
#include <gr_io_signature.h>
#include <sys/soundcard.h>
@@ -48,7 +49,7 @@
    d_sampling_freq (sampling_freq), d_device_name (device_name),
    d_fd (-1), d_buffer (0), d_chunk_size (0)
{
-  if ((d_fd = open (device_name.c_str (), O_RDONLY)) < 0){
+  if ((d_fd = audio_oss_dev::open (device_name.c_str (), AUDIO_OSS_DEV_SOURCE)) < 0){
    fprintf (stderr, "audio_oss_source: ");
    perror (device_name.c_str ());
    throw std::runtime_error ("audio_oss_source");
--- audio_oss_sink.cc.orig      2004-10-04 04:27:24.000000000 +0930
+++ audio_oss_sink.cc   2004-10-17 10:57:49.000000000 +0930
@@ -24,6 +24,7 @@
#include "config.h"
#endif

+#include <audio_oss_dev.h>
#include <audio_oss_sink.h>
#include <gr_io_signature.h>
#include <sys/soundcard.h>
@@ -36,7 +37,6 @@
#include <iostream>
#include <stdexcept>

-
static const double CHUNK_TIME = 0.001;                // 1 ms


@@ -48,7 +48,7 @@
    d_sampling_freq (sampling_freq), d_device_name (device_name),
    d_fd (-1), d_buffer (0), d_chunk_size (0)
{
-  if ((d_fd = open (device_name.c_str (), O_WRONLY)) < 0){
+  if ((d_fd = audio_oss_dev::open (device_name, AUDIO_OSS_DEV_SINK)) < 0){
    fprintf (stderr, "audio_oss_sink: ");
    perror (device_name.c_str ());
    throw std::runtime_error ("audio_oss_sink");
@@ -95,7 +95,7 @@

audio_oss_sink::~audio_oss_sink ()
{
-  close (d_fd);
+  audio_oss_dev::close (d_fd, AUDIO_OSS_DEV_SOURCE);
  delete [] d_buffer;
}