All of lore.kernel.org
 help / color / mirror / Atom feed
From: Guilherme <grlongo.ireland@gmail.com>
To: alsa-devel@alsa-project.org
Subject: busy device issue when it is not busy!
Date: Mon, 15 Jun 2009 02:38:56 -0300	[thread overview]
Message-ID: <4A35DE70.7000306@gmail.com> (raw)
In-Reply-To: <4A35D498.2000005@gmail.com>

Mates...

I am running a simple app that I found called pcm.c and I can't get 
through with that.  It creates  and send  simple sine wave to the speakers!

When I run the app I get the following error:

guilherme@lap:/home/guilherme/Experimentos# ./PCM
Playback device is plughw:0,0
Stream parameters are 44100Hz, S16_LE, 1 channels
sine wave rate is 0 0.0000Hz
Using transfer method: write
Playback open error: Device or resource busy

Every application I start playbacks the sound without a problem. Is 
there any special conf I should do to free the Device?

Here is the code:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sched.h>
#include <errno.h>
#include <getopt.h>
#include <alsa/asoundlib.h>
#include <sys/time.h>
#include <math.h>

static char *device = "plughw:0,0";                    //playback device 
aplay -l
static snd_pcm_format_t format = SND_PCM_FORMAT_S16;   //sample format 
unsigned 16 bit endian
static unsigned int rate = 44100;                      //stream rate
static unsigned int channels = 1;                       //contagem dos 
canais
static unsigned int buffer_time = 500000;              //ring buffer 
length on us
static unsigned int period_time = 100000;              //period time in us
static double freq = 400;                              // frequencia da 
senóide em Hz
static int verbose = 0;                                //verbose flag
static int resample = 1;                               //abilitar 
alsa-lib resampling
static int period_event = 0;                           // produz um 
event pool a cada periodo

static snd_pcm_sframes_t buffer_size;                  //quantidade de 
buffers frames
static snd_pcm_sframes_t period_size;                  //quantidade de 
periods frames
static snd_output_t *output = NULL;                    //ALSA usa esse 
ponteiro para lidar com output objects


static void generate_sine(const snd_pcm_channel_area_t *areas,
                                          snd_pcm_uframes_t offset,
                                          int count, double *_phase)
{
        static double max_phase = 2. * M_PI;
        double phase = *_phase;
        double step = max_phase*freq / (double)rate;
        double res;
        unsigned char *samples[channels], *tmp;
        int steps[channels];
        unsigned int chn, byte;
       
        union {
                int i;
                unsigned char c[4];
        } ires;
        unsigned int maxval = (1 << (snd_pcm_format_width(format) - 1)) - 1;
        int bps = snd_pcm_format_width(format) / 8; //bits per sample
       
        /*verificar e preparar o conteúdo das areas*/
        for (chn = 0; chn < channels; chn++) {
            if ((areas[chn].first % 8) != 0) {
                    printf("areas[%i].first == %i, abortando...\n", chn, 
areas[chn].first);
                    exit(EXIT_FAILURE);
            }
            //pega endereço e offset da area
            samples[chn] = /*(signed short *)*/(((unsigned char 
*)areas[chn].addr) + (areas[chn].first / 8));
           
         if ((areas[chn].step % 16) != 0) {
                printf("areas[%i].step == %i, aborting...\n", chn, 
areas[chn].step);
                exit(EXIT_FAILURE);
         }
           
                steps[chn] = areas[chn].step / 8;
                samples[chn] += offset * steps[chn];
        }
       
        //completa os channels da area
        while(count-- > 0) {
            res = sin(phase) * maxval;
            ires.i = res;
            tmp = ires.c;
            for (chn = 0; chn < channels; chn++) {
                    for (byte = 0; byte < (unsigned int)bps; byte++) 
*(samples[chn] + byte) = tmp[byte];
                        samples[chn] += steps[chn];
                    }
                    phase += step;
                    if (phase >= max_phase)
                            phase -= max_phase;
                    }
                    *_phase = phase;
  
}                               


