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>
This commit is contained in:
parent
3daedf267d
commit
2a4af36614
|
@ -89,6 +89,7 @@ FHANDLER_FILES= \
|
|||
fhandler/dsp.cc \
|
||||
fhandler/fifo.cc \
|
||||
fhandler/floppy.cc \
|
||||
fhandler/mixer.cc \
|
||||
fhandler/mqueue.cc \
|
||||
fhandler/netdrive.cc \
|
||||
fhandler/nodevice.cc \
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -180,6 +180,7 @@ const _device dev_error_storage =
|
|||
"/dev/console", BRACK(FH_CONSOLE), "/dev/console", exists_console, S_IFCHR, =console_dev
|
||||
"/dev/ptmx", BRACK(FH_PTMX), "/dev/ptmx", exists, S_IFCHR
|
||||
"/dev/windows", BRACK(FH_WINDOWS), "\\Device\\Null", exists_ntdev, S_IFCHR
|
||||
"/dev/mixer", BRACK(FH_OSS_MIXER), "\\Device\\Null", exists_ntdev, S_IFCHR
|
||||
"/dev/dsp", BRACK(FH_OSS_DSP), "\\Device\\Null", exists_ntdev, S_IFCHR
|
||||
"/dev/conin", BRACK(FH_CONIN), "/dev/conin", exists_console, S_IFCHR
|
||||
"/dev/conout", BRACK(FH_CONOUT), "/dev/conout", exists_console, S_IFCHR
|
||||
|
|
|
@ -552,6 +552,9 @@ fh_alloc (path_conv& pc)
|
|||
case FH_CLIPBOARD:
|
||||
fh = cnew (fhandler_dev_clipboard);
|
||||
break;
|
||||
case FH_OSS_MIXER:
|
||||
fh = cnew (fhandler_dev_mixer);
|
||||
break;
|
||||
case FH_OSS_DSP:
|
||||
fh = cnew (fhandler_dev_dsp);
|
||||
break;
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -242,6 +242,7 @@ enum fh_devices
|
|||
FH_URANDOM = FHDEV (DEV_MEM_MAJOR, 9),
|
||||
|
||||
DEV_SOUND_MAJOR = 14,
|
||||
FH_OSS_MIXER = FHDEV (DEV_SOUND_MAJOR, 0),
|
||||
FH_OSS_DSP = FHDEV (DEV_SOUND_MAJOR, 3),
|
||||
|
||||
DEV_SOCK_MAJOR = 30,
|
||||
|
|
|
@ -2777,6 +2777,35 @@ class fhandler_windows: public fhandler_base
|
|||
}
|
||||
};
|
||||
|
||||
class fhandler_dev_mixer: public fhandler_base
|
||||
{
|
||||
private:
|
||||
int rec_source;
|
||||
public:
|
||||
fhandler_dev_mixer () {}
|
||||
int open (int, mode_t mode = 0);
|
||||
ssize_t write (const void *, size_t);
|
||||
void read (void *, size_t&);
|
||||
int ioctl (unsigned int, void *);
|
||||
|
||||
fhandler_dev_mixer (void *) {}
|
||||
|
||||
void copy_from (fhandler_base *x)
|
||||
{
|
||||
pc.free_strings ();
|
||||
*this = *reinterpret_cast<fhandler_dev_mixer *> (x);
|
||||
_copy_from_reset_helper ();
|
||||
}
|
||||
|
||||
fhandler_dev_mixer *clone (cygheap_types malloc_type = HEAP_FHANDLER)
|
||||
{
|
||||
void *ptr = (void *) ccalloc (malloc_type, 1, sizeof (fhandler_dev_mixer));
|
||||
fhandler_dev_mixer *fh = new (ptr) fhandler_dev_mixer (ptr);
|
||||
fh->copy_from (this);
|
||||
return fh;
|
||||
}
|
||||
};
|
||||
|
||||
class fhandler_dev_dsp: public fhandler_base
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -31,6 +31,8 @@ What's new:
|
|||
|
||||
- New API calls: c8rtomb, c16rtomb, c32rtomb, mbrtoc8, mbrtoc16, mbrtoc32.
|
||||
|
||||
- Implement OSS-based sound mixer device (/dev/mixer).
|
||||
|
||||
What changed:
|
||||
-------------
|
||||
|
||||
|
|
Loading…
Reference in New Issue