/* 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; }
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, ¶m); if (err < 0) { perror("sched_getparam():"); exit(-1); } param.sched_priority = sched_get_priority_max(SCHED_FIFO); err = sched_setscheduler(0, SCHED_FIFO, ¶m); 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; }
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; }