Logo Search packages:      
Sourcecode: ecasound2.2 version File versions

audioio_alsa.cpp

// ------------------------------------------------------------------------
// audioio-alsa.cpp: ALSA 0.9.x PCM input and output.
// Copyright (C) 1999-2004 Kai Vehmanen, Jeremy Hall 
//
// Attributes:
//     eca-style-version: 3
//
// References:
//     http://alsa-project.org/
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
// 
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
// ------------------------------------------------------------------------

#include <string>
#include <cstring>
#include <cstdio>
#include <dlfcn.h>
#include <unistd.h>
#include <errno.h>

#include <alsa/version.h>
  
/* error if alsa-lib older than 0.9.0, use old API if 0.9.0->0.9.8, 
   otherwise do nothing */
#if SND_LIB_MAJOR < 1 && SND_LIB_MINOR == 9
#if SND_LIB_SUBMINOR > 0 || SND_LIB_EXTRAVER >= 100004
#define ALSA_PCM_NEW_HW_PARAMS_API
#define ALSA_PCM_NEW_SW_PARAMS_API
#else
#error "Unable to compile ALSA-support. Alsa-lib version 0.9.0rc4 or newer is required!"
#endif
#endif

#include <alsa/asoundlib.h>

#include <kvu_dbc.h>
#include <kvu_message_item.h>
#include <kvu_numtostr.h>
#include <kvu_utils.h>

#include "samplebuffer.h"
#include "audioio-device.h"
#include "audioio_alsa.h"

#include "eca-version.h"
#include "eca-error.h"
#include "eca-logger.h"

using std::cerr;
using std::endl;

#ifndef timersub
#define     timersub(a, b, result) \
do { \
      (result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \
      (result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \
      if ((result)->tv_usec < 0) { \
            --(result)->tv_sec; \
            (result)->tv_usec += 1000000; \
      } \
} while (0)
#endif

const string AUDIO_IO_ALSA_PCM::default_pcm_device_rep = "default";

AUDIO_IO_ALSA_PCM::AUDIO_IO_ALSA_PCM (int card, 
                              int device, 
                              int subdevice) 
  : AUDIO_IO_DEVICE()
{
  // ECA_LOG_MSG(ECA_LOGGER::system_objects, "construct");
  card_number_rep = card;
  device_number_rep = device;
  subdevice_number_rep = subdevice;
  trigger_request_rep = false;
  overruns_rep = underruns_rep = 0;
  nbufs_repp = 0;
  allocate_structs();
}

AUDIO_IO_ALSA_PCM::~AUDIO_IO_ALSA_PCM(void)
{
  if (is_open() == true && is_running()) stop();

  if (is_open() == true) {
    close();
  }

  if (io_mode() != io_read) {
    if (underruns_rep != 0) {
      cerr << "WARNING! While writing to ALSA-pcm device ";
      cerr << "C" << card_number_rep << "D" << device_number_rep;
      cerr << ", there were " << underruns_rep << " underruns.\n";
    }
  }
  else {
    if (overruns_rep != 0) {
      cerr << "WARNING! While reading from ALSA-pcm device ";
      cerr << "C" << card_number_rep << "D" << device_number_rep;
      cerr << ", there were " << overruns_rep << " overruns.\n";
    }
  }

  if (nbufs_repp != 0)
    delete nbufs_repp;

  deallocate_structs();
}

00122 AUDIO_IO_ALSA_PCM* AUDIO_IO_ALSA_PCM::clone(void) const
{
  AUDIO_IO_ALSA_PCM* target = new AUDIO_IO_ALSA_PCM();
  for(int n = 0; n < number_of_params(); n++) {
    target->set_parameter(n + 1, get_parameter(n + 1));
  }
  return target;
}

void AUDIO_IO_ALSA_PCM::allocate_structs(void)
{
  int err = snd_pcm_hw_params_malloc(&pcm_hw_params_repp);
  DBC_CHECK(!err);

  err = snd_pcm_sw_params_malloc(&pcm_sw_params_repp);
  DBC_CHECK(!err);
}

void AUDIO_IO_ALSA_PCM::deallocate_structs(void)
{
  snd_pcm_hw_params_free(pcm_hw_params_repp);
  snd_pcm_sw_params_free(pcm_sw_params_repp);
}


void AUDIO_IO_ALSA_PCM::open_device(void)
{
  ECA_LOG_MSG(ECA_LOGGER::system_objects, "open");

  // -------------------------------------------------------------------
  // Device name initialization

  string device_name = pcm_device_name();

  // -------------------------------------------------------------------
  // Open devices

  int err;
  if (io_mode() == io_read) {
    pcm_stream_rep = SND_PCM_STREAM_CAPTURE;
    err = snd_pcm_open(&audio_fd_repp, 
                   (char*)device_name.c_str(),
                   pcm_stream_rep,
                   SND_PCM_NONBLOCK);

    if (err < 0) {
      throw(SETUP_ERROR(SETUP_ERROR::io_mode, "AUDIOIO-ALSA: Unable to open ALSA--device for capture; error: " + 
                  string(snd_strerror(err))));
    }
  }    
  else if (io_mode() == io_write) {
    pcm_stream_rep = SND_PCM_STREAM_PLAYBACK;
    err = snd_pcm_open(&audio_fd_repp, 
                   (char*)device_name.c_str(),
                   pcm_stream_rep,
                   SND_PCM_NONBLOCK);
    
    if (err < 0) {
      throw(SETUP_ERROR(SETUP_ERROR::io_mode, "AUDIOIO-ALSA: Unable to open ALSA-device for playback; error: " +  
                  string(snd_strerror(err))));
    }
  }
  else if (io_mode() == io_readwrite) {
    throw(SETUP_ERROR(SETUP_ERROR::io_mode, "AUDIOIO-ALSA: Simultaneous input/output not supported."));
  }

  // -------------------------------------------------------------------
  // enables blocking mode
  snd_pcm_nonblock(audio_fd_repp, 0);
}

void AUDIO_IO_ALSA_PCM::set_audio_format_params(void)
{
  ECA_LOG_MSG(ECA_LOGGER::system_objects, "set_audio_format_params");
  format_rep = SND_PCM_FORMAT_LAST;
  switch(sample_format()) 
    {
    case ECA_AUDIO_FORMAT::sfmt_u8:  { format_rep = SND_PCM_FORMAT_U8; break; }
    case ECA_AUDIO_FORMAT::sfmt_s8:  { format_rep = SND_PCM_FORMAT_S8; break; }
    case ECA_AUDIO_FORMAT::sfmt_s16_le:  { format_rep = SND_PCM_FORMAT_S16_LE; break; }
    case ECA_AUDIO_FORMAT::sfmt_s16_be:  { format_rep = SND_PCM_FORMAT_S16_BE; break; }
    case ECA_AUDIO_FORMAT::sfmt_s24_le:  { format_rep = SND_PCM_FORMAT_S24_3LE; break; }
    case ECA_AUDIO_FORMAT::sfmt_s24_be:  { format_rep = SND_PCM_FORMAT_S24_3BE; break; }
    case ECA_AUDIO_FORMAT::sfmt_s32_le:  { format_rep = SND_PCM_FORMAT_S32_LE; break; }
    case ECA_AUDIO_FORMAT::sfmt_s32_be:  { format_rep = SND_PCM_FORMAT_S32_BE; break; }
      
    default:
      {
      throw(SETUP_ERROR(SETUP_ERROR::sample_format, "AUDIOIO-ALSA: Error when setting audio format not supported (1)"));
      }
    }
}

void AUDIO_IO_ALSA_PCM::print_pcm_info(void)
{
}

void AUDIO_IO_ALSA_PCM::fill_and_set_hw_params(void)
{
  ECA_LOG_MSG(ECA_LOGGER::system_objects, "fill_and_set_hw_params");

  /* 1. create one param combination */
  int err = snd_pcm_hw_params_any(audio_fd_repp, pcm_hw_params_repp);
  if (err < 0) throw(SETUP_ERROR(SETUP_ERROR::unexpected, "AUDIOIO-ALSA: Error when setting up hwparams/any: " + string(snd_strerror(err))));
  
  /* 2. set interleaving mode */
  if (interleaved_channels() == true)
    ECA_LOG_MSG(ECA_LOGGER::user_objects, "Using interleaved stream format.");
  else
    ECA_LOG_MSG(ECA_LOGGER::user_objects, "Using noninterleaved stream format.");

  if (interleaved_channels() == true)
    err = snd_pcm_hw_params_set_access(audio_fd_repp, pcm_hw_params_repp,
                               SND_PCM_ACCESS_RW_INTERLEAVED);
  else
    err = snd_pcm_hw_params_set_access(audio_fd_repp, pcm_hw_params_repp,
                               SND_PCM_ACCESS_RW_NONINTERLEAVED);
  if (err < 0) throw(SETUP_ERROR(SETUP_ERROR::unexpected, "AUDIOIO-ALSA: Error when setting up hwparams/access: " + string(snd_strerror(err))));

  /* 3. set sample format */
  err = snd_pcm_hw_params_set_format(audio_fd_repp, 
                             pcm_hw_params_repp, 
                             format_rep);
  if (err < 0) throw(SETUP_ERROR(SETUP_ERROR::sample_format, "AUDIOIO-ALSA: Audio format not supported."));

  /* 4. set channel count */
  err = snd_pcm_hw_params_set_channels(audio_fd_repp, 
                               pcm_hw_params_repp, 
                               channels());
  if (err < 0) throw(SETUP_ERROR(SETUP_ERROR::channels, "AUDIOIO-ALSA: Channel count " +
                         kvu_numtostr(channels()) + " is out of range!"));

  /* 5. set sampling rate */
  unsigned int uivalue = samples_per_second();
  err = snd_pcm_hw_params_set_rate_near(audio_fd_repp, 
                              pcm_hw_params_repp,
                              &uivalue, 
                              0);
  if (err < 0) throw(SETUP_ERROR(SETUP_ERROR::sample_rate, "AUDIOIO-ALSA: Sample rate " +
                         kvu_numtostr(samples_per_second()) + " is out of range!"));

  /* 6. create buffers for noninterleaved i/o */
  if (interleaved_channels() != true) {
    if (nbufs_repp == 0)
      nbufs_repp = new unsigned char* [channels()];
  }

  snd_pcm_uframes_t fvalue = buffersize();
  /* 7. sets period size (period = one fragment) */
  err = snd_pcm_hw_params_set_period_size_near(audio_fd_repp, 
                                     pcm_hw_params_repp,
                                     &fvalue, 
                                     0);
  if (err < 0) throw(SETUP_ERROR(SETUP_ERROR::buffersize, "AUDIOIO-ALSA: buffersize " +
                         kvu_numtostr(buffersize()) + " is out of range!"));

  /* 8. sets buffer size */
  if (max_buffers() == true) {
      snd_pcm_uframes_t bufferreq = buffersize() * 1024;
      err = snd_pcm_hw_params_set_buffer_size_near(audio_fd_repp, 
                                       pcm_hw_params_repp,
                                       &bufferreq);
    if (err < 0) throw(SETUP_ERROR(SETUP_ERROR::unexpected,
                           "AUDIOIO-ALSA: Error when setting up hwparams/btime (1): " + string(snd_strerror(err))));
  }
  else {
    snd_pcm_uframes_t bufferreq = buffersize() * 3;
    err = snd_pcm_hw_params_set_buffer_size_near(audio_fd_repp, 
                                     pcm_hw_params_repp,
                                     &bufferreq);
    if (err < 0) throw(SETUP_ERROR(SETUP_ERROR::unexpected,
                           "AUDIOIO-ALSA: Error when setting up hwparams/btime (2): " + string(snd_strerror(err))));
  }
   
  /* 9. print debug information */
  snd_pcm_hw_params_get_period_time(pcm_hw_params_repp, &uivalue, 0);
  ECA_LOG_MSG(ECA_LOGGER::system_objects, "period time set to " + kvu_numtostr(uivalue) + " usecs.");
  
  snd_pcm_hw_params_get_period_size(pcm_hw_params_repp, &period_size_rep, 0);
  ECA_LOG_MSG(ECA_LOGGER::system_objects, "period time set to " + kvu_numtostr(period_size_rep) + " frames.");
  if (period_size_rep != static_cast<unsigned int>(buffersize())) {
    ECA_LOG_MSG(ECA_LOGGER::info, 
            "Warning! Period-size differs from current client buffersize.");
  }

  snd_pcm_hw_params_get_buffer_time(pcm_hw_params_repp, &uivalue, 0);
  ECA_LOG_MSG(ECA_LOGGER::system_objects, "buffer time set to " + kvu_numtostr(uivalue) + " usecs.");

  snd_pcm_hw_params_get_buffer_size(pcm_hw_params_repp, &buffer_size_rep);
  ECA_LOG_MSG(ECA_LOGGER::system_objects, "buffer time set to " + kvu_numtostr(buffer_size_rep) + " frames.");
  ECA_LOG_MSG(ECA_LOGGER::system_objects, "total latency is " + kvu_numtostr(latency()) + " frames.");


  /* 9. all set, now active hw params */
  err = snd_pcm_hw_params(audio_fd_repp, pcm_hw_params_repp);
  if (err < 0) {
    throw(SETUP_ERROR(SETUP_ERROR::unexpected, "AUDIOIO-ALSA: Error when setting up hwparams: " + string(snd_strerror(err))));
  }
}

void AUDIO_IO_ALSA_PCM::fill_and_set_sw_params(void)
{
  ECA_LOG_MSG(ECA_LOGGER::system_objects, "fill_and_set_sw_params");

  /* 1. get current params */
  snd_pcm_sw_params_current(audio_fd_repp, pcm_sw_params_repp);

  /* 2. set start threshold (should be big enough so that processing 
        won't start until a explicit snd_pcm_start() is issued */
  int err = snd_pcm_sw_params_set_start_threshold(audio_fd_repp, 
                                      pcm_sw_params_repp,
                                      buffer_size_rep * 2);
  if (err < 0) throw(SETUP_ERROR(SETUP_ERROR::unexpected, "AUDIOIO-ALSA: Error when setting up pcm_sw_params/start_threshold: " + string(snd_strerror(err))));
  
  /* 3. set align to one frame (like the OSS-emulation layer) */
  err = snd_pcm_sw_params_set_xfer_align(audio_fd_repp,
                               pcm_sw_params_repp,
                               1);
  if (err < 0) throw(SETUP_ERROR(SETUP_ERROR::unexpected, "AUDIOIO-ALSA: Error when setting up pcm_sw_params_repp/xfer_align: " + string(snd_strerror(err))));
  
  /* 4. activate params */
  err = snd_pcm_sw_params(audio_fd_repp, pcm_sw_params_repp);
  if (err < 0) throw(SETUP_ERROR(SETUP_ERROR::unexpected, "AUDIOIO-ALSA: Error when setting up pcm_sw_params_repp: " + string(snd_strerror(err))));
}

00347 void AUDIO_IO_ALSA_PCM::open(void) throw(AUDIO_IO::SETUP_ERROR&)
{
  open_device();
  set_audio_format_params();
  fill_and_set_hw_params();
  print_pcm_info();
  fill_and_set_sw_params();

  AUDIO_IO_DEVICE::open();
}

00358 void AUDIO_IO_ALSA_PCM::stop(void)
{
  snd_pcm_drop(audio_fd_repp); /* non-blocking */
  // snd_pcm_drain(audio_fd_repp); /* blocking */
  
  ECA_LOG_MSG(ECA_LOGGER::user_objects, "stop - " + label() + ".");

  AUDIO_IO_DEVICE::stop();
}

00368 void AUDIO_IO_ALSA_PCM::close(void)
{
  ECA_LOG_MSG(ECA_LOGGER::user_objects, "close - " + label() + ".");

  if (is_prepared() == true && is_running() == true) stop();
  snd_pcm_close(audio_fd_repp);

  AUDIO_IO_DEVICE::close();
}

00378 void AUDIO_IO_ALSA_PCM::prepare(void)
{
  ECA_LOG_MSG(ECA_LOGGER::user_objects, "prepare - " + label() + ".");

  int err = snd_pcm_prepare(audio_fd_repp);
  if (err < 0)
    ECA_LOG_MSG(ECA_LOGGER::info, "Error when preparing stream: " + string(snd_strerror(err)));

  AUDIO_IO_DEVICE::prepare();
}

00389 void AUDIO_IO_ALSA_PCM::start(void)
{
  ECA_LOG_MSG(ECA_LOGGER::user_objects, "start - " + label() + ".");
  snd_pcm_start(audio_fd_repp);

  AUDIO_IO_DEVICE::start();
}

00397 long int AUDIO_IO_ALSA_PCM::read_samples(void* target_buffer, 
                                 long int samples)
{
  // --
  DBC_REQUIRE(samples <= buffersize());
  // --

  long int realsamples = 0;

  if (interleaved_channels() == true) {
    realsamples = snd_pcm_readi(audio_fd_repp, target_buffer,
                        buffersize());
    if (realsamples < 0) {
      /* Note! ALSA versions <=0.9.1 sometimes return -EIO in xrun-state;
       *       EPIPE=xrun, ESTRPIPE=xrun) */
      if (realsamples == -EPIPE || realsamples == -ESTRPIPE || realsamples == -EIO) {
      if (ignore_xruns() == true) {
        handle_xrun_capture();
        realsamples = snd_pcm_readi(audio_fd_repp, target_buffer,
                              buffersize());
        if (realsamples < 0) realsamples = 0;
      }
      else {
        cerr << "Overrun! Stopping operation!" << endl;
        stop();
        close();
      }
      }
      else {
      cerr << "Read error (" << realsamples << ")! Stopping operation." << endl;
      stop();
      close();
      }
    }
  }
  else {
    unsigned char* ptr_to_channel = reinterpret_cast<unsigned char*>(target_buffer);
    for (int channel = 0; channel < channels(); channel++) {
      nbufs_repp[channel] = ptr_to_channel;
      ptr_to_channel += samples * sample_size();
    }
    realsamples = snd_pcm_readn(audio_fd_repp, reinterpret_cast<void**>(target_buffer), buffersize());
    if (realsamples < 0) {
      /* Note! ALSA versions <=0.9.1 sometimes return -EIO in xrun-state;
       *       EPIPE=xrun, ESTRPIPE=xrun) */
      if (realsamples == -EPIPE || realsamples == -ESTRPIPE || realsamples == -EIO) {
      if (ignore_xruns() == true) {
        handle_xrun_capture();
        realsamples = snd_pcm_readn(audio_fd_repp, reinterpret_cast<void**>(target_buffer), buffersize());
        if (realsamples < 0) realsamples = 0;
      }
      else {
        cerr << "Overrun! Stopping operation!" << endl;
        stop();
        close();
      }
      }
      else {
      cerr << "Read error! Stopping operation." << endl;
      stop();
      close();
      }
    }
  }
  return realsamples;
}

void AUDIO_IO_ALSA_PCM::handle_xrun_capture(void)
{
  snd_pcm_status_t *status;
  snd_pcm_status_alloca(&status);

  int res = snd_pcm_status(audio_fd_repp, status);
  if (res >= 0) {
    snd_pcm_state_t state = snd_pcm_status_get_state(status);
    if (state == SND_PCM_STATE_XRUN) {
      struct timeval now, diff, tstamp;
      gettimeofday(&now, 0);
      snd_pcm_status_get_trigger_tstamp(status, &tstamp);
      timersub(&now, &tstamp, &diff);

      cerr << "warning! playback overrun - samples lost! " 
            << " Break was at least " << kvu_numtostr(diff.tv_sec *
                                            1000 +
                                            diff.tv_usec /
                                            1000.0) 
            << " ms long." << endl;

      overruns_rep++;
      stop();
      prepare();
      start();
    }
    else if (state == SND_PCM_STATE_SUSPENDED) {
      cerr << "Device suspended! Stopping operation!" << endl;
      stop();
      close();
    }
    else {
      cerr << "Unknown device state '" 
         << static_cast<int>(state) << "'" << endl;
    }
  }
  else {
    ECA_LOG_MSG(ECA_LOGGER::info, "snd_pcm_status() failed!");
  }
}

00505 void AUDIO_IO_ALSA_PCM::write_samples(void* target_buffer, long int samples)
{
  if (trigger_request_rep == true) {
    trigger_request_rep = false;
    start();
  }

  if (interleaved_channels() == true) {
    long int count = snd_pcm_writei(audio_fd_repp, target_buffer, samples);
    if (count < 0) {
      /* Note! ALSA versions <=0.9.1 sometimes return -EIO in xrun-state;
       *       EPIPE=xrun, ESTRPIPE=xrun) */
      DBC_CHECK(count != -EINTR);
      if (count == -EPIPE || count == -EIO || count == -ESTRPIPE) {
      if (ignore_xruns() == true) {
        handle_xrun_playback();
        if (snd_pcm_writei(audio_fd_repp, target_buffer, samples) < 0) 
          cerr << "Xrun handling failed!" << endl;
        trigger_request_rep = true;
      }
      else {
        cerr << "Underrun! Stopping operation!" << endl;
        stop();
        close();
      }
      }
      else {
      cerr << "Write error! Stopping operation (" << count << ")." << endl;
      stop();
      close();
      }
    }
  }
  else {
    unsigned char* ptr_to_channel = reinterpret_cast<unsigned char*>(target_buffer);
    for (int channel = 0; channel < channels(); channel++) {
      nbufs_repp[channel] = ptr_to_channel;
      // cerr << "Pointer to channel " << channel << ": " << reinterpret_cast<void*>(nbufs_repp[channel]) << endl;
      ptr_to_channel += samples * sample_size();
      // cerr << "Advancing pointer count by " << samples * sample_size() << " to " << reinterpret_cast<void*>(ptr_to_channel) << endl;
    }
    long int count =  snd_pcm_writen(audio_fd_repp,
                               reinterpret_cast<void**>(nbufs_repp), 
                               samples);
    if (count < 0) {
      /* Note! ALSA versions <=0.9.1 sometimes return -EIO in xrun-state;
       *       EPIPE=xrun, ESTRPIPE=xrun) */
      DBC_CHECK(count != -EINTR);
      if (count == -EPIPE || count == -EIO || count == -ESTRPIPE) {
      if (ignore_xruns() == true) {
        handle_xrun_playback();
        snd_pcm_writen(audio_fd_repp,
                     reinterpret_cast<void**>(nbufs_repp),
                     samples);
        trigger_request_rep = true;
      }
      else {
        cerr << "Underrun! Stopping operation!" << endl;
        stop();
        close();
      }
      }
      else {
      cerr << "Write  error! Stopping operation." << endl;
      stop();
      close();
      }
    }
  }
}

void AUDIO_IO_ALSA_PCM::handle_xrun_playback(void)
{
  snd_pcm_status_t *status;
  snd_pcm_status_alloca(&status);

  int res = snd_pcm_status(audio_fd_repp, status);
  if (res >= 0) {
    snd_pcm_state_t state = snd_pcm_status_get_state(status);
    if (state == SND_PCM_STATE_XRUN) {
      struct timeval now, diff, tstamp;
      gettimeofday(&now, 0);
      snd_pcm_status_get_trigger_tstamp(status, &tstamp);
      timersub(&now, &tstamp, &diff);
      
      cerr << "warning! playback underrun - samples lost! " 
            << " Break was at least " << kvu_numtostr(diff.tv_sec *
                                            1000 +
                                            diff.tv_usec /
                                            1000.0) 
            << " ms long." << endl;
      underruns_rep++;
      stop();
      prepare();
      trigger_request_rep = true;
    }
    else if (state == SND_PCM_STATE_SUSPENDED) {
      cerr << "Device suspended! Stopping operation!" << endl;
      stop();
      close();
    }
    else {
      cerr << "Unknown device state '" 
         << static_cast<int>(state) << "'" << endl;
    }
  }
  else {
    ECA_LOG_MSG(ECA_LOGGER::info, "snd_pcm_status() failed!");
  }
}

00616 long int AUDIO_IO_ALSA_PCM::delay(void) const
{
  snd_pcm_sframes_t delay = 0;

  if (is_running() == true) {
    if (snd_pcm_delay(audio_fd_repp, &delay) != 0) {
      delay = 0;
    }
  }

  return static_cast<long int>(delay);
}

00629 void AUDIO_IO_ALSA_PCM::set_parameter(int param, 
                              string value)
{
  switch (param) {
  case 1: 
    set_label(value);
    if (label().find("alsaplugin") != string::npos) {
      using_plugin_rep = true;
    }
    break;

  case 2: 
    card_number_rep = atoi(value.c_str());
    break;

  case 3: 
    device_number_rep = atoi(value.c_str());
    break;

  case 4: 
    subdevice_number_rep = atoi(value.c_str());
    break;
  }

  if (using_plugin_rep)
    pcm_device_name_rep = 
      string("plughw:") + 
      kvu_numtostr(card_number_rep) +
      "," +
      kvu_numtostr(device_number_rep) +
      "," +
      kvu_numtostr(subdevice_number_rep);
  else
    pcm_device_name_rep = 
      string("hw:") + 
      kvu_numtostr(card_number_rep) +
      "," +
      kvu_numtostr(device_number_rep) +
      "," +
      kvu_numtostr(subdevice_number_rep);
}

00671 string AUDIO_IO_ALSA_PCM::get_parameter(int param) const
{
  switch (param) {
  case 1: 
    return label();

  case 2: 
    return kvu_numtostr(card_number_rep);

  case 3: 
    return kvu_numtostr(device_number_rep);

  case 4: 
    return kvu_numtostr(subdevice_number_rep);
  }
  return "";
}

void AUDIO_IO_ALSA_PCM::set_pcm_device_name(const string& n)
{ 
  if (n.size() > 0)
    pcm_device_name_rep = n; 
  else
    pcm_device_name_rep = default_pcm_device_rep;
}

Generated by  Doxygen 1.6.0   Back to index