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 |
} |
} |