Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTakashi Yano <takashi.yano@nifty.ne.jp>2023-09-01 11:41:10 +0300
committerTakashi Yano <takashi.yano@nifty.ne.jp>2023-09-01 15:33:38 +0300
commit2a4af36614705e5499683aa2f63dfe499edce6b7 (patch)
tree17defa71a6450e7d62210b39d017f109831e2559 /winsup/cygwin/fhandler
parent3daedf267d5b4940355fd370538d3036016efeda (diff)
Cygwin: Implement sound mixer device.
This patch adds implementation of OSS-based sound mixer device. This allows applications to change the sound playing volume. NOTE: Currently, the recording volume cannot be changed. Reviewed-by: Corinna Vinschen <corinna@vinschen.de> Signed-off-by: Takashi Yano <takashi.yano@nifty.ne.jp>
Diffstat (limited to 'winsup/cygwin/fhandler')
-rw-r--r--winsup/cygwin/fhandler/mixer.cc152
1 files changed, 152 insertions, 0 deletions
diff --git a/winsup/cygwin/fhandler/mixer.cc b/winsup/cygwin/fhandler/mixer.cc
new file mode 100644
index 000000000..fabd397b7
--- /dev/null
+++ b/winsup/cygwin/fhandler/mixer.cc
@@ -0,0 +1,152 @@
+/* fhandler_dev_mixer: code to emulate OSS sound model /dev/mixer
+
+ Written by Takashi Yano <takashi.yano@nifty.ne.jp>
+
+This file is part of Cygwin.
+
+This software is a copyrighted work licensed under the terms of the
+Cygwin license. Please consult the file "CYGWIN_LICENSE" for
+details. */
+
+#include "winsup.h"
+#include <sys/soundcard.h>
+#include "cygerrno.h"
+#include "path.h"
+#include "fhandler.h"
+#include "dtable.h"
+#include "cygheap.h"
+
+ssize_t
+fhandler_dev_mixer::write (const void *ptr, size_t len)
+{
+ set_errno (EINVAL);
+ return -1;
+}
+
+void
+fhandler_dev_mixer::read (void *ptr, size_t& len)
+{
+ len = -1;
+ set_errno (EINVAL);
+}
+
+int
+fhandler_dev_mixer::open (int flags, mode_t)
+{
+ int ret = -1, err = 0;
+ switch (flags & O_ACCMODE)
+ {
+ case O_RDWR:
+ case O_WRONLY:
+ case O_RDONLY:
+ if (waveInGetNumDevs () == 0 && waveOutGetNumDevs () == 0)
+ err = ENXIO;
+ break;
+ default:
+ err = EINVAL;
+ }
+
+ if (err)
+ set_errno (err);
+ else
+ {
+ ret = open_null (flags);
+ rec_source = SOUND_MIXER_MIC;
+ }
+
+ return ret;
+}
+
+static DWORD
+volume_oss_to_winmm (int vol_oss)
+{
+ unsigned int vol_l, vol_r;
+ DWORD vol_winmm;
+
+ vol_l = ((unsigned int) vol_oss) & 0xff;
+ vol_r = ((unsigned int) vol_oss) >> 8;
+ vol_l = min ((vol_l * 65535 + 50) / 100, 65535);
+ vol_r = min ((vol_r * 65535 + 50) / 100, 65535);
+ vol_winmm = (vol_r << 16) | vol_l;
+
+ return vol_winmm;
+}
+
+static int
+volume_winmm_to_oss (DWORD vol_winmm)
+{
+ int vol_l, vol_r;
+
+ vol_l = vol_winmm & 0xffff;
+ vol_r = vol_winmm >> 16;
+ vol_l = min ((vol_l * 100 + 32768) / 65535, 100);
+ vol_r = min ((vol_r * 100 + 32768) / 65535, 100);
+ return (vol_r << 8) | vol_l;
+}
+
+int
+fhandler_dev_mixer::ioctl (unsigned int cmd, void *buf)
+{
+ int ret = 0;
+ DWORD vol;
+ switch (cmd)
+ {
+ case SOUND_MIXER_READ_DEVMASK:
+ *(int *) buf = SOUND_MASK_VOLUME | SOUND_MASK_MIC | SOUND_MASK_LINE;
+ break;
+ case SOUND_MIXER_READ_RECMASK:
+ *(int *) buf = SOUND_MASK_MIC | SOUND_MASK_LINE;
+ break;
+ case SOUND_MIXER_READ_STEREODEVS:
+ *(int *) buf = SOUND_MASK_VOLUME | SOUND_MASK_LINE;
+ break;
+ case SOUND_MIXER_READ_CAPS:
+ *(int *) buf = SOUND_CAP_EXCL_INPUT;
+ break;
+ case MIXER_WRITE (SOUND_MIXER_RECSRC):
+ /* Dummy implementation */
+ if (*(int *) buf == 0 || ((*(int *) buf) & SOUND_MASK_MIC))
+ rec_source = SOUND_MIXER_MIC;
+ else if ((*(int *) buf) & SOUND_MASK_LINE)
+ rec_source = SOUND_MIXER_LINE;
+ break;
+ case MIXER_READ (SOUND_MIXER_RECSRC):
+ /* Dummy implementation */
+ *(int *) buf = 1 << rec_source;
+ break;
+ case MIXER_WRITE (SOUND_MIXER_VOLUME):
+ vol = volume_oss_to_winmm (*(int *) buf);
+ if (waveOutSetVolume ((HWAVEOUT)WAVE_MAPPER, vol) != MMSYSERR_NOERROR)
+ {
+ set_errno (EINVAL);
+ ret = -1;
+ }
+ break;
+ case MIXER_READ (SOUND_MIXER_VOLUME):
+ DWORD vol;
+ if (waveOutGetVolume ((HWAVEOUT)WAVE_MAPPER, &vol) != MMSYSERR_NOERROR)
+ {
+ set_errno (EINVAL);
+ ret = -1;
+ break;
+ }
+ *(int *) buf = volume_winmm_to_oss (vol);
+ break;
+ default:
+ for (int i = 0; i < SOUND_MIXER_NRDEVICES; i++)
+ {
+ if (cmd == (unsigned int) MIXER_WRITE (i))
+ goto out;
+ if (cmd == (unsigned int) MIXER_READ (i))
+ {
+ *(int *) buf = 0;
+ goto out;
+ }
+ }
+ set_errno (EINVAL);
+ ret = -1;
+ break;
+ }
+out:
+ return ret;
+}