SoundIF-linux.cc
上传用户:weiliju62
上传日期:2007-01-06
资源大小:619k
文件大小:4k
源码类别:

SCSI/ASPI

开发平台:

MultiPlatform

  1. /*  cdrdao - write audio CD-Rs in disc-at-once mode
  2.  *
  3.  *  Copyright (C) 1998  Andreas Mueller <mueller@daneb.ping.de>
  4.  *
  5.  *  This program is free software; you can redistribute it and/or modify
  6.  *  it under the terms of the GNU General Public License as published by
  7.  *  the Free Software Foundation; either version 2 of the License, or
  8.  *  (at your option) any later version.
  9.  *
  10.  *  This program is distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  *  GNU General Public License for more details.
  14.  *
  15.  *  You should have received a copy of the GNU General Public License
  16.  *  along with this program; if not, write to the Free Software
  17.  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  */
  19. /*
  20.  * $Log: SoundIF-linux.cc,v $
  21.  * Revision 1.3  1999/08/07 16:27:28  mueller
  22.  * Applied patch from Yves Bastide:
  23.  * * prefixing member function names with their class name in connect_to_method
  24.  * * explicitly `const_cast'ing a cast to const
  25.  *
  26.  * Revision 1.2  1999/05/24 18:09:53  mueller
  27.  * Added check for existance of 'SNDCTL_DSP_GETODELAY'.
  28.  *
  29.  * Revision 1.1  1998/11/20 18:57:34  mueller
  30.  * Initial revision
  31.  *
  32.  */
  33. #include <linux/soundcard.h>
  34. #include <stdio.h>
  35. #include <assert.h>
  36. #include <string.h>
  37. #include <errno.h>
  38. #include <unistd.h>
  39. #include <fcntl.h>
  40. #include <sys/ioctl.h>
  41. #include <sys/types.h>
  42. #include "SoundIF.h"
  43. #include "Sample.h"
  44. #include "util.h"
  45. class SoundIFImpl {
  46. public:
  47.   SoundIFImpl() { dspFd_ = -1; }
  48.   int setupDevice();
  49.   int openDevice();
  50.   void closeDevice();
  51.   int dspFd_; // sound device
  52. };
  53. SoundIF::SoundIF()
  54. {
  55.   impl_ = new SoundIFImpl;
  56. }
  57. SoundIF::~SoundIF()
  58. {
  59.   delete impl_;
  60.   impl_ = NULL;
  61. }
  62. // Initializes sound interface.
  63. // return: 0: OK
  64. //         1: sounde device not found
  65. //         2: cannot setup sound device
  66. int SoundIF::init()
  67. {
  68.   if (impl_->openDevice() != 0)
  69.     return 1;
  70.   if (impl_->setupDevice() != 0) {
  71.     impl_->closeDevice();
  72.     return 2;
  73.   }
  74.   impl_->closeDevice();
  75.   return 0;
  76. }
  77. // Acquires sound device for playing.
  78. // return 0: OK
  79. //        1: error occured
  80. int SoundIF::start()
  81. {
  82.   if (impl_->dspFd_ >= 0)
  83.     return 0; // already opened
  84.   if (impl_->openDevice() != 0)
  85.     return 1;
  86.   if (impl_->setupDevice() != 0) {
  87.     impl_->closeDevice();
  88.     return 1;
  89.   }
  90.   return 0;
  91. }
  92. // Playes given sample buffer.
  93. // return: 0: OK
  94. //         1: error occured
  95. int SoundIF::play(Sample *sbuf, long nofSamples)
  96. {
  97.   if (impl_->dspFd_ < 0)
  98.     return 1;
  99.   swapSamples(sbuf, nofSamples);
  100.   long ret;
  101.   long len = nofSamples * sizeof(Sample);
  102.   long nwritten = 0;
  103.   char *buf = (char *)sbuf;
  104.   while (len > 0) {
  105.     ret = write(impl_->dspFd_, buf + nwritten, len);
  106.     if (ret <= 0)
  107.       return 1;
  108.     nwritten += ret;
  109.     len -= ret;
  110.   }
  111.   return 0;
  112. }
  113. unsigned long SoundIF::getDelay()
  114. {
  115.   if (impl_->dspFd_ < 0)
  116.     return 1;
  117. #ifdef SNDCTL_DSP_GETODELAY
  118.   int delay;
  119.   if (ioctl(impl_->dspFd_, SNDCTL_DSP_GETODELAY, &delay) == 0) {
  120.     return delay / 4;
  121.   }
  122. #endif
  123.   return 0;
  124. }
  125. // Finishs playing, sound device is released.
  126. void SoundIF::end()
  127. {
  128.   impl_->closeDevice();
  129. }
  130. int SoundIFImpl::openDevice()
  131. {
  132.   int flags;
  133.   if (dspFd_ >= 0)
  134.     return 0; // already open
  135.   if ((dspFd_ = open("/dev/dsp", O_WRONLY | O_NONBLOCK)) < 0) {
  136.     message(-1, "Cannot open "/dev/dsp": %s", strerror(errno));
  137.     return 1;
  138.   }
  139.   if ((flags = fcntl(dspFd_, F_GETFL)) >= 0) {
  140.     flags &= ~O_NONBLOCK;
  141.     fcntl(dspFd_, F_SETFL, flags);
  142.   }
  143.   return 0;
  144. }
  145.     
  146. void SoundIFImpl::closeDevice()
  147. {
  148.   if (dspFd_ >= 0) {
  149.     close(dspFd_);
  150.     dspFd_ = -1;
  151.   }
  152. }
  153. int SoundIFImpl::setupDevice()
  154. {
  155.   if (dspFd_ < 0)
  156.     return 1;
  157.   
  158.   int val = 44100;
  159.   if (ioctl(dspFd_, SNDCTL_DSP_SPEED, &val) < 0) {
  160.     message(-1, "Cannot set sample rate to 44100: %s", strerror(errno));
  161.     return 1;
  162.   }
  163.   val = 2;
  164.   if (ioctl(dspFd_, SNDCTL_DSP_CHANNELS, &val) < 0) {
  165.     message(-1, "Cannot setup 2 channels: %s", strerror(errno));
  166.     return 1;
  167.   }
  168.   val = AFMT_S16_LE;
  169.   if (ioctl(dspFd_, SNDCTL_DSP_SETFMT, &val) < 0) {
  170.     message(-1, "Cannot setup sound format: %s", strerror(errno));
  171.     return 1;
  172.   }
  173.   if (val != AFMT_S16_LE) {
  174.     message(-1, "Sound device does not support "
  175.     "little endian signed 16 bit samples.");
  176.     return 1;
  177.   }
  178.   
  179.   return 0;
  180. }