$NetBSD: patch-ai,v 1.1 2002/06/27 15:52:19 agc Exp $

--- obuffer.cc	2002/06/27 15:41:04	1.1
+++ obuffer.cc	2002/06/27 15:41:40
@@ -217,10 +217,10 @@
 int SparcObuffer::audio_fd = -1;
 
 #ifdef ULAW
-SparcObuffer::SparcObuffer (Header *header, bool use_speaker, bool use_headphone, bool use_line_out)
+SparcObuffer::SparcObuffer (Header *header, boolean use_speaker, boolean use_headphone, boolean use_line_out)
 #else
 SparcObuffer::SparcObuffer (uint32 number_of_channels, Header *header,
-			    bool use_speaker, bool use_headphone, bool use_line_out)
+			    boolean use_speaker, boolean use_headphone, boolean use_line_out)
 #endif
 {
 #ifndef ULAW
@@ -406,9 +406,9 @@
 
 
 #ifdef ULAW
-bool SparcObuffer::class_suitable (uint32 number_of_channels, bool force_amd)
+boolean SparcObuffer::class_suitable (uint32 number_of_channels, boolean force_amd)
 #else
-bool SparcObuffer::class_suitable (void)
+boolean SparcObuffer::class_suitable (void)
 #endif
 {
 #ifdef ULAW
@@ -537,6 +537,7 @@
     }
 
   // turn NDELAY mode off:
+#ifndef __FreeBSD__	/* Our /dev/audio doesn't like non-blocking I/O */
   int flags;
   if ((flags = fcntl (fd, F_GETFL, 0)) < 0)
   {
@@ -549,6 +550,7 @@
     perror ("fcntl F_SETFL on /dev/audio failed");
     exit (1);
   }
+#endif
   return fd;
 }
 
@@ -629,7 +631,7 @@
 }
 
 
-bool LinuxObuffer::class_suitable (uint32 number_of_channels)
+boolean LinuxObuffer::class_suitable (uint32 number_of_channels)
 {
   // open the dsp audio device:
   audio_fd = open_audio_device ();
@@ -637,3 +639,122 @@
 }
 
 #endif	/* LINUX */
+
+#ifdef NETBSD
+int NetBSDObuffer::audio_fd = -1;
+
+int NetBSDObuffer::open_audio_device (void)
+{
+  int fd;
+
+  if ((fd = open ("/dev/audio", O_WRONLY | O_NDELAY, 0)) < 0)
+    if (errno == EBUSY)
+    {
+      cerr << "Sorry, the audio device is busy!\n";
+      exit (1);
+    }
+    else
+    {
+      perror ("can't open /dev/audio for writing");
+      exit (1);
+    }
+
+  int flags;
+  if ((flags = fcntl (fd, F_GETFL, 0)) < 0)
+  {
+    perror ("fcntl F_GETFL on /dev/audio failed");
+    exit (1);
+  }
+  flags &= ~O_NDELAY;
+  if (fcntl (fd, F_SETFL, flags) < 0)
+  {
+    perror ("fcntl F_SETFL on /dev/audio failed");
+    exit (1);
+  }
+  return fd;
+}
+
+
+NetBSDObuffer::NetBSDObuffer (uint32 number_of_channels, Header *header)
+{
+#ifdef DEBUG
+  if (!number_of_channels || number_of_channels > MAXCHANNELS)
+  {
+    cerr << "NetBSDObuffer: 0 < number of channels < " << MAXCHANNELS << "!\n";
+    exit (1);
+  }
+#endif
+  channels = number_of_channels;
+  for (int i = 0; i < number_of_channels; ++i)
+    bufferp[i] = buffer + i;
+
+  if (audio_fd < 0)
+  {
+    cerr << "Internal error, NetBSDObuffer::audio_fd has to be initialized\n"
+	    "by NetBSDObuffer::class_suitable()!\n";
+    exit (1);
+  }
+
+  audio_info info;
+  AUDIO_INITINFO(&info);
+
+  // configure the device:
+  info.play.encoding = AUDIO_ENCODING_SLINEAR;
+  info.play.precision = 16;
+  info.play.channels = channels;
+  info.play.sample_rate = header->frequency ();
+
+  if (ioctl (audio_fd, AUDIO_SETINFO, &info))
+  {
+    perror ("configuration of /dev/audio failed");
+    exit (1);
+  }
+}
+
+
+NetBSDObuffer::~NetBSDObuffer (void)
+{
+  close (audio_fd);
+}
+
+
+void NetBSDObuffer::append (uint32 channel, int16 value)
+{
+#ifdef DEBUG
+  if (channel >= channels)
+  {
+    cerr << "illegal channelnumber in NetBSDObuffer::append()!\n";
+    exit (1);
+  }
+  if (bufferp[channel] - buffer >= OBUFFERSIZE)
+  {
+    cerr << "buffer overflow!\n";
+    exit (1);
+  }
+#endif
+  *bufferp[channel] = value;
+  bufferp[channel] += channels;
+}
+
+
+void NetBSDObuffer::write_buffer (int)
+{
+  int length = (int)((char *)bufferp[0] - (char *)buffer);
+  if (write (audio_fd, buffer, length) != length)
+  {
+    perror ("write to /dev/audio failed");
+    exit (1);
+  }
+  for (int i = 0; i < channels; ++i)
+    bufferp[i] = buffer + i;
+}
+
+
+boolean NetBSDObuffer::class_suitable (uint32 number_of_channels)
+{
+  // open the dsp audio device:
+  audio_fd = open_audio_device ();
+  return True;
+}
+
+#endif	/* NETBSD */
