aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--audio/ossaudio.c79
1 files changed, 74 insertions, 5 deletions
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 <sys/soundcard.h>
#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;
}