/* prepare the audio device for playback */
int ao_plugin_open(ao_device *device, ao_sample_format *format)
{
	ao_alsa_internal *internal  = (ao_alsa_internal *) device->internal;
	int err;

	/* Get the ALSA bitformat first to make sure it's valid */
	err = alsa_get_sample_bitformat(format->bits,
			device->client_byte_format == AO_FMT_BIG);
	if (err < 0)
		goto error;

	internal->bitformat = err;

	/* Open the ALSA device */
	internal->cmd = "snd_pcm_open";
	err = snd_pcm_open(&(internal->pcm_handle), internal->dev,
			   SND_PCM_STREAM_PLAYBACK, 0);
	if (err < 0) {
		internal->pcm_handle = NULL;
		goto error;
	}

	/* Set up the hardware parameters, ie sample and buffer specs */
	err = alsa_set_hwparams(internal, format);
	if (err < 0)
		goto error;

	/* Set up the software parameters, ie de-buffering specs */
	err = alsa_set_swparams(internal);
	if (err < 0)
		goto error;

	/* alsa's endinness will be the same as the application's */
	if (format->bits > 8)
		device->driver_byte_format = device->client_byte_format;

	return 1;

error:
	fprintf(stderr, "ALSA %s error: %s\n",
			internal->cmd, snd_strerror(err));
	if (internal->pcm_handle) {
		snd_pcm_close(internal->pcm_handle);
		internal->pcm_handle = NULL;
	}
	return 0;
}
static inline int alsa_test_open(ao_device *device,
                                 char *dev,
                                 ao_sample_format *format)
{
  ao_alsa_internal *internal  = (ao_alsa_internal *) device->internal;
  snd_pcm_hw_params_t   *params;
  int err;

  adebug("Trying to open ALSA device '%s'\n",dev);

  internal->local_config = init_local_config_with_workaround(device,dev);
  if(internal->local_config)
    err = snd_pcm_open_lconf(&(internal->pcm_handle), dev,
                             SND_PCM_STREAM_PLAYBACK, 0, internal->local_config);
  else
    err = snd_pcm_open(&(internal->pcm_handle), dev,
                       SND_PCM_STREAM_PLAYBACK, 0);

  if(err){
    adebug("Unable to open ALSA device '%s'\n",dev);
    if(internal->local_config)
      snd_config_delete(internal->local_config);
    internal->local_config=NULL;
    return err;
  }

  /* try to set up hw params */
  err = alsa_set_hwparams(device,format);
  if(err<0){
    adebug("Unable to open ALSA device '%s'\n",dev);
    snd_pcm_close(internal->pcm_handle);
    if(internal->local_config)
      snd_config_delete(internal->local_config);
    internal->local_config=NULL;
    internal->pcm_handle = NULL;
    return err;
  }

  /* try to set up sw params */
  err = alsa_set_swparams(device);
  if(err<0){
    adebug("Unable to open ALSA device '%s'\n",dev);
    snd_pcm_close(internal->pcm_handle);
    if(internal->local_config)
      snd_config_delete(internal->local_config);
    internal->local_config=NULL;
    internal->pcm_handle = NULL;
    return err;
  }

  /* this is a hack and fragile if the exact device detection code
     flow changes!  Nevertheless, this is a useful warning for users.
     Never fail silently if we can help it! */
  if(!strcasecmp(dev,"default")){
    /* default device */
    if(device->output_channels>2){
      awarn("ALSA 'default' device plays only channels 0,1.\n");
    }
  }
  if(!strcasecmp(dev,"default") || !strncasecmp(dev,"plug",4)){
    if(format->bits>16){
      awarn("ALSA '%s' device may only simulate >16 bit playback\n",dev);
    }
  }

  /* success! */
  return 0;
}
Beispiel #3
0
int alsa_init(alsa_dev_t *dev, void *ptr, void (*callback)(snd_async_handler_t *))
{
  snd_pcm_t *phandle;
  snd_pcm_t *chandle;
  
  int err;
  snd_pcm_hw_params_t *hwparams_capture, *hwparams_playback;
  snd_pcm_sw_params_t *swparams_capture, *swparams_playback;
    
  struct sched_param param;
  
  err = sched_getparam(0, &param);
  if (err < 0) {
    perror("sched_getparam():");
    exit(-1);
  }
  
  param.sched_priority = sched_get_priority_max(SCHED_FIFO);
  err = sched_setscheduler(0, SCHED_FIFO, &param);
  if (err < 0) {
    perror("sched_setscheduler():");
   exit(-1);
  }  

  snd_pcm_hw_params_alloca(&hwparams_capture);
  snd_pcm_sw_params_alloca(&swparams_capture);  
  
  snd_pcm_hw_params_alloca(&hwparams_playback);
  snd_pcm_sw_params_alloca(&swparams_playback);   
  
  err = snd_output_stdio_attach(&dev->output, stdout, 0);
  if (err < 0) {
    printf("Output failed: %s\n", snd_strerror(err));
    exit(-1);
  }  
  
  printf("Playback device is %s\n", dev->pdevice);
  printf("Stream parameters are %dHz, %s, %d channels\n", dev->rate, snd_pcm_format_name(dev->format), dev->channels);
  
  if ((err = snd_pcm_open(&phandle, dev->pdevice, SND_PCM_STREAM_PLAYBACK, 0)) < 0) {
    printf("Playback open error: %s\n", snd_strerror(err));
    exit(-1);
  }
  
  if ((err = alsa_set_hwparams(dev, phandle, hwparams_playback, SND_PCM_ACCESS_MMAP_INTERLEAVED)) < 0) {
    printf("Setting of hwparams_playback failed: %s\n", snd_strerror(err));
    exit(-1);
  }
  
  if ((err = alsa_set_swparams(dev, phandle, swparams_playback)) < 0) {
    printf("Setting of swparams_playback failed: %s\n", snd_strerror(err));
    exit(-1);
  }
  
  snd_pcm_dump(phandle, dev->output);  
  
  printf("Capture device is %s\n", dev->cdevice);
  
  if ((err = snd_pcm_open(&chandle, dev->cdevice, SND_PCM_STREAM_CAPTURE, 0)) < 0) {
    printf("Capture open error: %s\n", snd_strerror(err));
    exit(-1);
  }
  
  if ((err = alsa_set_hwparams(dev, chandle, hwparams_capture, SND_PCM_ACCESS_MMAP_INTERLEAVED)) < 0) {
    printf("Setting of hwparams_capture failed: %s\n", snd_strerror(err));
    exit(-1);
  }
  
  if ((err = alsa_set_swparams(dev, chandle, swparams_capture)) < 0) {
    printf("Setting of swparams_capture failed: %s\n", snd_strerror(err));
    exit(-1);
  }
  
  snd_pcm_dump(chandle, dev->output);    
  
  if ((err = snd_pcm_link(phandle, chandle)) < 0)
  {
    printf("snd_pcm_link() failed: %s\n", snd_strerror(err));
    exit(-1);    
  }
  
  dev->chandle = chandle;
  dev->phandle = phandle;

  err = alsa_async_direct_loop(dev, ptr, callback);
  if (err < 0)
    printf("Transfer failed: %s\n", snd_strerror(err));  
  
  return 0;  
}
Beispiel #4
0
int audio_alsa_init()
{
	int fd, err;
	char *pcm_rate;
	char tmp_name[20];

	init_rec_buffer();

	/* Create a temporary filename for our FIFO,
	 * Use mkstemp() instead of mktemp() although we need a FIFO not a
	 * regular file. We do this since glibc barfs at mktemp() and this
	 * scares the users :-)
	 */
	strcpy(tmp_name, "/tmp/lircXXXXXX");
	fd = mkstemp(tmp_name);
	close(fd);

	/* Start the race! */
	unlink(tmp_name);
	if (mknod(tmp_name, S_IFIFO | S_IRUSR | S_IWUSR, 0)) {
		logprintf(LOG_ERR, "could not create FIFO %s", tmp_name);
		logperror(LOG_ERR, "audio_alsa_init ()");
		return 0;
	}
	/* Phew, we won the race ... */

	/* Open the pipe and hand it to LIRC ... */
	hw.fd = open(tmp_name, O_RDWR);
	if (hw.fd < 0) {
		logprintf(LOG_ERR, "could not open pipe %s", tmp_name);
		logperror(LOG_ERR, "audio_alsa_init ()");
error:		unlink(tmp_name);
		audio_alsa_deinit();
		return 0;
	}

	/* Open the other end of the pipe and hand it to ALSA code.
	 * We're opening it in non-blocking mode to avoid lockups.
	 */
	alsa_hw.fd = open(tmp_name, O_RDWR | O_NONBLOCK);
	/* Ok, we don't need the FIFO visible in the filesystem anymore ... */
	unlink(tmp_name);

	/* Examine the device name, if it contains a sample rate */
	strncpy(tmp_name, hw.device, sizeof(tmp_name) - 1);
	pcm_rate = strchr(tmp_name, '@');
	if (pcm_rate) {
		int rate;
		char *stereo_channel;

		/* Examine if we need to capture in stereo
		 * looking for an 'l' or 'r' character to indicate
		 * which channel to look at.*/
		stereo_channel = strchr(pcm_rate, ',');

		if (stereo_channel) {

			/* Syntax in device string indicates we need
			   to use stereo */
			alsa_hw.num_channels = 2;
			/* As we are requesting stereo now, use the
			   more common signed 16bit samples */
			alsa_hw.format = SND_PCM_FORMAT_S16_LE;

			if (stereo_channel[1] == 'l') {
				alsa_hw.channel = 0;
			} else if (stereo_channel[1] == 'r') {
				alsa_hw.channel = 1;
			} else {
				logperror(LOG_WARNING,
					  "dont understand which channel to use - defaulting to left\n");
			}
		}

		/* Remove the sample rate from device name (and
		   channel indicator if present) */
		*pcm_rate++ = 0;
		/* See if rate is meaningful */
		rate = atoi(pcm_rate);
		if (rate > 0) {
			alsa_hw.rate = rate;
		}
	}

	/* Open the audio card in non-blocking mode */
	err = snd_pcm_open(&alsa_hw.handle, tmp_name, SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK);
	if (err < 0) {
		logprintf(LOG_ERR, "could not open audio device %s: %s", hw.device, snd_strerror(err));
		logperror(LOG_ERR, "audio_alsa_init ()");
		goto error;
	}

	/* Set up the I/O signal handler */
	if (alsa_error
	    ("async_add_handler", snd_async_add_pcm_handler(&alsa_hw.sighandler, alsa_hw.handle, alsa_sig_io, NULL)))
		goto error;

	/* Set sampling parameters */
	if (alsa_set_hwparams(alsa_hw.handle))
		goto error;

	LOGPRINTF(LOG_INFO, "hw_audio_alsa: Using device '%s', sampling rate %dHz\n", tmp_name, alsa_hw.rate);

	/* Start sampling data */
	if (alsa_error("start", snd_pcm_start(alsa_hw.handle)))
		goto error;

	return 1;
}