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

📄 sound_alsa.cxx

📁 安装 H323需要的pwlib库
💻 CXX
📖 第 1 页 / 共 2 页
字号:
/* * sound_alsa.cxx * * Sound driver implementation. * * Portable Windows Library * * Copyright (c) 1993-1998 Equivalence Pty. Ltd. * * The contents of this file are subject to the Mozilla Public License * Version 1.0 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. * * The Original Code is Portable Windows Library. * * The Initial Developer of the Original ALSA Code is  * Damien Sandras <dsandras@seconix.com> * * Portions are Copyright (C) 1993 Free Software Foundation, Inc. * All Rights Reserved. * * Contributor(s): / * * $Log: sound_alsa.cxx,v $ * Revision 1.24  2004/11/07 20:23:00  dsandras * Removed erroneous update of lastReadCount in previous commit. * * Revision 1.23  2004/11/07 20:01:32  dsandras * Make sure lastWriteCount is updated. * * Revision 1.22  2004/11/06 16:31:12  dsandras * Removed dictionnary copy. * * Revision 1.21  2004/10/18 11:43:39  dsandras * Use Capture instead of Mic when changing the volume. Use the correct mixer when using the Default device. * * Revision 1.20  2004/10/14 19:30:16  dsandras * Removed DMIX and DSNOOP plugins and added support for DEFAULT as it is the correcti way to do things. * * Revision 1.19  2004/08/30 21:09:41  dsandras * Added DSNOOP plugin support. * * Revision 1.18  2004/05/14 10:15:26  dominance * Fixes direct opening of sound output devices. The list of devices does no longer return NULL in that case. Patch provided by Julien Puydt <julien.puydt@laposte.net>. * * Revision 1.17  2004/04/03 10:33:45  dsandras * Use PStringToOrdinal to store the detected devices, that fixes problems if there is a discontinuity in the succession of soundcard ID's. For example the user has card ID 1 and 3, but not 2. * * Revision 1.16  2004/03/13 12:36:14  dsandras * Added support for DMIX plugin output. * * Revision 1.15  2004/03/04 13:36:13  dsandras * Added check so that ALSA doesn't assert on broken installations. * * Revision 1.14  2004/02/12 09:07:57  csoutheren * Fixed typo in ALSA driver, thanks to Julien Puydt * * Revision 1.13  2004/01/04 20:59:30  dsandras * Use set_rate_near instead of set_rate. * * Revision 1.12  2003/12/28 15:10:35  dsandras * Updated to the new PCM API. * * Revision 1.11  2003/12/18 11:16:41  dominance * Removed the ALSA Abort completely upon Damien's request ;) * * Revision 1.10  2003/12/18 10:38:55  dominance * Removed ALSA Abort as it segfaults in various circumstances. * Fix proposed by Damien Sandras <dsandras@seconix.com>. * * Revision 1.9  2003/12/09 22:47:10  dsandras * Use less aggressive Abort. * * Revision 1.8  2003/12/03 21:48:21  dsandras * Better handling of buffer sizes. Removed unuseful code. * * Revision 1.7  2003/11/25 20:13:48  dsandras * Added #pragma. * * Revision 1.6  2003/11/25 09:58:01  dsandras * Removed Abort call from PlaySound (). * * Revision 1.5  2003/11/25 09:52:07  dsandras * Modified WaitForPlayCompletion so that it uses snd_pcm_drain instead of active waiting. * * Revision 1.4  2003/11/23 22:09:57  dsandras * Removed unuseful stuff and added implementation for functions permitting to play a file or a PSound. * * Revision 1.3  2003/11/14 05:28:47  csoutheren * Updated for new plugin code thanks to Damien and Snark * */#pragma implementation "sound_alsa.h"#include "sound_alsa.h"PCREATE_SOUND_PLUGIN(ALSA, PSoundChannelALSA)static PStringToOrdinal playback_devices;static PStringToOrdinal capture_devices;///////////////////////////////////////////////////////////////////////////////PSoundChannelALSA::PSoundChannelALSA(){  PSoundChannelALSA::Construct();}PSoundChannelALSA::PSoundChannelALSA (const PString &device,				      Directions dir,				      unsigned numChannels,				      unsigned sampleRate,				      unsigned bitsPerSample){  Construct();  Open (device, dir, numChannels, sampleRate, bitsPerSample);}void PSoundChannelALSA::Construct(){  frame_bytes = 0;  period_size = 0;  periods = 0;  card_nr = 0;  os_handle = NULL;}PSoundChannelALSA::~PSoundChannelALSA(){  Close();}void PSoundChannelALSA::UpdateDictionary (Directions dir){  int card = -1, dev = -1;    snd_ctl_t *handle = NULL;  snd_ctl_card_info_t *info = NULL;  snd_pcm_info_t *pcminfo = NULL;  snd_pcm_stream_t stream;  char *name = NULL;  char card_id [32];  if (dir == Recorder) {    stream = SND_PCM_STREAM_CAPTURE;    capture_devices = PStringToOrdinal ();  }  else {    stream = SND_PCM_STREAM_PLAYBACK;    playback_devices = PStringToOrdinal ();  }  snd_ctl_card_info_alloca (&info);  snd_pcm_info_alloca (&pcminfo);  /* No sound card found */  if (snd_card_next (&card) < 0 || card < 0) {    return;  }  while (card >= 0) {    snprintf (card_id, 32, "hw:%d", card);        if (snd_ctl_open (&handle, card_id, 0) == 0) {      snd_ctl_card_info (handle, info);      while (1) {        snd_ctl_pcm_next_device (handle, &dev);        if (dev < 0)          break;        snd_pcm_info_set_device (pcminfo, dev);        snd_pcm_info_set_subdevice (pcminfo, 0);        snd_pcm_info_set_stream (pcminfo, stream);        if (snd_ctl_pcm_info (handle, pcminfo) >= 0) {	  snd_card_get_name (card, &name);	  if (dir == Recorder) 	    capture_devices.SetAt (name, card);	  else 	    playback_devices.SetAt (name, card);          free (name);        }      }    }    snd_ctl_close(handle);    snd_card_next (&card);  }}PStringArray PSoundChannelALSA::GetDeviceNames (Directions dir){  PStringArray devices;   UpdateDictionary (dir);    if (dir == Recorder) {        for (PINDEX j = 0 ; j < capture_devices.GetSize () ; j++)       devices += capture_devices.GetKeyAt (j);  }  else {    for (PINDEX j = 0 ; j < playback_devices.GetSize () ; j++)       devices += playback_devices.GetKeyAt (j);  }  if (devices.GetSize () > 0)    devices += "Default";    return devices;}PString PSoundChannelALSA::GetDefaultDevice(Directions dir){  PStringArray devicenames;  devicenames = PSoundChannelALSA::GetDeviceNames (dir);  return devicenames[0];}BOOL PSoundChannelALSA::Open (const PString & _device,                              Directions _dir,			      unsigned _numChannels,			      unsigned _sampleRate,			      unsigned _bitsPerSample){  PString real_device_name;  POrdinalKey *i = NULL;  snd_pcm_stream_t stream;  Close();  os_handle = NULL;  if (_dir == Recorder)    stream = SND_PCM_STREAM_CAPTURE;  else    stream = SND_PCM_STREAM_PLAYBACK;  /* Open in NONBLOCK mode */  if (_device == "Default") {    real_device_name = "default";    card_nr = -2;  }  else {  if ((_dir == Recorder && capture_devices.IsEmpty ())      || (_dir == Player && playback_devices.IsEmpty ()))    UpdateDictionary (_dir);    i = (_dir == Recorder) ? capture_devices.GetAt (_device) : playback_devices.GetAt (_device);    if (i) {      real_device_name = "plughw:" + PString (*i);      card_nr = *i;    }    else {      PTRACE (1, "ALSA\tDevice not found");      return FALSE;    }  }      if (snd_pcm_open (&os_handle, real_device_name, stream, SND_PCM_NONBLOCK) < 0) {    PTRACE (1, "ALSA\tOpen Failed");    return FALSE;  }  else     snd_pcm_nonblock (os_handle, 0);     /* save internal parameters */  direction = _dir;  device = real_device_name;  mNumChannels = _numChannels;  mSampleRate = _sampleRate;  mBitsPerSample = _bitsPerSample;  isInitialised = FALSE;  PTRACE (1, "ALSA\tDevice " << real_device_name << " Opened");  return TRUE;}BOOL PSoundChannelALSA::Setup(){  snd_pcm_hw_params_t *hw_params = NULL;  snd_pcm_uframes_t buffer_size = 0;    int err = 0;  enum _snd_pcm_format val = SND_PCM_FORMAT_UNKNOWN;  BOOL no_error = TRUE;  if (os_handle == NULL) {    PTRACE(6, "ALSA\tSkipping setup of " << device << " as not open");    return FALSE;  }  if (isInitialised) {    PTRACE(6, "ALSA\tSkipping setup of " << device << " as instance already initialised");    return TRUE;  }#if PBYTE_ORDER == PLITTLE_ENDIAN  val = (mBitsPerSample == 16) ? SND_PCM_FORMAT_S16_LE : SND_PCM_FORMAT_U8;#else  val = (mBitsPerSample == 16) ? SND_PCM_FORMAT_S16_BE : SND_PCM_FORMAT_U8;#endif  frame_bytes = (mNumChannels * (snd_pcm_format_width (val) / 8));  snd_pcm_hw_params_alloca (&hw_params);  if ((err = snd_pcm_hw_params_any (os_handle, hw_params)) < 0) {    PTRACE (1, "ALSA\tCannot initialize hardware parameter structure " <<	    snd_strerror (err));    no_error = FALSE;  }  if ((err = snd_pcm_hw_params_set_access (os_handle, hw_params, 					   SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {    PTRACE (1, "ALSA\tCannot set access type " <<	    snd_strerror (err));    no_error = FALSE;  }  if ((err = snd_pcm_hw_params_set_format (os_handle, hw_params, val)) < 0) {    PTRACE (1, "ALSA\tCannot set sample format " <<             snd_strerror (err));    no_error = FALSE;  }  if ((err = snd_pcm_hw_params_set_rate_near (os_handle,					      hw_params, 					      &mSampleRate,					      NULL)) < 0) {    PTRACE (1, "ALSA\tCannot set sample rate " <<	    snd_strerror (err));    no_error = FALSE;  }  if ((err = snd_pcm_hw_params_set_channels (os_handle, hw_params, 					     mNumChannels)) < 0) {    PTRACE (1, "ALSA\tCannot set channel count " <<             snd_strerror (err));    no_error = FALSE;  }  // Ignore errors here   if (periods && period_size) {    if ((err = snd_pcm_hw_params_set_period_size_near (os_handle, 						       hw_params, 						       &period_size, 						       0)) < 0)      PTRACE (1, "ALSA\tCannot set period size " <<	      snd_strerror (err));        if ((err = snd_pcm_hw_params_set_periods_near (os_handle, 						   hw_params, 						   &periods,						   0)) < 0)      PTRACE (1, "ALSA\tCannot set number of periods " <<	      snd_strerror (err));    buffer_size = periods*period_size/frame_bytes;          if ((err = (int) snd_pcm_hw_params_set_buffer_size_near (os_handle, 							     hw_params, 							     &buffer_size))	< 0)      PTRACE (1, "ALSA\tCannot set buffer size " <<	      snd_strerror (err));  }        if ((err = snd_pcm_hw_params (os_handle, hw_params)) < 0) {    PTRACE (1, "ALSA\tCannot set parameters " <<	    snd_strerror (err));    no_error = FALSE;  }    isInitialised = TRUE;  return no_error;}BOOL PSoundChannelALSA::Close(){  PWaitAndSignal m(device_mutex);  /* if the channel isn't open, do nothing */  if (!os_handle)    return FALSE;

⌨️ 快捷键说明

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