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

📄 sound_alsa.cxx

📁 sloedgy open sip stack source code
💻 CXX
📖 第 1 页 / 共 2 页
字号:

  if ((err = snd_pcm_hw_params_set_period_time_near (os_handle, hw_params, &period_time, 0)) < 0) {
    msg << "Cannot set period_time to " << (period_time / 1000) << " ms   " << snd_strerror (err);
    PTRACE (1, "ALSA\t" << msg);
    cerr << msg << endl;
  }
        
  if ((err = snd_pcm_hw_params (os_handle, hw_params)) < 0) {
    msg << "Cannot set parameters " <<      snd_strerror (err);
    PTRACE (1, "ALSA\t" << msg);
    cerr << msg << endl;
    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;

  snd_pcm_close (os_handle);
  os_handle = NULL;

  return TRUE;
}


BOOL PSoundChannelALSA::Write (const void *buf, PINDEX len)
{
  long r = 0;
  char *buf2 = (char *) buf;
  int pos = 0, max_try = 0;
 
  lastWriteCount = 0;
  PWaitAndSignal m(device_mutex);

  if (!isInitialised && !Setup(len) || !len || !os_handle)
    return FALSE;

  do {

      
    /* the number of frames to read is the buffer length 
       divided by the size of one frame */
    r = snd_pcm_writei (os_handle, (char *) &buf2 [pos], len / frameBytes);

    if (r > 0) {
      pos += r * frameBytes;
      len -= r * frameBytes;
      lastWriteCount += r * frameBytes;
    }
    else {
      if (r == -EPIPE) {    /* under-run */
        r = snd_pcm_prepare (os_handle);
        if (r < 0)
          PTRACE (1, "ALSA\tCould not prepare device: " << snd_strerror (r));
      } else if (r == -ESTRPIPE) {

        while ((r = snd_pcm_resume (os_handle)) == -EAGAIN)
          sleep(1);       /* wait until the suspend flag is released */
      
        if (r < 0) 
          snd_pcm_prepare (os_handle);
      }

      PTRACE (1, "ALSA\tCould not write " << max_try << " " << len << " " << r);
      max_try++;
    }  
  } while (len > 0 && max_try < 5);

  return TRUE;
}


BOOL PSoundChannelALSA::Read (void * buf, PINDEX len)
{
  long r = 0;

  char *buf2 = (char *) buf;
  int pos = 0, max_try = 0;

  lastReadCount = 0;
  PWaitAndSignal m(device_mutex);

  if (!isInitialised && !Setup(len) || !len || !os_handle)
    return FALSE;

  memset ((char *) buf, 0, len);
  
  do {

    /* the number of frames to read is the buffer length 
       divided by the size of one frame */
    r = snd_pcm_readi (os_handle, (char *) &buf2 [pos], len / frameBytes);
    if (r > 0) {
      pos += r * frameBytes;
      len -= r * frameBytes;
      lastReadCount += r * frameBytes;
    }
    else {
      if (r == -EPIPE) {    /* under-run */
        snd_pcm_prepare (os_handle);
      } 
      else if (r == -ESTRPIPE) {
        while ((r = snd_pcm_resume (os_handle)) == -EAGAIN)
          sleep(1);       /* wait until the suspend flag is released */
        if (r < 0) 
          snd_pcm_prepare (os_handle);
      }

      PTRACE (1, "ALSA\tCould not read");
      max_try++;
    }
  } while (len > 0 && max_try < 5);

 
  if (len != 0) {

    memset ((char *) &buf2 [pos], 0, len);
    lastReadCount += len;

    PTRACE (1, "ALSA\tRead Error, filling with zeros");
  }
  
  
  return TRUE;
}


BOOL PSoundChannelALSA::SetFormat (unsigned numChannels,
                                   unsigned sampleRate,
                                   unsigned bitsPerSample)
{
  if (!os_handle)
    return SetErrorValues(NotOpen, EBADF);

  /* check parameters */
  PAssert((bitsPerSample == 8) || (bitsPerSample == 16), PInvalidParameter);
  PAssert(numChannels >= 1 && numChannels <= 2, PInvalidParameter);

  mNumChannels   = numChannels;
  mSampleRate    = sampleRate;
  mBitsPerSample = bitsPerSample;
 
  /* mark this channel as uninitialised */
  isInitialised = FALSE;

  return TRUE;
}


unsigned PSoundChannelALSA::GetChannels()   const
{
  return mNumChannels;
}


unsigned PSoundChannelALSA::GetSampleRate() const
{
  return mSampleRate;
}


unsigned PSoundChannelALSA::GetSampleSize() const
{
  return mBitsPerSample;
}


BOOL PSoundChannelALSA::SetBuffers (PINDEX size, PINDEX count)
{
  storedPeriods = count;

  storedSize = size;

  return TRUE;
}


BOOL PSoundChannelALSA::GetBuffers(PINDEX & size, PINDEX & count)
{
  size = storedSize;
  count = storedPeriods;
  
  return FALSE;
}


BOOL PSoundChannelALSA::PlaySound(const PSound & sound, BOOL wait)
{
  if (!os_handle)
    return SetErrorValues(NotOpen, EBADF);

  if (!Write((const BYTE *)sound, sound.GetSize()))
    return FALSE;

  if (wait)
    return WaitForPlayCompletion();

  return TRUE;
}


BOOL PSoundChannelALSA::PlayFile(const PFilePath & filename, BOOL wait)
{
  BYTE buffer [512];
  
  if (!os_handle)
    return SetErrorValues(NotOpen, EBADF);

  PFile file (filename, PFile::ReadOnly);

  if (!file.IsOpen())
    return FALSE;

  for (;;) {

    if (!file.Read (buffer, 512))
      break;

    PINDEX len = file.GetLastReadCount();
    if (len == 0)
      break;
    if (!Write(buffer, len))
      break;
  }

  file.Close();

  if (wait)
    return WaitForPlayCompletion();

  return TRUE;
}