static int set_hwparams(snd_pcm_t *handle,
                                snd_pcm_hw_params_t *params,
                                snd_pcm_access_t access)
{
        unsigned int rrate;
        snd_pcm_uframes_t size;
        int err, dir;
       
        /*escolha todos os parametros*/
        err = snd_pcm_hw_params_any(handle, params);
        if (err < 0) {
                printf("Broken configuration for playback: no 
configuration available: %s\n", snd_strerror(err));
                return err;
        }
       
        /*set hardware resampling*/
        err = snd_pcm_hw_params_set_rate_resample(handle, params, resample);
        if (err < 0) {
                printf("Resampling setup failed for playback: %s\n", 
snd_strerror(err));
                return err;
        }
       
      /* set the interleaved read/write format */
      err = snd_pcm_hw_params_set_access(handle, params, access);
      if (err < 0) {
            printf("Access type not available for playback: %s\n", 
snd_strerror(err));
            return err;
       }
      
      /* set the sample format SND_PCM_FORMAT_S16 */
       err = snd_pcm_hw_params_set_format(handle, params, format);
       if (err < 0) {
             printf("Sample format not available for playback: %s\n", 
snd_strerror(err));
             return err;
      }
     
        /* set the count of channels 1  */
       err = snd_pcm_hw_params_set_channels(handle, params, channels);
       if (err < 0) {
             printf("Channels count (%i) not available for playbacks: 
%s\n", channels, snd_strerror(err));
             return err;
      }
     
      /* set the stream rate */
       rrate = rate;
       err = snd_pcm_hw_params_set_rate_near(handle, params, &rrate, 0);
       if (err < 0) {
             printf("Rate %iHz not available for playback: %s\n", rate, 
snd_strerror(err));
             return err;
      }
      if (rrate != rate) {
             printf("Rate doesn't match (requested %iHz, get %iHz)\n", 
rate, err);
            return -EINVAL;
      }
      /* set the buffer time */
      err = snd_pcm_hw_params_set_buffer_time_near(handle, params, 
&buffer_time, &dir);
      if (err < 0) {
           printf("Unable to set buffer time %i for playback: %s\n", 
buffer_time, snd_strerror(err));
           return err;
      }
      err = snd_pcm_hw_params_get_buffer_size(params, &size);
      if (err < 0) {
           printf("Unable to get buffer size for playback: %s\n", 
snd_strerror(err));
           return err;
      }
      buffer_size = size;
      /* set the period time */
      err = snd_pcm_hw_params_set_period_time_near(handle, params, 
&period_time, &dir);
      if (err < 0) {
           printf("Unable to set period time %i for playback: %s\n", 
period_time, snd_strerror(err));
           return err;
      }
      err = snd_pcm_hw_params_get_period_size(params, &size, &dir);
      if (err < 0) {
           printf("Unable to get period size for playback: %s\n", 
snd_strerror(err));
           return err;
      }
      period_size = size;
      /* write the parameters to device */
      err = snd_pcm_hw_params(handle, params);
      if (err < 0) {
           printf("Unable to set hw params for playback: %s\n", 
snd_strerror(err));
           return err;
      }
      return 0;
}



static int set_swparams(snd_pcm_t *handle, snd_pcm_sw_params_t *swparams) {

            int err;
           
            /*pegar os parametros atuais swparams*/
            err = snd_pcm_sw_params_current(handle, swparams);
            if (err < 0) {
                printf("Unable to determine current swparams for 
playback: %s\n", snd_strerror(err));
                return err;
            }
            /*Começa a transferência quando o buffer está quase cheio*/
            /*(buffer_size / avail_min) * avail_min */
            err = snd_pcm_sw_params_set_avail_min(handle, swparams, 
(buffer_size / period_size) * period_size);
            if (err < 0) {
                printf("Unable to set start threshold mode for playback: 
%s\n", snd_strerror(err));
                return err;
            }
            /* allow the transfer when at least period_size samples can 
be processed */
          /* or disable this mechanism when period event is enabled (aka 
interrupt like style processing) */
          err = snd_pcm_sw_params_set_avail_min(handle, swparams, 
period_event ? buffer_size : period_size);
          if (err < 0) {
                 printf("Unable to set avail min for playback: %s\n", 
snd_strerror(err));
                  return err;
         }
          /* enable period events when requested */
         if (period_event) {
                  err = snd_pcm_sw_params_set_period_event(handle, 
swparams, 1);
                  if (err < 0) {
                          printf("Unable to set period event: %s\n", 
snd_strerror(err));
                          return err;
                 }
          }
          /* write the parameters to the playback device */
          err = snd_pcm_sw_params(handle, swparams);
          if (err < 0) {
                  printf("Unable to set sw params for playback: %s\n", 
snd_strerror(err));
                  return err;
          }
          return 0;
 }

/* Tenta recuperar estados de underrun e suspend */

static int xrun_recovery(snd_pcm_t *handle, int err)
{
            if (verbose)
                    printf("stream recovery\n");
            if (err == -EPIPE) {      //under-run*/
                    err = snd_pcm_prepare(handle);
                    if (err < 0)
                                printf("Can't recovery from underrun, 
prepare failed: %s\n", snd_strerror(err));
                    return 0;
            } else if (err == -ESTRPIPE) {
                    while ((err = snd_pcm_resume(handle)) == -EAGAIN)
                            sleep(1); /*espera pela release flag*/
                    if (err < 0) {
                            err = snd_pcm_prepare(handle);
                            if (err < 0)
                                    printf("Can't recovery from suspend, 
prepare failed: %s\n", snd_strerror(err));
                            }
                            return 0;
                    }
                    return err;
}

/* Metodo de transferência *WRITE-ONLY* */
static int write_loop(snd_pcm_t *handle,
                             signed short *samples,
                             snd_pcm_channel_area_t *areas)
{
        double phase = 0;
        signed short *ptr;
        int err, cptr;
       
        while(1) {
            generate_sine(areas, 0, period_size, &phase);
            ptr = samples;
            cptr = period_size;
            while (cptr > 0) {
                    err = snd_pcm_writei(handle, ptr, cptr);
                    if (err == -EAGAIN)
                                 continue;
                    if (err < 0) {
                         if (xrun_recovery(handle, err) < 0) {
                                 printf("Write error: %s\n", 
snd_strerror(err));
                                 exit(EXIT_FAILURE);
                         }//if
                         ptr += err * channels;
                         cptr -= err;
                   }//if
                    }//if

         }//while
}


 /*
 *   Método de transferência - write and wait por espaço no buffer
 */

static int wait_for_poll(snd_pcm_t *handle, struct pollfd *ufds, 
unsigned int count)
{
        unsigned short revents;

        while (1) {
                 poll(ufds, count, -1);
                 snd_pcm_poll_descriptors_revents(handle, ufds, count, 
&revents);
                 if (revents & POLLERR)
                        return -EIO;
                 if (revents & POLLOUT)
                        return 0;
        }
}


static int write_and_poll_loop(snd_pcm_t *handle,
                                 signed short *samples,
                                 snd_pcm_channel_area_t *areas)
  {
          struct pollfd *ufds;
          double phase = 0;
          signed short *ptr;
          int err, count, cptr, init;
 
          count = snd_pcm_poll_descriptors_count (handle);
          if (count <= 0) {
                  printf("Invalid poll descriptors count\n");
                  return count;
          }
 
          ufds = malloc(sizeof(struct pollfd) * count);
          if (ufds == NULL) {
                  printf("No enough memory\n");
                  return -ENOMEM;
          }
          if ((err = snd_pcm_poll_descriptors(handle, ufds, count)) < 0) {
                  printf("Unable to obtain poll descriptors for 
playback: %s\n", snd_strerror(err));
                  return err;
          }
 
          init = 1;
          while (1) {
                  if (!init) {
                          err = wait_for_poll(handle, ufds, count);
                          if (err < 0) {
                                 if (snd_pcm_state(handle) == 
SND_PCM_STATE_XRUN ||
                                      snd_pcm_state(handle) == 
SND_PCM_STATE_SUSPENDED) {
                                          err = snd_pcm_state(handle) == 
SND_PCM_STATE_XRUN ? -EPIPE : -ESTRPIPE;
                                          if (xrun_recovery(handle, err) 
< 0) {
                                                  printf("Write error: 
%s\n", snd_strerror(err));
                                                  exit(EXIT_FAILURE);
                                          }
                                          init = 1;
                                  } else {
                                          printf("Wait for poll failed\n");
                                         return err;
                                  }
                          }
                  }
 
                  generate_sine(areas, 0, period_size, &phase);
                  ptr = samples;
                 cptr = period_size;
                  while (cptr > 0) {
                          err = snd_pcm_writei(handle, ptr, cptr);
                          if (err < 0) {
                                  if (xrun_recovery(handle, err) < 0) {
                                          printf("Write error: %s\n", 
snd_strerror(err));
                                          exit(EXIT_FAILURE);
                                  }
                                  init = 1;
                                 break;  /* skip one period */
                          }
                          if (snd_pcm_state(handle) == 
SND_PCM_STATE_RUNNING)
                                  init = 0;
                          ptr += err * channels;
                          cptr -= err;
                         if (cptr == 0)
                                  break;
                           /* it is possible, that the initial buffer 
cannot store */
                          /* all data from the last period, so wait 
awhile */
                          err = wait_for_poll(handle, ufds, count);
                          if (err < 0) {
                                  if (snd_pcm_state(handle) == 
SND_PCM_STATE_XRUN ||
                                     snd_pcm_state(handle) == 
SND_PCM_STATE_SUSPENDED) {
                                          err = snd_pcm_state(handle) == 
SND_PCM_STATE_XRUN ? -EPIPE : -ESTRPIPE;
                                          if (xrun_recovery(handle, err) 
< 0) {
                                                  printf("Write error: 
%s\n", snd_strerror(err));
                                                  exit(EXIT_FAILURE);
                                          }
                                          init = 1;
                                  } else {
                                          printf("Wait for poll failed\n");
                                         return err;
                                  }
                          }
                 }
          }
}



/*
*  Metodo de transferencia - Notificação assincrona
*/


 struct async_private_data {
         signed short *samples;
         snd_pcm_channel_area_t *areas;
         double phase;
 };
 

static void async_callback(snd_async_handler_t *ahandler)
{
         snd_pcm_t *handle = snd_async_handler_get_pcm(ahandler);
         struct async_private_data *data = 
snd_async_handler_get_callback_private(ahandler);
          signed short *samples = data->samples;
          snd_pcm_channel_area_t *areas = data->areas;
         snd_pcm_sframes_t avail;
          int err;
         
         avail = snd_pcm_avail_update(handle);
          while (avail >= period_size) {
                 generate_sine(areas, 0, period_size, &data->phase);
                  err = snd_pcm_writei(handle, samples, period_size);
                  if (err < 0) {
                          printf("Write error: %s\n", snd_strerror(err));
                         exit(EXIT_FAILURE);
                 }
                  if (err != period_size) {
                          printf("Write error: written %i expected 
%li\n", err, period_size);
                         exit(EXIT_FAILURE);
                 }
                  avail = snd_pcm_avail_update(handle);
          }
}


static int async_loop(snd_pcm_t *handle,
                        signed short *samples,
                       snd_pcm_channel_area_t *areas)
  {
          struct async_private_data data;
         snd_async_handler_t *ahandler;
          int err, count;
 
         data.samples = samples;
          data.areas = areas;
         data.phase = 0;
          err = snd_async_add_pcm_handler(&ahandler, handle, 
async_callback, &data);
          if (err < 0) {
                  printf("Unable to register async handler\n");
                  exit(EXIT_FAILURE);
         }
         for (count = 0; count < 2; count++) {
                 generate_sine(areas, 0, period_size, &data.phase);
                  err = snd_pcm_writei(handle, samples, period_size);
                  if (err < 0) {
                         printf("Initial write error: %s\n", 
snd_strerror(err));
                         exit(EXIT_FAILURE);
                  }
                  if (err != period_size) {
                          printf("Initial write error: written %i 
expected %li\n", err, period_size);
                         exit(EXIT_FAILURE);
                  }
          }
          if (snd_pcm_state(handle) == SND_PCM_STATE_PREPARED) {
                  err = snd_pcm_start(handle);
                  if (err < 0) {
                         printf("Start error: %s\n", snd_strerror(err));
                          exit(EXIT_FAILURE);
                  }
          }
 
         /* because all other work is done in the signal handler,
             suspend the process */
          while (1) {
                  sleep(1);
          }
}

 /*
 *   Transfer method - asynchronous notification + direct write
 */
 
  static void async_direct_callback(snd_async_handler_t *ahandler)
  {
          snd_pcm_t *handle = snd_async_handler_get_pcm(ahandler);
          struct async_private_data *data = 
snd_async_handler_get_callback_private(ahandler);
          const snd_pcm_channel_area_t *my_areas;
          snd_pcm_uframes_t offset, frames, size;
          snd_pcm_sframes_t avail, commitres;
          snd_pcm_state_t state;
          int first = 0, err;
         
          while (1) {
                  state = snd_pcm_state(handle);
                  if (state == SND_PCM_STATE_XRUN) {
                          err = xrun_recovery(handle, -EPIPE);
                          if (err < 0) {
                                  printf("XRUN recovery failed: %s\n", 
snd_strerror(err));
                                  exit(EXIT_FAILURE);
                          }
                          first = 1;
                  } else if (state == SND_PCM_STATE_SUSPENDED) {
                          err = xrun_recovery(handle, -ESTRPIPE);
                          if (err < 0) {
                                  printf("SUSPEND recovery failed: 
%s\n", snd_strerror(err));
                                  exit(EXIT_FAILURE);
                          }
                  }
                  avail = snd_pcm_avail_update(handle);
                  if (avail < 0) {
                          err = xrun_recovery(handle, avail);
                          if (err < 0) {
                                  printf("avail update failed: %s\n", 
snd_strerror(err));
                                   exit(EXIT_FAILURE);
                          }
                          first = 1;
                          continue;
                  }
                  if (avail < period_size) {
                          if (first) {
                                  first = 0;
                                  err = snd_pcm_start(handle);
                                  if (err < 0) {
                                          printf("Start error: %s\n", 
snd_strerror(err));
                                          exit(EXIT_FAILURE);
                                 }
                         } else {
                                  break;
                          }
                          continue;
                  }
                 size = period_size;
                  while (size > 0) {
                          frames = size;
                          err = snd_pcm_mmap_begin(handle, &my_areas, 
&offset, &frames);
                          if (err < 0) {
                                  if ((err = xrun_recovery(handle, err)) 
< 0) {
                                          printf("MMAP begin avail 
error: %s\n", snd_strerror(err));
                                          exit(EXIT_FAILURE);
                                  }
                                  first = 1;
                          }
                          generate_sine(my_areas, offset, frames, 
&data->phase);
                          commitres = snd_pcm_mmap_commit(handle, 
offset, frames);
                          if (commitres < 0 || 
(snd_pcm_uframes_t)commitres != frames) {
                                  if ((err = xrun_recovery(handle, 
commitres >= 0 ? -EPIPE : commitres)) < 0) {
                                          printf("MMAP commit error: 
%s\n", snd_strerror(err));
                                          exit(EXIT_FAILURE);
                                  }
                                  first = 1;
                          }
                          size -= frames;
                  }
         }
}


static int async_direct_loop(snd_pcm_t *handle,
                               signed short *samples ATTRIBUTE_UNUSED,
                               snd_pcm_channel_area_t *areas 
ATTRIBUTE_UNUSED)
  {
          struct async_private_data data;
          snd_async_handler_t *ahandler;
          const snd_pcm_channel_area_t *my_areas;
          snd_pcm_uframes_t offset, frames, size;
          snd_pcm_sframes_t commitres;
          int err, count;
 
          data.samples = NULL;    /* we do not require the global sample 
area for direct write */
          data.areas = NULL;      /* we do not require the global areas 
for direct write */
          data.phase = 0;
         err = snd_async_add_pcm_handler(&ahandler, handle, 
async_direct_callback, &data);
          if (err < 0) {
                  printf("Unable to register async handler\n");
                  exit(EXIT_FAILURE);
          }
          for (count = 0; count < 2; count++) {
                  size = period_size;
                  while (size > 0) {
                          frames = size;
                          err = snd_pcm_mmap_begin(handle, &my_areas, 
&offset, &frames);
                          if (err < 0) {
                                  if ((err = xrun_recovery(handle, err)) 
< 0) {
                                          printf("MMAP begin avail 
error: %s\n", snd_strerror(err));
                                          exit(EXIT_FAILURE);
                                 }
                         }
                          generate_sine(my_areas, offset, frames, 
&data.phase);
                          commitres = snd_pcm_mmap_commit(handle, 
offset, frames);
                          if (commitres < 0 || 
(snd_pcm_uframes_t)commitres != frames) {
                                  if ((err = xrun_recovery(handle, 
commitres >= 0 ? -EPIPE : commitres)) < 0) {
                                          printf("MMAP commit error: 
%s\n", snd_strerror(err));
                                          exit(EXIT_FAILURE);
                                  }
                          }
                          size -= frames;
                   }
          }
          err = snd_pcm_start(handle);
          if (err < 0) {
                  printf("Start error: %s\n", snd_strerror(err));
                  exit(EXIT_FAILURE);
          }
 
         /* because all other work is done in the signal handler,
             suspend the process */
          while (1) {
                  sleep(1);
          }
}

 /*
 *   Transfer method - direct write only
 */
 
 static int direct_loop(snd_pcm_t *handle,
                         signed short *samples ATTRIBUTE_UNUSED,
                         snd_pcm_channel_area_t *areas ATTRIBUTE_UNUSED)
  {
          double phase = 0;
         const snd_pcm_channel_area_t *my_areas;
          snd_pcm_uframes_t offset, frames, size;
         snd_pcm_sframes_t avail, commitres;
          snd_pcm_state_t state;
          int err, first = 1;
 
          while (1) {
                  state = snd_pcm_state(handle);
                  if (state == SND_PCM_STATE_XRUN) {
                          err = xrun_recovery(handle, -EPIPE);
                          if (err < 0) {
                                 printf("XRUN recovery failed: %s\n", 
snd_strerror(err));
                                  return err;
                          }
                          first = 1;
                 } else if (state == SND_PCM_STATE_SUSPENDED) {
                         err = xrun_recovery(handle, -ESTRPIPE);
                          if (err < 0) {
                                  printf("SUSPEND recovery failed: 
%s\n", snd_strerror(err));
                                   return err;
                          }
                  }
                  avail = snd_pcm_avail_update(handle);
                  if (avail < 0) {
                          err = xrun_recovery(handle, avail);
                          if (err < 0) {
                                  printf("avail update failed: %s\n", 
snd_strerror(err));
                                  return err;
                          }
                          first = 1;
                          continue;
                  }
                  if (avail < period_size) {
                          if (first) {
                                  first = 0;
                                  err = snd_pcm_start(handle);
                                  if (err < 0) {
                                          printf("Start error: %s\n", 
snd_strerror(err));
                                          exit(EXIT_FAILURE);
                                  }
                          } else {
                                  err = snd_pcm_wait(handle, -1);
                                  if (err < 0) {
                                          if ((err = 
xrun_recovery(handle, err)) < 0) {
                                                  printf("snd_pcm_wait 
error: %s\n", snd_strerror(err));
                                                  exit(EXIT_FAILURE);
                                          }
                                          first = 1;
                                  }
                          }
                          continue;
                  }
                  size = period_size;
                  while (size > 0) {
                           frames = size;
                          err = snd_pcm_mmap_begin(handle, &my_areas, 
&offset, &frames);
                          if (err < 0) {
                                 if ((err = xrun_recovery(handle, err)) 
< 0) {
                                          printf("MMAP begin avail 
error: %s\n", snd_strerror(err));
                                          exit(EXIT_FAILURE);
                                  }
                                  first = 1;
                         }
                          generate_sine(my_areas, offset, frames, &phase);
                          commitres = snd_pcm_mmap_commit(handle, 
offset, frames);
                          if (commitres < 0 || 
(snd_pcm_uframes_t)commitres != frames) {
                                 if ((err = xrun_recovery(handle, 
commitres >= 0 ? -EPIPE : commitres)) < 0) {
                                          printf("MMAP commit error: 
%s\n", snd_strerror(err));
                                          exit(EXIT_FAILURE);
                                  }
                                 first = 1;
                          }
                          size -= frames;
                  }
          }
}

/*
 *   Transfer method - direct write only using mmap_write functions
 */
 
 static int direct_write_loop(snd_pcm_t *handle,
                               signed short *samples,
                              snd_pcm_channel_area_t *areas)
 {
         double phase = 0;
          signed short *ptr;
          int err, cptr;
 
          while (1) {
                  generate_sine(areas, 0, period_size, &phase);
                 ptr = samples;
                  cptr = period_size;
                  while (cptr > 0) {
                          err = snd_pcm_mmap_writei(handle, ptr, cptr);
                          if (err == -EAGAIN)
                                  continue;
                          if (err < 0) {
                                  if (xrun_recovery(handle, err) < 0) {
                                          printf("Write error: %s\n", 
snd_strerror(err));
                                          exit(EXIT_FAILURE);
                                 }
                                 break;  /* skip one period */
                         }
                          ptr += err * channels;
                          cptr -= err;
                  }
          }
}

struct transfer_method {
       const char *name;
       snd_pcm_access_t access;
       int (*transfer_loop)(snd_pcm_t *handle,
                            signed short *samples,
                            snd_pcm_channel_area_t *areas);
};

static struct transfer_method transfer_methods[] = {
          { "write", SND_PCM_ACCESS_RW_INTERLEAVED, write_loop },
          { "write_and_poll", SND_PCM_ACCESS_RW_INTERLEAVED, 
write_and_poll_loop },
          { "async", SND_PCM_ACCESS_RW_INTERLEAVED, async_loop },
          { "async_direct", SND_PCM_ACCESS_MMAP_INTERLEAVED, 
async_direct_loop },
          { "direct_interleaved", SND_PCM_ACCESS_MMAP_INTERLEAVED, 
direct_loop },
          { "direct_noninterleaved", SND_PCM_ACCESS_MMAP_NONINTERLEAVED, 
direct_loop },
          { "direct_write", SND_PCM_ACCESS_MMAP_INTERLEAVED, 
direct_write_loop },
          { NULL, SND_PCM_ACCESS_RW_INTERLEAVED, NULL }
};



static void help(void)
{
         int k;
          printf(
  "Usage: pcm [OPTION]... [FILE]...\n"
  "-h,--help      help\n"
  "-D,--device    playback device\n"
  "-r,--rate      stream rate in Hz\n"
  "-c,--channels  count of channels in stream\n"
  "-f,--frequency sine wave frequency in Hz\n"
  "-b,--buffer    ring buffer size in us\n"
  "-p,--period    period size in us\n"
  "-m,--method    transfer method\n"
  "-o,--format    sample format\n"
  "-v,--verbose   show the PCM setup parameters\n"
  "-n,--noresample  do not resample\n"
  "-e,--pevent    enable poll event after each period\n"
  "\n");
          printf("Recognized sample formats are:");
         for (k = 0; k < SND_PCM_FORMAT_LAST; ++k) {
                  const char *s = snd_pcm_format_name(k);
                  if (s)
                          printf(" %s", s);
          }
          printf("\n");
          printf("Recognized transfer methods are:");
          for (k = 0; transfer_methods[k].name; k++)
                  printf(" %s", transfer_methods[k].name);
          printf("\n");
}



int main (int argc, char *argv[])
{
            struct option long_option[] =
                {
                     {"help", 0, NULL, 'h'},
                     {"device", 1, NULL, 'd'},
                     {"rate", 1, NULL, 'r'},
                     {"channels", 1, NULL, 'c'},
                     {"frequency", 1, NULL, 'f'},
                     {"buffer", 1, NULL, 'b'},
                     {"period", 1, NULL, 'p'},
                     {"method", 1, NULL, 'm'},
                     {"format", 1, NULL, 'o'},
                     {"verbose", 1, NULL, 'v'},
                     {"noresample", 1, NULL, 'n'},
                     {"pevent", 1, NULL, 'e'},
                     {NULL, 0, NULL, 0},
                };
               
                snd_pcm_t *handle;                            //ponteiro 
para pcm handle
                int err, morehelp;
                snd_pcm_hw_params_t *hwparams;                
//parametros de hardware
                snd_pcm_sw_params_t *swparams;                
//parametros de software
                int method = 0;
                signed short *samples;
                unsigned int chn;
                snd_pcm_channel_area_t *areas;

                //snd_pcm_hw_params_alloca(&hwparams);
                //snd_pcm_sw_params_alloca(&swparams);
               
                morehelp = 0;
                while (1) {
                            int c;
                            if ((c = getopt_long(argc, argv, 
"hd:r:c:f:b:p:m:o:vne", long_option, NULL)) < 0)
                                    break;
                            switch(c) {
                            case 'h':
                                        morehelp++;
                                        break;
                            case 'd':
                                        device = strdup(optarg);
                                        break;
                            case 'r':
                                        rate = atoi(optarg);
                                        rate = rate < 4000 ? 4000 : rate;
                                        rate = rate > 196000 ? 19600 : rate;
                                        break;
                         case 'c':
                              channels = atoi(optarg);
                              channels = channels < 1 ? 1 : channels;
                              channels = channels > 1024 ? 1024 : channels;
                              break;
                     case 'f':
                              freq = atoi(optarg);
                              freq = freq < 50 ? 50 : freq;
                              freq = freq > 5000 ? 5000 : freq;
                              break;
                     case 'b':
                              buffer_time = atoi(optarg);
                              buffer_time = buffer_time < 1000 ? 1000 : 
buffer_time;
                              buffer_time = buffer_time > 1000000 ? 
1000000 : buffer_time;
                              break;
                     case 'p':
                              period_time = atoi(optarg);
                              period_time = period_time < 1000 ? 1000 : 
period_time;
                              period_time = period_time > 1000000 ? 
1000000 : period_time;
                              break;
                     case 'm':
                              for (method = 0; 
transfer_methods[method].name; method++)
                                              if 
(!strcasecmp(transfer_methods[method].name, optarg))
                                              break;
                              if (transfer_methods[method].name == NULL)
                                      method = 0;
                              break;
                     case 'o':
                              for (format = 0; format < 
SND_PCM_FORMAT_LAST; format++) {
                                      const char *format_name = 
snd_pcm_format_name(format);
                                      if (format_name)
                                              if 
(!strcasecmp(format_name, optarg))
                                              break;
                              }
                              if (format == SND_PCM_FORMAT_LAST)
                                     format = SND_PCM_FORMAT_S16;
                              break;
                     case 'v':
                              verbose = 1;
                              break;
                     case 'n':
                              resample = 0;
                              break;
                      case 'e':
                              period_event = 1;
                              break;
                     }//switch
              }//while
             
              if(morehelp) {
                          help();
                          return 0;
              }

                //cria um novo output objeto
                err = snd_output_stdio_attach(&output, &stdout, 0);
                if (err < 0) {
                        printf("Output failed: %s\n", snd_strerror(err));
                        return 0;
                }
               
                printf("Playback device is %s\n", device);
                printf("Stream parameters are %iHz, %s, %i channels\n", 
rate, snd_pcm_format_name(format), channels);
                printf("sine wave rate is %i %.4fHz\n", freq);
                printf("Using transfer method: %s\n", 
transfer_methods[method].name);
               
                if ((err = snd_pcm_open(&handle, device, 
SND_PCM_STREAM_PLAYBACK, 0)) < 0) {
                        printf("Playback open error: %s\n", 
snd_strerror(err));
                        return 0;
                }
               
                if ((err = set_hwparams(handle, hwparams, 
transfer_methods[method].access)) < 0) {
                  printf("Setting of hwparams failed: %s\n", 
snd_strerror(err));
                  exit(EXIT_FAILURE);
            }
            if ((err = set_swparams(handle, swparams)) < 0) {
                  printf("Setting of swparams failed: %s\n", 
snd_strerror(err));
                  exit(EXIT_FAILURE);
           }
 
            if (verbose > 0)
                  snd_pcm_dump(handle, output);
               
            samples = malloc((period_size * channels * 
snd_pcm_format_physical_width(format)) / 8);
            if (samples == NULL) {
                  printf("No enough memory\n");
                  exit(EXIT_FAILURE);
            }
         
            areas = calloc(channels, sizeof(snd_pcm_channel_area_t));
            if (areas == NULL) {
                  printf("No enough memory\n");
                  exit(EXIT_FAILURE);
            }
            for (chn = 0; chn < channels; chn++) {
                  areas[chn].addr = samples;
                  areas[chn].first = chn * 
snd_pcm_format_physical_width(format);
                  areas[chn].step = channels * 
snd_pcm_format_physical_width(format);
             }
 
            err = transfer_methods[method].transfer_loop(handle, 
samples, areas);
            if (err < 0)
                  printf("Transfer failed: %s\n", snd_strerror(err));
 
            free(areas);
            free(samples);
            snd_pcm_close(handle);
            return 0;
}


Thanks in advance;



Tks!

-------------------

Guilherme Longo
Dept. Eng. da Computação
Unaerp

Linux User - #484927

*Before Asking
http://www.istf.com.br/?page=perguntas

!- I'd rather die on my feet than live on my knees -!



Ted T. Logan wrote:
> ALSA lib pcm_bluetooth.c:1607:(audioservice_expect) BT_OPEN failed : 
> Invalid argument(22)
>
> ** WARNING **: alsa_setup(): Unable to install hw params
>
> I get this all the time now.  What does this error mean?
>
>
>
> arecord -D bluetoothh550 -f S16_LE | aplay -D bluetoothh550 -f S16_LE
> Recording WAVE 'stdin' : Signed 16 bit Little Endian, Rate 8000 Hz, Mono
> ALSA lib pcm_bluetooth.c:1607:(audioservice_expect) BT_OPEN failed : 
> Invalid argument(22)
> arecord: set_params:1041: Unable to install hw params:
> ACCESS:  RW_INTERLEAVED
> FORMAT:  S16_LE
> SUBFORMAT:  STD
> SAMPLE_BITS: 16
> FRAME_BITS: 16
> CHANNELS: 1
> RATE: 8000
> PERIOD_TIME: 125000
> PERIOD_SIZE: 1000
> PERIOD_BYTES: 2000
> PERIODS: 4
> BUFFER_TIME: 500000
> BUFFER_SIZE: 4000
> BUFFER_BYTES: 8000
> TICK_TIME: [0 0]
> aplay: playback:2297: read error
>
>
>
> and here with mplayer
>
>
> Playing skypering.wav.
> Audio only file format detected.
> ==========================================================================
> Opening audio decoder: [pcm] Uncompressed PCM audio decoder
> AUDIO: 16000 Hz, 2 ch, s16le, 512.0 kbit/100.00% (ratio: 64000->64000)
> Selected audio codec: [pcm] afm: pcm (Uncompressed PCM)
> ==========================================================================
> [AO_ALSA] alsa-lib: pcm_bluetooth.c:1607:(audioservice_expect) BT_OPEN 
> failed : Invalid argument(22)
> [AO_ALSA] Unable to set hw-parameters: Invalid argument
> Failed to initialize audio driver 'alsa:device=bluetoothh550'
> Could not open/initialize audio device -> no sound.
> Audio: no sound
> Video: no video
>
>
>
> _______________________________________________
> Alsa-devel mailing list
> Alsa-devel@alsa-project.org
> http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
>
>   

  reply	other threads:[~2009-06-15  5:38 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-06-14 10:51 [PATCH, RFC 0/3] magician fix and UDA1380 i2c device registration change Philipp Zabel
     [not found] ` <1244976692-5189-2-git-send-email-philipp.zabel@gmail.com>
2009-06-14 10:51   ` [PATCH 1/3] ASoC: magician: fix PXA SSP clock polarity Philipp Zabel
2009-06-14 10:51     ` [PATCH, RFC 2/3] ASoC: UDA1380: register from board files, configure via pdata Philipp Zabel
2009-06-14 10:51       ` [PATCH, RFC 3/3] pxa/magician: add I2C board info and platform data for UDA1380 Philipp Zabel
2009-06-14 15:00         ` Mark Brown
2009-06-15  2:06           ` Eric Miao
2009-06-15 10:26             ` Mark Brown
2009-06-14 14:51       ` [PATCH, RFC 2/3] ASoC: UDA1380: register from board files, configure via pdata Mark Brown
2009-06-14 20:52         ` pHilipp Zabel
2009-06-15  4:56           ` Can't use bluetooth headset after upgrade of alsa/bluez with fedora 11 Ted T. Logan
2009-06-15  5:38             ` Guilherme [this message]
2009-06-15 20:18         ` [PATCH] ASoC: UDA1380: refactor device registration Philipp Zabel
2009-06-15 21:10           ` Mark Brown
2009-06-14 14:23     ` [PATCH 1/3] ASoC: magician: fix PXA SSP clock polarity Mark Brown

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4A35DE70.7000306@gmail.com \
    --to=grlongo.ireland@gmail.com \
    --cc=alsa-devel@alsa-project.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.