oss: poll mode handling
authormalc <av1474@comtv.ru>
Fri, 11 Sep 2009 22:29:16 +0000 (02:29 +0400)
committermalc <av1474@comtv.ru>
Fri, 11 Sep 2009 22:50:58 +0000 (02:50 +0400)
Signed-off-by: malc <av1474@comtv.ru>
audio/ossaudio.c

index e4f90f20297cfdf41b2c024129cddb46903fd429..f2385df5f1c70cec3c47e4c91478cbc0953f2758 100644 (file)
@@ -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;
 }