diff --git a/audio/ossaudio.c b/audio/ossaudio.c index e4f90f2029..f2385df5f1 100644 --- a/audio/ossaudio.c +++ b/audio/ossaudio.c @@ -31,6 +31,7 @@ #include #endif #include "qemu-common.h" +#include "qemu-char.h" #include "audio.h" #define AUDIO_CAP "oss" @@ -114,9 +115,36 @@ static void oss_anal_close (int *fdp) if (err) { oss_logerr (errno, "Failed to close file(fd=%d)\n", *fdp); } + qemu_set_fd_handler (*fdp, NULL, NULL, NULL); *fdp = -1; } +static void oss_helper_poll_out (void *opaque) +{ + (void) opaque; + audio_run ("oss_poll_out"); +} + +static void oss_helper_poll_in (void *opaque) +{ + (void) opaque; + audio_run ("oss_poll_in"); +} + +static int oss_poll_out (HWVoiceOut *hw) +{ + OSSVoiceOut *oss = (OSSVoiceOut *) hw; + + return qemu_set_fd_handler (oss->fd, NULL, oss_helper_poll_out, NULL); +} + +static int oss_poll_in (HWVoiceIn *hw) +{ + OSSVoiceIn *oss = (OSSVoiceIn *) hw; + + return qemu_set_fd_handler (oss->fd, oss_helper_poll_in, NULL, NULL); +} + static int oss_write (SWVoiceOut *sw, void *buf, int len) { return audio_pcm_sw_write (sw, buf, len); @@ -547,15 +575,26 @@ static int oss_init_out (HWVoiceOut *hw, struct audsettings *as) static int oss_ctl_out (HWVoiceOut *hw, int cmd, ...) { int trig; + va_list ap; + int poll_mode; OSSVoiceOut *oss = (OSSVoiceOut *) hw; - if (!oss->mmapped) { - return 0; - } + va_start (ap, cmd); + poll_mode = va_arg (ap, int); + va_end (ap); switch (cmd) { case VOICE_ENABLE: ldebug ("enabling voice\n"); + if (poll_mode && oss_poll_out (hw)) { + poll_mode = 0; + } + hw->poll_mode = poll_mode; + + if (!oss->mmapped) { + return 0; + } + audio_pcm_info_clear_buf (&hw->info, oss->pcm_buf, hw->samples); trig = PCM_ENABLE_OUTPUT; if (ioctl (oss->fd, SNDCTL_DSP_SETTRIGGER, &trig) < 0) { @@ -568,6 +607,15 @@ static int oss_ctl_out (HWVoiceOut *hw, int cmd, ...) break; case VOICE_DISABLE: + if (hw->poll_mode) { + qemu_set_fd_handler (oss->fd, NULL, NULL, NULL); + hw->poll_mode = 0; + } + + if (!oss->mmapped) { + return 0; + } + ldebug ("disabling voice\n"); trig = 0; if (ioctl (oss->fd, SNDCTL_DSP_SETTRIGGER, &trig) < 0) { @@ -723,8 +771,29 @@ static int oss_read (SWVoiceIn *sw, void *buf, int size) static int oss_ctl_in (HWVoiceIn *hw, int cmd, ...) { - (void) hw; - (void) cmd; + va_list ap; + int poll_mode; + OSSVoiceIn *oss = (OSSVoiceIn *) hw; + + va_start (ap, cmd); + poll_mode = va_arg (ap, int); + va_end (ap); + + switch (cmd) { + case VOICE_ENABLE: + if (poll_mode && oss_poll_in (hw)) { + poll_mode = 0; + } + hw->poll_mode = poll_mode; + break; + + case VOICE_DISABLE: + if (hw->poll_mode) { + hw->poll_mode = 0; + qemu_set_fd_handler (oss->fd, NULL, NULL, NULL); + } + break; + } return 0; }