--- 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;
}