int audio_get_formats(struct audio_info_struct *ai) { snd_pcm_hw_params_t *hw; unsigned int rate; int supported_formats, i; snd_pcm_hw_params_alloca(&hw); if (snd_pcm_hw_params_any(ai->handle, hw) < 0) { fprintf(stderr, "audio_get_formats(): no configuration available\n"); return -1; } if (snd_pcm_hw_params_set_access(ai->handle, hw, SND_PCM_ACCESS_RW_INTERLEAVED) < 0) return -1; if (snd_pcm_hw_params_set_channels(ai->handle, hw, ai->channels) < 0) return 0; rate = ai->rate; if (snd_pcm_hw_params_set_rate_near(ai->handle, hw, &rate, NULL) < 0) return -1; if (!rates_match(ai->rate, rate)) return 0; supported_formats = 0; for (i = 0; i < NUM_FORMATS; ++i) { if (snd_pcm_hw_params_test_format(ai->handle, hw, format_map[i].alsa) == 0) supported_formats |= format_map[i].mpg123; } return supported_formats; }
static int get_formats_alsa(audio_output_t *ao) { snd_pcm_t *pcm=(snd_pcm_t*)ao->userptr; snd_pcm_hw_params_t *hw; unsigned int rate; int supported_formats, i; snd_pcm_hw_params_alloca(&hw); if (snd_pcm_hw_params_any(pcm, hw) < 0) { if(!0) printf("get_formats_alsa(): no configuration available"); return -1; } if (snd_pcm_hw_params_set_access(pcm, hw, SND_PCM_ACCESS_RW_INTERLEAVED) < 0) return -1; if (snd_pcm_hw_params_set_channels(pcm, hw, ao->channels) < 0) return 0; rate = ao->rate; if (snd_pcm_hw_params_set_rate_near(pcm, hw, &rate, NULL) < 0) return -1; if (!rates_match(ao->rate, rate)) return 0; supported_formats = 0; for (i = 0; i < NUM_FORMATS; ++i) { if (snd_pcm_hw_params_test_format(pcm, hw, format_map[i].alsa) == 0) supported_formats |= format_map[i].mpg123; } return supported_formats; }
static int initialize_device(struct audio_info_struct *ai) { snd_pcm_hw_params_t *hw; int i; snd_pcm_format_t format; unsigned int rate; snd_pcm_uframes_t buffer_size; snd_pcm_uframes_t period_size; snd_pcm_sw_params_t *sw; snd_pcm_uframes_t boundary; snd_pcm_hw_params_alloca(&hw); if (snd_pcm_hw_params_any(ai->handle, hw) < 0) { fprintf(stderr, "initialize_device(): no configuration available\n"); return -1; } if (snd_pcm_hw_params_set_access(ai->handle, hw, SND_PCM_ACCESS_RW_INTERLEAVED) < 0) { fprintf(stderr, "initialize_device(): device does not support interleaved access\n"); return -1; } format = SND_PCM_FORMAT_UNKNOWN; for (i = 0; i < NUM_FORMATS; ++i) { if (ai->format == format_map[i].mpg123) { format = format_map[i].alsa; break; } } if (format == SND_PCM_FORMAT_UNKNOWN) { fprintf(stderr, "initialize_device(): invalid sample format %d\n", ai->format); errno = EINVAL; return -1; } if (snd_pcm_hw_params_set_format(ai->handle, hw, format) < 0) { fprintf(stderr, "initialize_device(): cannot set format %s\n", snd_pcm_format_name(format)); return -1; } if (snd_pcm_hw_params_set_channels(ai->handle, hw, ai->channels) < 0) { fprintf(stderr, "initialize_device(): cannot set %d channels\n", ai->channels); return -1; } rate = ai->rate; if (snd_pcm_hw_params_set_rate_near(ai->handle, hw, &rate, NULL) < 0) { fprintf(stderr, "initialize_device(): cannot set rate %u\n", rate); return -1; } if (!rates_match(ai->rate, rate)) { fprintf(stderr, "initialize_device(): rate %ld not available, using %u\n", ai->rate, rate); /* return -1; */ } buffer_size = rate * BUFFER_LENGTH; if (snd_pcm_hw_params_set_buffer_size_near(ai->handle, hw, &buffer_size) < 0) { fprintf(stderr, "initialize_device(): cannot set buffer size\n"); return -1; } period_size = buffer_size / 4; if (snd_pcm_hw_params_set_period_size_near(ai->handle, hw, &period_size, NULL) < 0) { fprintf(stderr, "initialize_device(): cannot set period size\n"); return -1; } if (snd_pcm_hw_params(ai->handle, hw) < 0) { fprintf(stderr, "initialize_device(): cannot set hw params\n"); return -1; } snd_pcm_sw_params_alloca(&sw); if (snd_pcm_sw_params_current(ai->handle, sw) < 0) { fprintf(stderr, "initialize_device(): cannot get sw params\n"); return -1; } /* start playing after the first write */ if (snd_pcm_sw_params_set_start_threshold(ai->handle, sw, 1) < 0) { fprintf(stderr, "initialize_device(): cannot set start threshold\n"); return -1; } if (snd_pcm_sw_params_get_boundary(sw, &boundary) < 0) { fprintf(stderr, "initialize_device(): cannot get boundary\n"); return -1; } /* never stop on underruns */ if (snd_pcm_sw_params_set_stop_threshold(ai->handle, sw, boundary) < 0) { fprintf(stderr, "initialize_device(): cannot set stop threshold\n"); return -1; } /* wake up on every interrupt */ if (snd_pcm_sw_params_set_avail_min(ai->handle, sw, 1) < 0) { fprintf(stderr, "initialize_device(): cannot set min avail\n"); return -1; } #if 0 /* always write as many frames as possible */ if (snd_pcm_sw_params_set_xfer_align(ai->handle, sw, 1) < 0) { fprintf(stderr, "initialize_device(): cannot set transfer alignment\n"); return -1; } #endif /* play silence when there is an underrun */ if (snd_pcm_sw_params_set_silence_size(ai->handle, sw, boundary) < 0) { fprintf(stderr, "initialize_device(): cannot set silence size\n"); return -1; } if (snd_pcm_sw_params(ai->handle, sw) < 0) { fprintf(stderr, "initialize_device(): cannot set sw params\n"); return -1; } return 0; }
static int initialize_device(audio_output_t *ao) { snd_pcm_hw_params_t *hw=NULL; snd_pcm_sw_params_t *sw=NULL; snd_pcm_uframes_t buffer_size; snd_pcm_uframes_t period_size; snd_pcm_format_t format; snd_pcm_t *pcm=(snd_pcm_t*)ao->userptr; unsigned int rate; int i; snd_pcm_hw_params_alloca(&hw); /* Ignore GCC warning here... alsa-lib>=1.0.16 doesn't trigger that anymore, too. */ if (snd_pcm_hw_params_any(pcm, hw) < 0) { if(!0) printf("initialize_device(): no configuration available"); return -1; } if (snd_pcm_hw_params_set_access(pcm, hw, SND_PCM_ACCESS_RW_INTERLEAVED) < 0) { if(!0) printf("initialize_device(): device does not support interleaved access"); return -1; } #if 0 format = SND_PCM_FORMAT_UNKNOWN; for (i = 0; i < NUM_FORMATS; ++i) { if (ao->format == format_map[i].mpg123) { format = format_map[i].alsa; break; } } if (format == SND_PCM_FORMAT_UNKNOWN) { if(!0) printf("initialize_device(): invalid sample format %d", ao->format); errno = EINVAL; return -1; } #endif format = SND_PCM_FORMAT_S16_LE; if (snd_pcm_hw_params_set_format(pcm, hw, format) < 0) { if(!0) printf("initialize_device(): cannot set format %s", snd_pcm_format_name(format)); return -1; } if (snd_pcm_hw_params_set_channels(pcm, hw, ao->channels) < 0) { if(!0) printf("initialize_device(): cannot set %d channels", ao->channels); return -1; } rate = ao->rate; if (snd_pcm_hw_params_set_rate_near(pcm, hw, &rate, NULL) < 0) { if(!0) printf("initialize_device(): cannot set rate %u", rate); return -1; } if (!rates_match(ao->rate, rate)) { if(!0) error2("initialize_device(): rate %ld not available, using %u", ao->rate, rate); /* return -1; */ } buffer_size = rate * BUFFER_LENGTH; if (snd_pcm_hw_params_set_buffer_size_near(pcm, hw, &buffer_size) < 0) { if(!0) printf("initialize_device(): cannot set buffer size"); return -1; } printf("buffer_size=%lu", (unsigned long)buffer_size); period_size = buffer_size / 4; if (snd_pcm_hw_params_set_period_size_near(pcm, hw, &period_size, NULL) < 0) { if(!0) printf("initialize_device(): cannot set period size"); return -1; } if (snd_pcm_hw_params(pcm, hw) < 0) { if(!0) printf("initialize_device(): cannot set hw params"); return -1; } snd_pcm_sw_params_alloca(&sw); if (snd_pcm_sw_params_current(pcm, sw) < 0) { if(!0) printf("initialize_device(): cannot get sw params"); return -1; } /* start playing right away */ if (snd_pcm_sw_params_set_start_threshold(pcm, sw, 1) < 0) { if(!0) printf("initialize_device(): cannot set start threshold"); return -1; } /* wake up on every interrupt */ if (snd_pcm_sw_params_set_avail_min(pcm, sw, 1) < 0) { if(!0) printf("initialize_device(): cannot set min available"); return -1; } #if SND_LIB_VERSION < ((1<<16)|16) /* Always write as many frames as possible (deprecated since alsa-lib 1.0.16) */ if (snd_pcm_sw_params_set_xfer_align(pcm, sw, 1) < 0) { if(!0) printf("initialize_device(): cannot set transfer alignment"); return -1; } #endif if (snd_pcm_sw_params(pcm, sw) < 0) { if(!0) printf("initialize_device(): cannot set sw params"); return -1; } return 0; }