home *** CD-ROM | disk | FTP | other *** search
/ Windows 95 Secrets / Secrets2.iso / Audio / WAV / MaplayP / _SETUP.1 / linux_obuffer.cc < prev    next >
Encoding:
C/C++ Source or Header  |  1997-07-08  |  4.4 KB  |  198 lines

  1. /* linux_obuffer.cc
  2.  
  3.    Output buffer for Linux written by
  4.    Louis P. Kruger (lpkruger@phoenix.princeton.edu)
  5.  
  6.    This buffer should work for FreeBSD as well, thanks to the patches
  7.    from the FreeBSD web site.
  8.  
  9.    This program is free software; you can redistribute it and/or modify
  10.    it under the terms of the GNU General Public License as published by
  11.    the Free Software Foundation; either version 2 of the License, or
  12.    (at your option) any later version.
  13.  
  14.    This program is distributed in the hope that it will be useful,
  15.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17.    GNU General Public License for more details.
  18.  
  19.    You should have received a copy of the GNU General Public License
  20.    along with this program; if not, write to the Free Software
  21.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
  22.  
  23. #if defined(LINUX) || defined (__FREEBSD__)
  24.  
  25. #include <stdio.h>
  26. #include <stdlib.h>
  27. #include <string.h>
  28. #include <errno.h>
  29. #include <unistd.h>
  30. #include <fcntl.h>
  31. #include <sys/ioctl.h>
  32. #include <iostream.h>
  33.  
  34. extern "C" {
  35. #ifdef __FreeBSD__
  36. #include <machine/soundcard.h>
  37. #else
  38. #include <sys/soundcard.h>
  39. #endif // __FreeBSD__
  40. }
  41.  
  42. #include "args.h"
  43. #include "header.h"
  44. #include "obuffer.h"
  45.  
  46. int LinuxObuffer::audio_fd = -1;
  47.  
  48. int LinuxObuffer::open_audio_device (void)
  49. {
  50.   int fd;
  51.  
  52.   if ((fd = open ("/dev/dsp", O_WRONLY | O_NDELAY, 0)) < 0)
  53.     if (errno == EBUSY)
  54.     {
  55.       cerr << "Sorry, the audio device is busy!\n";
  56.       exit (1);
  57.     }
  58.     else
  59.     {
  60.       perror ("can't open /dev/dsp for writing");
  61.       exit (1);
  62.     }
  63.  
  64.  
  65. #ifdef LINUX
  66.  
  67.   // turn NDELAY mode off, for LINUX only
  68.  
  69.   int flags;
  70.   if ((flags = fcntl (fd, F_GETFL, 0)) < 0)
  71.   {
  72.     perror ("fcntl F_GETFL on /dev/audio failed");
  73.     exit (1);
  74.   }
  75.   flags &= ~O_NDELAY;
  76.   if (fcntl (fd, F_SETFL, flags) < 0)
  77.   {
  78.     perror ("fcntl F_SETFL on /dev/audio failed");
  79.     exit (1);
  80.   }
  81.  
  82. #endif // LINUX
  83.  
  84.   return fd;
  85. }
  86.  
  87.  
  88. LinuxObuffer::LinuxObuffer (uint32 number_of_channels, MPEG_Args *maplay_args)
  89. {
  90. #ifdef DEBUG
  91.   if (!number_of_channels || number_of_channels > MAXCHANNELS)
  92.   {
  93.     cerr << "LinuxObuffer: 0 < number of channels < " << MAXCHANNELS << "!\n";
  94.     exit (1);
  95.   }
  96. #endif
  97.   channels = number_of_channels;
  98.   for (int i = 0; i < number_of_channels; ++i)
  99.     bufferp[i] = buffer + i;
  100.  
  101.   if (audio_fd < 0)
  102.   {
  103.     cerr << "Internal error, LinuxObuffer::audio_fd has to be initialized\n"
  104.         "by LinuxObuffer::class_suitable()!\n";
  105.     exit (1);
  106.   }
  107.  
  108.   // configure the device:
  109.   int play_precision = 16;
  110.   int play_stereo = channels-1;
  111.   int play_sample_rate = maplay_args->MPEGheader->frequency ();
  112.  
  113.   if(
  114.       ioctl(audio_fd, SNDCTL_DSP_SAMPLESIZE, &play_precision) == -1 ||
  115.       ioctl(audio_fd, SNDCTL_DSP_STEREO, &play_stereo) == -1 ||
  116.       ioctl(audio_fd, SNDCTL_DSP_SPEED, &play_sample_rate) == -1
  117.     )
  118.   {
  119.     perror ("configuration of /dev/dsp failed");
  120.     exit (1);
  121.   }
  122. }
  123.  
  124. LinuxObuffer::~LinuxObuffer (void)
  125. {
  126.   sleep (1);
  127.   close (audio_fd);
  128. }
  129.  
  130. void LinuxObuffer::append (uint32 channel, int16 value)
  131. {
  132. #ifdef DEBUG
  133.   if (channel >= channels)
  134.   {
  135.     cerr << "illegal channelnumber in LinuxObuffer::append()!\n";
  136.     exit (1);
  137.   }
  138.   if (bufferp[channel] - buffer >= OBUFFERSIZE)
  139.   {
  140.     cerr << "buffer overflow!\n";
  141.     exit (1);
  142.   }
  143. #endif
  144.   *bufferp[channel] = value;
  145.   bufferp[channel] += channels;
  146. }
  147.  
  148. #ifdef SEEK_STOP
  149. void LinuxObuffer::clear_buffer(void)
  150. {
  151. }
  152.  
  153. void LinuxObuffer::set_stop_flag(void)
  154. {
  155. }
  156. #endif // SEEK_STOP
  157.  
  158. void LinuxObuffer::write_buffer (int)
  159. {
  160.   int length = (int)((char *)bufferp[0] - (char *)buffer);
  161.   if (write (audio_fd, buffer, length) != length)
  162.   {
  163.     perror ("write to /dev/dsp failed");
  164.     exit (1);
  165.   }
  166.   for (int i = 0; i < channels; ++i)
  167.     bufferp[i] = buffer + i;
  168. }
  169.  
  170.  
  171. BOOL LinuxObuffer::class_suitable (uint32 number_of_channels)
  172. {
  173.   // open the dsp audio device:
  174.   audio_fd = open_audio_device ();
  175.   return(TRUE);
  176. }
  177.  
  178. Obuffer *create_obuffer(MPEG_Args *maplay_args)
  179. {
  180.   Obuffer *buffer;
  181.  
  182.   enum e_mode mode = maplay_args->MPEGheader->mode();
  183.   enum e_channels which_channels = maplay_args->which_c;
  184.  
  185.   if (LinuxObuffer::class_suitable((mode == single_channel) ||
  186.                                                (which_channels != both)) ? 1 : 2)
  187.     if (mode == single_channel || which_channels != both)
  188.        buffer = new LinuxObuffer (1, maplay_args);
  189.     else
  190.        buffer = new LinuxObuffer (2, maplay_args);
  191.   else
  192.     return(NULL);
  193.  
  194.   return(buffer);
  195. }
  196.  
  197. #endif    // LINUX || __FREEBSD__
  198.