*/
#include <alsa/asoundlib.h>
#include "qemu-common.h"
-#include "qemu-char.h"
+#include "qemu/main-loop.h"
#include "audio.h"
#if QEMU_GNUC_PREREQ(4, 3)
for (i = 0; i < hlp->count; ++i) {
qemu_set_fd_handler (pfds[i].fd, NULL, NULL, NULL);
}
- qemu_free (pfds);
+ g_free (pfds);
}
hlp->pfds = NULL;
hlp->count = 0;
if (err < 0) {
alsa_logerr (err, "Could not initialize poll mode\n"
"Could not obtain poll descriptors\n");
- qemu_free (pfds);
+ g_free (pfds);
return -1;
}
while (i--) {
qemu_set_fd_handler (pfds[i].fd, NULL, NULL, NULL);
}
- qemu_free (pfds);
+ g_free (pfds);
return -1;
}
}
return audio_pcm_sw_write (sw, buf, len);
}
-static snd_pcm_format_t aud_to_alsafmt (audfmt_e fmt)
+static snd_pcm_format_t aud_to_alsafmt (audfmt_e fmt, int endianness)
{
switch (fmt) {
case AUD_FMT_S8:
return SND_PCM_FORMAT_U8;
case AUD_FMT_S16:
- return SND_PCM_FORMAT_S16_LE;
+ if (endianness) {
+ return SND_PCM_FORMAT_S16_BE;
+ }
+ else {
+ return SND_PCM_FORMAT_S16_LE;
+ }
case AUD_FMT_U16:
- return SND_PCM_FORMAT_U16_LE;
+ if (endianness) {
+ return SND_PCM_FORMAT_U16_BE;
+ }
+ else {
+ return SND_PCM_FORMAT_U16_LE;
+ }
case AUD_FMT_S32:
- return SND_PCM_FORMAT_S32_LE;
+ if (endianness) {
+ return SND_PCM_FORMAT_S32_BE;
+ }
+ else {
+ return SND_PCM_FORMAT_S32_LE;
+ }
case AUD_FMT_U32:
- return SND_PCM_FORMAT_U32_LE;
+ if (endianness) {
+ return SND_PCM_FORMAT_U32_BE;
+ }
+ else {
+ return SND_PCM_FORMAT_U32_LE;
+ }
default:
dolog ("Internal logic error: Bad audio format %d\n", fmt);
alsa_anal_close (&alsa->handle, &alsa->pollhlp);
if (alsa->pcm_buf) {
- qemu_free (alsa->pcm_buf);
+ g_free (alsa->pcm_buf);
alsa->pcm_buf = NULL;
}
}
snd_pcm_t *handle;
struct audsettings obt_as;
- req.fmt = aud_to_alsafmt (as->fmt);
+ req.fmt = aud_to_alsafmt (as->fmt, as->endianness);
req.freq = as->freq;
req.nchannels = as->nchannels;
req.period_size = conf.period_size_out;
return 0;
}
-static int alsa_voice_ctl (snd_pcm_t *handle, const char *typ, int pause)
+#define VOICE_CTL_PAUSE 0
+#define VOICE_CTL_PREPARE 1
+#define VOICE_CTL_START 2
+
+static int alsa_voice_ctl (snd_pcm_t *handle, const char *typ, int ctl)
{
int err;
- if (pause) {
+ if (ctl == VOICE_CTL_PAUSE) {
err = snd_pcm_drop (handle);
if (err < 0) {
alsa_logerr (err, "Could not stop %s\n", typ);
alsa_logerr (err, "Could not prepare handle for %s\n", typ);
return -1;
}
+ if (ctl == VOICE_CTL_START) {
+ err = snd_pcm_start(handle);
+ if (err < 0) {
+ alsa_logerr (err, "Could not start handle for %s\n", typ);
+ return -1;
+ }
+ }
}
return 0;
poll_mode = 0;
}
hw->poll_mode = poll_mode;
- return alsa_voice_ctl (alsa->handle, "playback", 0);
+ return alsa_voice_ctl (alsa->handle, "playback", VOICE_CTL_PREPARE);
}
case VOICE_DISABLE:
ldebug ("disabling voice\n");
- return alsa_voice_ctl (alsa->handle, "playback", 1);
+ if (hw->poll_mode) {
+ hw->poll_mode = 0;
+ alsa_fini_poll (&alsa->pollhlp);
+ }
+ return alsa_voice_ctl (alsa->handle, "playback", VOICE_CTL_PAUSE);
}
return -1;
snd_pcm_t *handle;
struct audsettings obt_as;
- req.fmt = aud_to_alsafmt (as->fmt);
+ req.fmt = aud_to_alsafmt (as->fmt, as->endianness);
req.freq = as->freq;
req.nchannels = as->nchannels;
req.period_size = conf.period_size_in;
alsa_anal_close (&alsa->handle, &alsa->pollhlp);
if (alsa->pcm_buf) {
- qemu_free (alsa->pcm_buf);
+ g_free (alsa->pcm_buf);
alsa->pcm_buf = NULL;
}
}
}
}
- hw->conv (dst, src, nread, &nominal_volume);
+ hw->conv (dst, src, nread);
src = advance (src, nread << hwshift);
dst += nread;
}
hw->poll_mode = poll_mode;
- return alsa_voice_ctl (alsa->handle, "capture", 0);
+ return alsa_voice_ctl (alsa->handle, "capture", VOICE_CTL_START);
}
case VOICE_DISABLE:
hw->poll_mode = 0;
alsa_fini_poll (&alsa->pollhlp);
}
- return alsa_voice_ctl (alsa->handle, "capture", 1);
+ return alsa_voice_ctl (alsa->handle, "capture", VOICE_CTL_PAUSE);
}
return -1;