| 98 |
audfmt_e fmt; |
audfmt_e fmt; |
| 99 |
int nchannels; |
int nchannels; |
| 100 |
int can_pause; |
int can_pause; |
| 101 |
snd_pcm_uframes_t buffer_size; |
snd_pcm_uframes_t samples; |
| 102 |
}; |
}; |
| 103 |
|
|
| 104 |
static void GCC_FMT_ATTR (2, 3) alsa_logerr (int err, const char *fmt, ...) |
static void GCC_FMT_ATTR (2, 3) alsa_logerr (int err, const char *fmt, ...) |
| 121 |
{ |
{ |
| 122 |
va_list ap; |
va_list ap; |
| 123 |
|
|
| 124 |
AUD_log (AUDIO_CAP, "Can not initialize %s\n", typ); |
AUD_log (AUDIO_CAP, "Could not initialize %s\n", typ); |
| 125 |
|
|
| 126 |
va_start (ap, fmt); |
va_start (ap, fmt); |
| 127 |
AUD_vlog (AUDIO_CAP, fmt, ap); |
AUD_vlog (AUDIO_CAP, fmt, ap); |
| 209 |
return 0; |
return 0; |
| 210 |
} |
} |
| 211 |
|
|
| 212 |
#ifdef DEBUG_MISMATCHES |
#if defined DEBUG_MISMATCHES || defined DEBUG |
| 213 |
static void alsa_dump_info (struct alsa_params_req *req, |
static void alsa_dump_info (struct alsa_params_req *req, |
| 214 |
struct alsa_params_obt *obt) |
struct alsa_params_obt *obt) |
| 215 |
{ |
{ |
| 221 |
dolog ("============================================\n"); |
dolog ("============================================\n"); |
| 222 |
dolog ("requested: buffer size %d period size %d\n", |
dolog ("requested: buffer size %d period size %d\n", |
| 223 |
req->buffer_size, req->period_size); |
req->buffer_size, req->period_size); |
| 224 |
dolog ("obtained: buffer size %ld\n", obt->buffer_size); |
dolog ("obtained: samples %ld\n", obt->samples); |
| 225 |
} |
} |
| 226 |
#endif |
#endif |
| 227 |
|
|
| 234 |
|
|
| 235 |
err = snd_pcm_sw_params_current (handle, sw_params); |
err = snd_pcm_sw_params_current (handle, sw_params); |
| 236 |
if (err < 0) { |
if (err < 0) { |
| 237 |
dolog ("Can not fully initialize DAC\n"); |
dolog ("Could not fully initialize DAC\n"); |
| 238 |
alsa_logerr (err, "Failed to get current software parameters\n"); |
alsa_logerr (err, "Failed to get current software parameters\n"); |
| 239 |
return; |
return; |
| 240 |
} |
} |
| 241 |
|
|
| 242 |
err = snd_pcm_sw_params_set_start_threshold (handle, sw_params, threshold); |
err = snd_pcm_sw_params_set_start_threshold (handle, sw_params, threshold); |
| 243 |
if (err < 0) { |
if (err < 0) { |
| 244 |
dolog ("Can not fully initialize DAC\n"); |
dolog ("Could not fully initialize DAC\n"); |
| 245 |
alsa_logerr (err, "Failed to set software threshold to %ld\n", |
alsa_logerr (err, "Failed to set software threshold to %ld\n", |
| 246 |
threshold); |
threshold); |
| 247 |
return; |
return; |
| 249 |
|
|
| 250 |
err = snd_pcm_sw_params (handle, sw_params); |
err = snd_pcm_sw_params (handle, sw_params); |
| 251 |
if (err < 0) { |
if (err < 0) { |
| 252 |
dolog ("Can not fully initialize DAC\n"); |
dolog ("Could not fully initialize DAC\n"); |
| 253 |
alsa_logerr (err, "Failed to set software parameters\n"); |
alsa_logerr (err, "Failed to set software parameters\n"); |
| 254 |
return; |
return; |
| 255 |
} |
} |
| 344 |
handle, |
handle, |
| 345 |
hw_params, |
hw_params, |
| 346 |
&period_size, |
&period_size, |
| 347 |
0); |
0 |
| 348 |
|
); |
| 349 |
if (err < 0) { |
if (err < 0) { |
| 350 |
alsa_logerr2 (err, typ, |
alsa_logerr2 (err, typ, |
| 351 |
"Failed to set period time %d\n", |
"Failed to set period time %d\n", |
| 358 |
handle, |
handle, |
| 359 |
hw_params, |
hw_params, |
| 360 |
&buffer_size, |
&buffer_size, |
| 361 |
0); |
0 |
| 362 |
|
); |
| 363 |
|
|
| 364 |
if (err < 0) { |
if (err < 0) { |
| 365 |
alsa_logerr2 (err, typ, |
alsa_logerr2 (err, typ, |
| 384 |
if (err < 0) { |
if (err < 0) { |
| 385 |
alsa_logerr ( |
alsa_logerr ( |
| 386 |
err, |
err, |
| 387 |
"Can not get minmal period size for %s\n", |
"Could not get minmal period size for %s\n", |
| 388 |
typ |
typ |
| 389 |
); |
); |
| 390 |
} |
} |
| 421 |
&minval |
&minval |
| 422 |
); |
); |
| 423 |
if (err < 0) { |
if (err < 0) { |
| 424 |
alsa_logerr (err, "Can not get minmal buffer size for %s\n", |
alsa_logerr (err, "Could not get minmal buffer size for %s\n", |
| 425 |
typ); |
typ); |
| 426 |
} |
} |
| 427 |
else { |
else { |
| 453 |
} |
} |
| 454 |
} |
} |
| 455 |
else { |
else { |
| 456 |
dolog ("warning: buffer size is not set\n"); |
dolog ("warning: Buffer size is not set\n"); |
| 457 |
} |
} |
| 458 |
|
|
| 459 |
err = snd_pcm_hw_params (handle, hw_params); |
err = snd_pcm_hw_params (handle, hw_params); |
| 470 |
|
|
| 471 |
err = snd_pcm_prepare (handle); |
err = snd_pcm_prepare (handle); |
| 472 |
if (err < 0) { |
if (err < 0) { |
| 473 |
alsa_logerr2 (err, typ, "Can not prepare handle %p\n", handle); |
alsa_logerr2 (err, typ, "Could not prepare handle %p\n", handle); |
| 474 |
goto err; |
goto err; |
| 475 |
} |
} |
| 476 |
|
|
| 477 |
obt->can_pause = snd_pcm_hw_params_can_pause (hw_params); |
obt->can_pause = snd_pcm_hw_params_can_pause (hw_params); |
| 478 |
if (obt->can_pause < 0) { |
if (obt->can_pause < 0) { |
| 479 |
alsa_logerr (err, "Can not get pause capability for %s\n", typ); |
alsa_logerr (err, "Could not get pause capability for %s\n", typ); |
| 480 |
obt->can_pause = 0; |
obt->can_pause = 0; |
| 481 |
} |
} |
| 482 |
|
|
| 495 |
obt->fmt = req->fmt; |
obt->fmt = req->fmt; |
| 496 |
obt->nchannels = nchannels; |
obt->nchannels = nchannels; |
| 497 |
obt->freq = freq; |
obt->freq = freq; |
| 498 |
obt->buffer_size = snd_pcm_frames_to_bytes (handle, obt_buffer_size); |
obt->samples = obt_buffer_size; |
| 499 |
*handlep = handle; |
*handlep = handle; |
| 500 |
|
|
| 501 |
|
#if defined DEBUG_MISMATCHES || defined DEBUG |
| 502 |
if (obt->fmt != req->fmt || |
if (obt->fmt != req->fmt || |
| 503 |
obt->nchannels != req->nchannels || |
obt->nchannels != req->nchannels || |
| 504 |
obt->freq != req->freq) { |
obt->freq != req->freq) { |
|
#ifdef DEBUG_MISMATCHES |
|
| 505 |
dolog ("Audio paramters mismatch for %s\n", typ); |
dolog ("Audio paramters mismatch for %s\n", typ); |
| 506 |
alsa_dump_info (req, obt); |
alsa_dump_info (req, obt); |
|
#endif |
|
| 507 |
} |
} |
| 508 |
|
#endif |
| 509 |
|
|
| 510 |
#ifdef DEBUG |
#ifdef DEBUG |
| 511 |
alsa_dump_info (req, obt); |
alsa_dump_info (req, obt); |
| 552 |
} |
} |
| 553 |
} |
} |
| 554 |
|
|
| 555 |
alsa_logerr (avail, "Can not get amount free space\n"); |
alsa_logerr (avail, "Could not get amount free space\n"); |
| 556 |
return 0; |
return 0; |
| 557 |
} |
} |
| 558 |
|
|
| 620 |
} |
} |
| 621 |
} |
} |
| 622 |
|
|
| 623 |
static int alsa_init_out (HWVoiceOut *hw, int freq, int nchannels, audfmt_e fmt) |
static int alsa_init_out (HWVoiceOut *hw, audsettings_t *as) |
| 624 |
{ |
{ |
| 625 |
ALSAVoiceOut *alsa = (ALSAVoiceOut *) hw; |
ALSAVoiceOut *alsa = (ALSAVoiceOut *) hw; |
| 626 |
struct alsa_params_req req; |
struct alsa_params_req req; |
| 629 |
int endianness; |
int endianness; |
| 630 |
int err; |
int err; |
| 631 |
snd_pcm_t *handle; |
snd_pcm_t *handle; |
| 632 |
|
audsettings_t obt_as; |
| 633 |
|
|
| 634 |
req.fmt = aud_to_alsafmt (fmt); |
req.fmt = aud_to_alsafmt (as->fmt); |
| 635 |
req.freq = freq; |
req.freq = as->freq; |
| 636 |
req.nchannels = nchannels; |
req.nchannels = as->nchannels; |
| 637 |
req.period_size = conf.period_size_out; |
req.period_size = conf.period_size_out; |
| 638 |
req.buffer_size = conf.buffer_size_out; |
req.buffer_size = conf.buffer_size_out; |
| 639 |
|
|
| 647 |
return -1; |
return -1; |
| 648 |
} |
} |
| 649 |
|
|
| 650 |
|
obt_as.freq = obt.freq; |
| 651 |
|
obt_as.nchannels = obt.nchannels; |
| 652 |
|
obt_as.fmt = effective_fmt; |
| 653 |
|
|
| 654 |
audio_pcm_init_info ( |
audio_pcm_init_info ( |
| 655 |
&hw->info, |
&hw->info, |
| 656 |
obt.freq, |
&obt_as, |
|
obt.nchannels, |
|
|
effective_fmt, |
|
| 657 |
audio_need_to_swap_endian (endianness) |
audio_need_to_swap_endian (endianness) |
| 658 |
); |
); |
| 659 |
alsa->can_pause = obt.can_pause; |
alsa->can_pause = obt.can_pause; |
| 660 |
hw->bufsize = obt.buffer_size; |
hw->samples = obt.samples; |
| 661 |
|
|
| 662 |
alsa->pcm_buf = qemu_mallocz (hw->bufsize); |
alsa->pcm_buf = audio_calloc (AUDIO_FUNC, obt.samples, 1 << hw->info.shift); |
| 663 |
if (!alsa->pcm_buf) { |
if (!alsa->pcm_buf) { |
| 664 |
|
dolog ("Could not allocate DAC buffer (%d bytes)\n", |
| 665 |
|
hw->samples << hw->info.shift); |
| 666 |
alsa_anal_close (&handle); |
alsa_anal_close (&handle); |
| 667 |
return -1; |
return -1; |
| 668 |
} |
} |
| 710 |
return 0; |
return 0; |
| 711 |
} |
} |
| 712 |
|
|
| 713 |
static int alsa_init_in (HWVoiceIn *hw, |
static int alsa_init_in (HWVoiceIn *hw, audsettings_t *as) |
|
int freq, int nchannels, audfmt_e fmt) |
|
| 714 |
{ |
{ |
| 715 |
ALSAVoiceIn *alsa = (ALSAVoiceIn *) hw; |
ALSAVoiceIn *alsa = (ALSAVoiceIn *) hw; |
| 716 |
struct alsa_params_req req; |
struct alsa_params_req req; |
| 719 |
int err; |
int err; |
| 720 |
audfmt_e effective_fmt; |
audfmt_e effective_fmt; |
| 721 |
snd_pcm_t *handle; |
snd_pcm_t *handle; |
| 722 |
|
audsettings_t obt_as; |
| 723 |
|
|
| 724 |
req.fmt = aud_to_alsafmt (fmt); |
req.fmt = aud_to_alsafmt (as->fmt); |
| 725 |
req.freq = freq; |
req.freq = as->freq; |
| 726 |
req.nchannels = nchannels; |
req.nchannels = as->nchannels; |
| 727 |
req.period_size = conf.period_size_in; |
req.period_size = conf.period_size_in; |
| 728 |
req.buffer_size = conf.buffer_size_in; |
req.buffer_size = conf.buffer_size_in; |
| 729 |
|
|
| 737 |
return -1; |
return -1; |
| 738 |
} |
} |
| 739 |
|
|
| 740 |
|
obt_as.freq = obt.freq; |
| 741 |
|
obt_as.nchannels = obt.nchannels; |
| 742 |
|
obt_as.fmt = effective_fmt; |
| 743 |
|
|
| 744 |
audio_pcm_init_info ( |
audio_pcm_init_info ( |
| 745 |
&hw->info, |
&hw->info, |
| 746 |
obt.freq, |
&obt_as, |
|
obt.nchannels, |
|
|
effective_fmt, |
|
| 747 |
audio_need_to_swap_endian (endianness) |
audio_need_to_swap_endian (endianness) |
| 748 |
); |
); |
| 749 |
alsa->can_pause = obt.can_pause; |
alsa->can_pause = obt.can_pause; |
| 750 |
hw->bufsize = obt.buffer_size; |
hw->samples = obt.samples; |
| 751 |
alsa->pcm_buf = qemu_mallocz (hw->bufsize); |
|
| 752 |
|
alsa->pcm_buf = audio_calloc (AUDIO_FUNC, hw->samples, 1 << hw->info.shift); |
| 753 |
if (!alsa->pcm_buf) { |
if (!alsa->pcm_buf) { |
| 754 |
|
dolog ("Could not allocate ADC buffer (%d bytes)\n", |
| 755 |
|
hw->samples << hw->info.shift); |
| 756 |
alsa_anal_close (&handle); |
alsa_anal_close (&handle); |
| 757 |
return -1; |
return -1; |
| 758 |
} |
} |