BOOL PSoundChannelALSA::HasPlayCompleted()
{
  if (!os_handle)
    return SetErrorValues(NotOpen, EBADF);

  return (snd_pcm_state (os_handle) != SND_PCM_STATE_RUNNING);
}


BOOL PSoundChannelALSA::WaitForPlayCompletion()
{
  if (!os_handle)
    return SetErrorValues(NotOpen, EBADF);

  snd_pcm_drain (os_handle);

  return TRUE;
}


BOOL PSoundChannelALSA::RecordSound(PSound & sound)
{
  return FALSE;
}


BOOL PSoundChannelALSA::RecordFile(const PFilePath & filename)
{
  return FALSE;
}


BOOL PSoundChannelALSA::StartRecording()
{
  return FALSE;
}


BOOL PSoundChannelALSA::IsRecordBufferFull()
{
  return TRUE;
}


BOOL PSoundChannelALSA::AreAllRecordBuffersFull()
{
  return TRUE;
}


BOOL PSoundChannelALSA::WaitForRecordBufferFull()
{
  return TRUE;
}


BOOL PSoundChannelALSA::WaitForAllRecordBuffersFull()
{
  return FALSE;
}


BOOL PSoundChannelALSA::Abort()
{
  int r = 0;

  if (!os_handle)
    return FALSE;

  if ((r = snd_pcm_drain (os_handle)) < 0) {
    PTRACE (1, "ALSA\tCannot abort" << snd_strerror (r));
    return FALSE;
  }
  else
    return TRUE;
}



BOOL PSoundChannelALSA::SetVolume (unsigned newVal)
{
  unsigned i = 0;

  return Volume (TRUE, newVal, i);
}


BOOL  PSoundChannelALSA::GetVolume(unsigned &devVol)
{
  return Volume (FALSE, 0, devVol);
}
  

BOOL PSoundChannelALSA::IsOpen () const
{
  return (os_handle != NULL);
}


BOOL PSoundChannelALSA::Volume (BOOL set, unsigned set_vol, unsigned &get_vol)
{
  int err = 0;
  snd_mixer_t *handle;
  snd_mixer_elem_t *elem;
  snd_mixer_selem_id_t *sid;

  const char *play_mix_name [] = { "PCM", "Master", "Speaker", NULL };
  const char *rec_mix_name [] = { "Capture", "Mic", NULL };
  PString card_name;

  long pmin = 0, pmax = 0;
  long int vol = 0;
  int i = 0;

  if (!os_handle)
    return FALSE;

  if (card_nr == -2)
    card_name = "default";
  else
    card_name = "hw:" + PString (card_nr);

  //allocate simple id
  snd_mixer_selem_id_alloca (&sid);

  //sets simple-mixer index and name
  snd_mixer_selem_id_set_index (sid, 0);

  if ((err = snd_mixer_open (&handle, 0)) < 0) {
    PTRACE (1, "alsa-control: mixer open error: " << snd_strerror (err));
    return FALSE;
  }

  if ((err = snd_mixer_attach (handle, card_name)) < 0) {
    PTRACE (1, "alsa-control: mixer attach " << card_name << " error: " << snd_strerror(err));
    snd_mixer_close(handle);
    return FALSE;
  }

  if ((err = snd_mixer_selem_register (handle, NULL, NULL)) < 0) {
    PTRACE (1, "alsa-control: mixer register error: " << snd_strerror(err));
    snd_mixer_close(handle);
    return FALSE;
  }

  err = snd_mixer_load(handle);
  if (err < 0) {
    PTRACE (1, "alsa-control: mixer load error: " << snd_strerror(err));
    snd_mixer_close(handle);
    return FALSE;
  }

  do {
    snd_mixer_selem_id_set_name (sid, (direction == Player)?play_mix_name[i]:rec_mix_name[i]);
    elem = snd_mixer_find_selem (handle, sid);
    i++;
  } while (!elem && ((direction == Player && play_mix_name[i] != NULL) || (direction == Recorder && rec_mix_name[i] != NULL)));

  if (!elem) {
    PTRACE (1, "alsa-control: unable to find simple control.");
    snd_mixer_close(handle);
    return FALSE;
  }

  if (set) {
    if (direction == Player) {
      
      snd_mixer_selem_get_playback_volume_range (elem, &pmin, &pmax);
      vol = (set_vol * (pmax?pmax:31)) / 100;
      snd_mixer_selem_set_playback_volume_all (elem, vol);
    }
    else {
      
      snd_mixer_selem_get_capture_volume_range (elem, &pmin, &pmax);
      vol = (set_vol * (pmax?pmax:31)) / 100;
      snd_mixer_selem_set_capture_volume_all (elem, vol);
    }
    PTRACE (4, "Set volume to " << vol);
  }
  else {

    if (direction == Player) {
      snd_mixer_selem_get_playback_volume_range (elem, &pmin, &pmax);
      snd_mixer_selem_get_playback_volume (elem, SND_MIXER_SCHN_FRONT_LEFT, &vol);
    }
    else {
      snd_mixer_selem_get_capture_volume_range (elem, &pmin, &pmax);
      snd_mixer_selem_get_capture_volume (elem, SND_MIXER_SCHN_FRONT_LEFT, &vol); 
    }
    get_vol = (vol * 100) / (pmax?pmax:31);

    PTRACE (4, "Got volume " << vol);
  }

  snd_mixer_close(handle);

  return TRUE;
}

⌨️ 快捷键说明

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