Currently, if the device does not have capability WAVECAPS_LRVOLUME,
the volume control does not work properly. This patch fixes that.

Fixes: 2a4af3661470 ("Cygwin: Implement sound mixer device.")
Signed-off-by: Takashi Yano <takashi.y...@nifty.ne.jp>
---
 winsup/cygwin/autoload.cc       |  2 ++
 winsup/cygwin/fhandler/mixer.cc | 14 +++++++++++++-
 2 files changed, 15 insertions(+), 1 deletion(-)

diff --git a/winsup/cygwin/autoload.cc b/winsup/cygwin/autoload.cc
index c262c7efb..7e882ef1e 100644
--- a/winsup/cygwin/autoload.cc
+++ b/winsup/cygwin/autoload.cc
@@ -603,6 +603,8 @@ LoadDLLfuncEx3 (waveOutReset, winmm, 1, 0, 1)
 LoadDLLfuncEx3 (waveOutSetVolume, winmm, 1, 0, 1)
 LoadDLLfuncEx3 (waveOutUnprepareHeader, winmm, 1, 0, 1)
 LoadDLLfuncEx3 (waveOutWrite, winmm, 1, 0, 1)
+LoadDLLfuncEx3 (waveOutMessage, winmm, 1, 0, 1)
+LoadDLLfuncEx3 (waveOutGetDevCapsA, winmm, 1, 0, 1)
 
 LoadDLLfunc (accept, ws2_32)
 LoadDLLfunc (bind, ws2_32)
diff --git a/winsup/cygwin/fhandler/mixer.cc b/winsup/cygwin/fhandler/mixer.cc
index fabd397b7..f4997f952 100644
--- a/winsup/cygwin/fhandler/mixer.cc
+++ b/winsup/cygwin/fhandler/mixer.cc
@@ -15,6 +15,7 @@ details. */
 #include "fhandler.h"
 #include "dtable.h"
 #include "cygheap.h"
+#include <mmddk.h>
 
 ssize_t
 fhandler_dev_mixer::write (const void *ptr, size_t len)
@@ -88,7 +89,9 @@ int
 fhandler_dev_mixer::ioctl (unsigned int cmd, void *buf)
 {
   int ret = 0;
+  DWORD id, flag;
   DWORD vol;
+  WAVEOUTCAPS woc;
   switch (cmd)
     {
     case SOUND_MIXER_READ_DEVMASK:
@@ -115,7 +118,12 @@ fhandler_dev_mixer::ioctl (unsigned int cmd, void *buf)
       *(int *) buf = 1 << rec_source;
       break;
     case MIXER_WRITE (SOUND_MIXER_VOLUME):
+      waveOutMessage ((HWAVEOUT)WAVE_MAPPER, DRVM_MAPPER_PREFERRED_GET,
+                     (DWORD_PTR)&id, (DWORD_PTR)&flag);
+      waveOutGetDevCaps ((UINT)id, &woc, sizeof (woc));
       vol = volume_oss_to_winmm (*(int *) buf);
+      if (!(woc.dwSupport & WAVECAPS_LRVOLUME))
+       vol = max(vol & 0xffff, (vol >> 16) & 0xffff);
       if (waveOutSetVolume ((HWAVEOUT)WAVE_MAPPER, vol) != MMSYSERR_NOERROR)
        {
          set_errno (EINVAL);
@@ -123,13 +131,17 @@ fhandler_dev_mixer::ioctl (unsigned int cmd, void *buf)
        }
       break;
     case MIXER_READ (SOUND_MIXER_VOLUME):
-      DWORD vol;
+      waveOutMessage ((HWAVEOUT)WAVE_MAPPER, DRVM_MAPPER_PREFERRED_GET,
+                     (DWORD_PTR)&id, (DWORD_PTR)&flag);
+      waveOutGetDevCaps ((UINT)id, &woc, sizeof (woc));
       if (waveOutGetVolume ((HWAVEOUT)WAVE_MAPPER, &vol) != MMSYSERR_NOERROR)
        {
          set_errno (EINVAL);
          ret = -1;
          break;
        }
+      if (!(woc.dwSupport & WAVECAPS_LRVOLUME))
+       vol |= (vol & 0xffff) << 16;
       *(int *) buf = volume_winmm_to_oss (vol);
       break;
     default:
-- 
2.45.1

Reply via email to