⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sound_oss.cxx

📁 安装 H323需要的pwlib库
💻 CXX
📖 第 1 页 / 共 3 页
字号:
	// So collect devices by looking for dsp(N) and mixer(N).        // (or /dev/audio(N) and mixer(N) on NetBSD	// Notes. FreeBSD supports audio stream mixing. A single sound card	// may have multiple /dev entries in the form /dev/dspN.M	// eg /dev/dsp0.0 /dev/dsp0.1 /dev/dsp0.2 and /dev/dsp0.3	// When adding these to the 'dsp' string array, only the first one	// found is used.#ifndef P_NETBSD        // Look for dsp        if (filename == "dsp") {          dsp.SetAt(0, devname);        }        // Look for dspN entries. Insert at position N + 1        // and look for dspN.M entries. Insert at position N + 1 (ignoring M)        if ((filename.GetLength() > 3) && (filename.Left(3) == "dsp")) {	  PString numbers = filename.Mid(3); // get everything after 'dsp'	  if (IsNumericString(numbers)) {            PINDEX cardnum = numbers.AsInteger(); //dspN.M is truncated to dspN.	    // If we have not yet inserted something for this cardnum, insert it	    if (dsp.GetAt(cardnum+1) == NULL) {              dsp.SetAt(cardnum+1, devname);	    }	  }        }#else        // Look for audio on NetBSD         if (filename == "audio") {          dsp.SetAt(0, devname);        }        // Look for audioN. Insert at position cardnum + 1        if ((filename.GetLength() > 5) && (filename.Left(5) == "audio")) {	  PString numbers = filename.Mid(5); // get everything after 'audio'	  if (IsNumericString(numbers)) {            PINDEX cardnum = numbers.AsInteger();            dsp.SetAt(cardnum+1, devname);	  }        }#endif        // Look for mixer        if (filename == "mixer") {          mixer.SetAt(0, devname);        }        // Look for mixerN. Insert at position cardnum + 1        if ((filename.GetLength() > 5) && (filename.Left(5) == "mixer")) {	  PString numbers = filename.Mid(5); // get everything after 'mixer'	  if (IsNumericString(numbers)) {            PINDEX cardnum = numbers.AsInteger();            mixer.SetAt(cardnum+1, devname);	  }        }      }    }  } while (devdir.Next());}PStringArray PSoundChannelOSS::GetDeviceNames(Directions /*dir*/){  // First locate sound cards. On Linux with devfs and on the other platforms  // (eg FreeBSD), we search for filenames with dspN or mixerN.  // On linux without devfs we scan all of the devices and look for ones  // with major device numbers corresponding to OSS compatible drivers.  POrdinalToString dsp, mixer;#ifdef P_LINUX  PDirectory devdir = "/dev/sound";  if (devdir.Open()) {    CollectSoundDevices("/dev/sound", dsp, mixer, TRUE); // use names (devfs)  } else {    CollectSoundDevices("/dev", dsp, mixer, FALSE); // use major numbers  }#else  CollectSoundDevices("/dev", dsp, mixer, TRUE); // use names#endif  // Now we go through the collected devices and see if any have a phyisical reality  PStringList devices;  for (PINDEX i = 0; i < dsp.GetSize(); i++) {    PINDEX cardnum = dsp.GetKeyAt(i);    // Try and open mixer if have one as this is unlikely to fail for any    // reason other than there not being a physical device    if (mixer.Contains(cardnum)) {      int fd = ::open(mixer[cardnum], O_RDONLY);      if (fd >= 0) {        // Do something with the mixer to be sure it is there        int dummy;        if (::ioctl(fd, SOUND_MIXER_READ_DEVMASK, &dummy) >= 0)          devices.AppendString(dsp[cardnum]);        ::close(fd);      }      else {        // mixer failed but this could still be a valid dsp...        // warning this is just a hack to make this work on strange mixer and dsp configurations        // on my machine the first sound card registers 1 mixer and 2 dsp, so when my webcam        // registers itself as dsp2 this test would fail...        int fd = ::open(dsp[cardnum], O_RDONLY | O_NONBLOCK);        if (fd >= 0 || errno == EBUSY) {          devices.AppendString(dsp[cardnum]);          ::close(fd);        }      }    }    else {      // No mixer available, try and open it directly, this could fail if      // the device happens to be open already      int fd = ::open(dsp[cardnum], O_RDONLY | O_NONBLOCK);      if (fd >= 0 || errno == EBUSY) {        devices.AppendString(dsp[cardnum]);        ::close(fd);      }    }  }  return devices;}PString PSoundChannelOSS::GetDefaultDevice(Directions dir){  // Normally /dev/dsp points to the default sound device. If this is not  // present, probe /dev for sound devices and return the first detected device.    // return the first dsp device detected  PStringArray devicenames;  devicenames = PSoundChannelOSS::GetDeviceNames(dir);  return devicenames[0];}BOOL PSoundChannelOSS::Open(const PString & _device,                              Directions _dir,                                unsigned _numChannels,                                unsigned _sampleRate,                                unsigned _bitsPerSample){  Close();  // lock the dictionary  PWaitAndSignal mutex(dictMutex);  // make the direction value 1 or 2  int dir = _dir + 1;  // if this device is in the dictionary  if (handleDict().Contains(_device)) {    SoundHandleEntry & entry = handleDict()[_device];    // see if the sound channel is already open in this direction    if ((entry.direction & dir) != 0)       {	return FALSE;      }    // flag this entry as open in this direction    entry.direction |= dir;    os_handle = entry.handle;  } else {    // this is the first time this device has been used    // open the device in read/write mode always    // open the device in non-blocking mode to avoid hang if already open    os_handle = ::open((const char *)_device, O_RDWR | O_NONBLOCK);    if ((os_handle < 0) && (errno != EWOULDBLOCK))       return ConvertOSError(os_handle);    // switch to blocking mode    DWORD cmd = 0;    ::ioctl(os_handle, FIONBIO, &cmd);    // add the device to the dictionary    SoundHandleEntry * entry = PNEW SoundHandleEntry;    handleDict().SetAt(_device, entry);     // save the information into the dictionary entry    entry->handle        = os_handle;    entry->direction     = dir;    entry->numChannels   = mNumChannels     = _numChannels;    entry->sampleRate    = actualSampleRate = mSampleRate    = _sampleRate;    entry->bitsPerSample = mBitsPerSample   = _bitsPerSample;    entry->isInitialised = FALSE;    entry->fragmentValue = 0x7fff0008;  }     // save the direction and device  direction     = _dir;  device        = _device;  isInitialised = FALSE;  return TRUE;}BOOL PSoundChannelOSS::Setup(){  PWaitAndSignal mutex(dictMutex);  if (os_handle < 0) {    PTRACE(6, "OSS\tSkipping setup of " << device << " as not open");    return FALSE;  }  if (isInitialised) {    PTRACE(6, "OSS\tSkipping setup of " << device << " as instance already initialised");    return TRUE;  }  // the device must always be in the dictionary  PAssertOS(handleDict().Contains(device));  // get record for the device  SoundHandleEntry & entry = handleDict()[device];  // set default return status  BOOL stat = TRUE;  // do not re-initialise initialised devices  if (entry.isInitialised) {    PTRACE(6, "OSS\tSkipping setup for " << device << " as already initialised");  } else {    PTRACE(6, "OSS\tInitialising " << device << "(" << (void *)(&entry) << ")");#if defined(P_LINUX)    // enable full duplex (maybe).    ::ioctl(os_handle, SNDCTL_DSP_SETDUPLEX, 0);#endif    stat = FALSE;  // must always set paramaters in the following order:  //   buffer paramaters  //   sample format (number of bits)  //   number of channels (mon/stereo)  //   speed (sampling rate)    int arg, val;    // reset the device first so it will accept the new parms    if (ConvertOSError(::ioctl(os_handle, SNDCTL_DSP_RESET, &arg))) {      // set the write fragment size (applies to sound output only)      arg = val = entry.fragmentValue;      ::ioctl(os_handle, SNDCTL_DSP_SETFRAGMENT, &arg);       mBitsPerSample = entry.bitsPerSample;#if PBYTE_ORDER == PLITTLE_ENDIAN      arg = val = (entry.bitsPerSample == 16) ? AFMT_S16_LE : AFMT_S8;#else      arg = val = (entry.bitsPerSample == 16) ? AFMT_S16_BE : AFMT_S8;#endif      if (ConvertOSError(::ioctl(os_handle, SNDCTL_DSP_SETFMT, &arg)) || (arg != val)) {        mNumChannels = entry.numChannels;        arg = val = (entry.numChannels == 2) ? 1 : 0;        if (ConvertOSError(::ioctl(os_handle, SNDCTL_DSP_STEREO, &arg)) || (arg != val)) {          mSampleRate = entry.sampleRate;          arg = val = entry.sampleRate;          if (ConvertOSError(::ioctl(os_handle, SNDCTL_DSP_SPEED, &arg))) {            stat = TRUE;            actualSampleRate = arg;          }        }      }#if PTRACING      audio_buf_info info;      ::ioctl(os_handle, SNDCTL_DSP_GETOSPACE, &info);      PTRACE(4, "OSS\tOutput: fragments = " << info.fragments                     << ", total frags = " << info.fragstotal                     << ", frag size   = " << info.fragsize                     << ", bytes       = " << info.bytes);      ::ioctl(os_handle, SNDCTL_DSP_GETISPACE, &info);      PTRACE(4, "OSS\tInput: fragments = " << info.fragments                     << ", total frags = " << info.fragstotal                     << ", frag size   = " << info.fragsize                     << ", bytes       = " << info.bytes);#endif    }  }  // ensure device is marked as initialised  isInitialised       = TRUE;  entry.isInitialised = TRUE;  return stat;}BOOL PSoundChannelOSS::Close(){  // if the channel isn't open, do nothing  if (os_handle < 0)    return TRUE;  // the device must be in the dictionary  dictMutex.Wait();  SoundHandleEntry * entry;  PAssert((entry = handleDict().GetAt(device)) != NULL, "Unknown sound device \"" + device + "\" found");  // modify the directions bit mask in the dictionary  entry->direction ^= (direction+1);  // if this is the last usage of this entry, then remove it  if (entry->direction == 0) {    handleDict().RemoveAt(device);    dictMutex.Signal();    return PChannel::Close();  }  // flag this channel as closed  dictMutex.Signal();  os_handle = -1;  return TRUE;}BOOL PSoundChannelOSS::IsOpen() const{  return os_handle >= 0;}BOOL PSoundChannelOSS::Write(const void * buf, PINDEX len){  lastWriteCount = 0;  if (!Setup() || os_handle < 0)    return FALSE;  while (!ConvertOSError(::write(os_handle, (void *)buf, len)))    if (GetErrorCode() != Interrupted)      return FALSE;    lastWriteCount += len;    return TRUE;}BOOL PSoundChannelOSS::Read(void * buf, PINDEX len){  lastReadCount = 0;  if (!Setup() || os_handle < 0)    return FALSE;  PTRACE(6, "OSS\tRead start");#if defined(P_FREEBSD)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -