示例#1
0
文件: sound.c 项目: mmaruska/emacs
static void
alsa_open (struct sound_device *sd)
{
  const char *file;
  struct alsa_params *p;
  int err;

  /* Open the sound device.  Default is "default".  */
  if (sd->file)
    file = sd->file;
  else
    file = DEFAULT_ALSA_SOUND_DEVICE;

  p = xmalloc (sizeof (*p));
  p->handle = NULL;
  p->hwparams = NULL;
  p->swparams = NULL;

  sd->fd = -1;
  sd->data = p;


  err = snd_pcm_open (&p->handle, file, SND_PCM_STREAM_PLAYBACK, 0);
  if (err < 0)
    alsa_sound_perror (file, err);
}
示例#2
0
文件: sound.c 项目: mmaruska/emacs
static void
alsa_write (struct sound_device *sd, const char *buffer, int nbytes)
{
  struct alsa_params *p = (struct alsa_params *) sd->data;

  /* The the third parameter to snd_pcm_writei is frames, not bytes. */
  int fact = snd_pcm_format_size (sd->format, 1) * sd->channels;
  int nwritten = 0;
  int err;

  while (nwritten < nbytes)
    {
      snd_pcm_uframes_t frames = (nbytes - nwritten)/fact;
      if (frames == 0) break;

      err = snd_pcm_writei (p->handle, buffer + nwritten, frames);
      if (err < 0)
        {
          if (err == -EPIPE)
            {	/* under-run */
              err = snd_pcm_prepare (p->handle);
              if (err < 0)
                alsa_sound_perror ("Can't recover from underrun, prepare failed",
                                   err);
            }
          else if (err == -ESTRPIPE)
            {
              while ((err = snd_pcm_resume (p->handle)) == -EAGAIN)
                sleep(1);	/* wait until the suspend flag is released */
              if (err < 0)
                {
                  err = snd_pcm_prepare (p->handle);
                  if (err < 0)
                    alsa_sound_perror ("Can't recover from suspend, "
                                       "prepare failed",
                                       err);
                }
            }
          else
            alsa_sound_perror ("Error writing to sound device", err);

        }
      else
        nwritten += err * fact;
    }
}
示例#3
0
static void
alsa_open (struct sound_device *sd)
{
  /* Open the sound device.  Default is "default".  */
  struct alsa_params *p = xmalloc (sizeof *p);
  char const *file = string_default (sd->file, DEFAULT_ALSA_SOUND_DEVICE);
  int err;

  p->handle = NULL;
  p->hwparams = NULL;
  p->swparams = NULL;

  sd->fd = -1;
  sd->data = p;


  err = snd_pcm_open (&p->handle, file, SND_PCM_STREAM_PLAYBACK, 0);
  if (err < 0)
    alsa_sound_perror (file, err);
}
示例#4
0
文件: sound.c 项目: mmaruska/emacs
static void
alsa_configure (struct sound_device *sd)
{
  int val, err, dir;
  unsigned uval;
  struct alsa_params *p = (struct alsa_params *) sd->data;
  snd_pcm_uframes_t buffer_size;

  xassert (p->handle != 0);

  err = snd_pcm_hw_params_malloc (&p->hwparams);
  if (err < 0)
    alsa_sound_perror ("Could not allocate hardware parameter structure", err);

  err = snd_pcm_sw_params_malloc (&p->swparams);
  if (err < 0)
    alsa_sound_perror ("Could not allocate software parameter structure", err);

  err = snd_pcm_hw_params_any (p->handle, p->hwparams);
  if (err < 0)
    alsa_sound_perror ("Could not initialize hardware parameter structure", err);

  err = snd_pcm_hw_params_set_access (p->handle, p->hwparams,
                                      SND_PCM_ACCESS_RW_INTERLEAVED);
  if (err < 0)
    alsa_sound_perror ("Could not set access type", err);

  val = sd->format;
  err = snd_pcm_hw_params_set_format (p->handle, p->hwparams, val);
  if (err < 0)
    alsa_sound_perror ("Could not set sound format", err);

  uval = sd->sample_rate;
  err = snd_pcm_hw_params_set_rate_near (p->handle, p->hwparams, &uval, 0);
  if (err < 0)
    alsa_sound_perror ("Could not set sample rate", err);

  val = sd->channels;
  err = snd_pcm_hw_params_set_channels (p->handle, p->hwparams, val);
  if (err < 0)
    alsa_sound_perror ("Could not set channel count", err);

  err = snd_pcm_hw_params (p->handle, p->hwparams);
  if (err < 0)
    alsa_sound_perror ("Could not set parameters", err);


  err = snd_pcm_hw_params_get_period_size (p->hwparams, &p->period_size, &dir);
  if (err < 0)
    alsa_sound_perror ("Unable to get period size for playback", err);

  err = snd_pcm_hw_params_get_buffer_size (p->hwparams, &buffer_size);
  if (err < 0)
    alsa_sound_perror("Unable to get buffer size for playback", err);

  err = snd_pcm_sw_params_current (p->handle, p->swparams);
  if (err < 0)
    alsa_sound_perror ("Unable to determine current swparams for playback",
                       err);

  /* Start the transfer when the buffer is almost full */
  err = snd_pcm_sw_params_set_start_threshold (p->handle, p->swparams,
                                               (buffer_size / p->period_size)
                                               * p->period_size);
  if (err < 0)
    alsa_sound_perror ("Unable to set start threshold mode for playback", err);

  /* Allow the transfer when at least period_size samples can be processed */
  err = snd_pcm_sw_params_set_avail_min (p->handle, p->swparams, p->period_size);
  if (err < 0)
    alsa_sound_perror ("Unable to set avail min for playback", err);

  err = snd_pcm_sw_params (p->handle, p->swparams);
  if (err < 0)
    alsa_sound_perror ("Unable to set sw params for playback\n", err);

  snd_pcm_hw_params_free (p->hwparams);
  p->hwparams = NULL;
  snd_pcm_sw_params_free (p->swparams);
  p->swparams = NULL;

  err = snd_pcm_prepare (p->handle);
  if (err < 0)
    alsa_sound_perror ("Could not prepare audio interface for use", err);

  if (sd->volume > 0)
    {
      int chn;
      snd_mixer_t *handle;
      snd_mixer_elem_t *e;
      const char *file = sd->file ? sd->file : DEFAULT_ALSA_SOUND_DEVICE;

      if (snd_mixer_open (&handle, 0) >= 0)
        {
          if (snd_mixer_attach (handle, file) >= 0
              && snd_mixer_load (handle) >= 0
              && snd_mixer_selem_register (handle, NULL, NULL) >= 0)
            for (e = snd_mixer_first_elem (handle);
                 e;
                 e = snd_mixer_elem_next (e))
              {
                if (snd_mixer_selem_has_playback_volume (e))
                  {
                    long pmin, pmax, vol;
                    snd_mixer_selem_get_playback_volume_range (e, &pmin, &pmax);
                    vol = pmin + (sd->volume * (pmax - pmin)) / 100;

                    for (chn = 0; chn <= SND_MIXER_SCHN_LAST; chn++)
                      snd_mixer_selem_set_playback_volume (e, chn, vol);
                  }
              }
          snd_mixer_close(handle);
        }
    }
}