Modify OSS_Wave{In,Out}Init to report the exact capabilities of the

OSS driver.
Add support for the 48kHz and 96kHz formats.
This commit is contained in:
Francois Gouget 2003-01-11 22:47:51 +00:00 committed by Alexandre Julliard
parent e8a7ad3040
commit ce0557fe8e

View File

@ -405,24 +405,30 @@ static DWORD OSS_ResetDevice(OSS_DEVICE* ossdev)
return ret;
}
const static int win_std_oss_fmts[2]={AFMT_U8,AFMT_S16_LE};
const static int win_std_rates[5]={96000,48000,44100,22050,11025};
const static int win_std_formats[2][2][5]=
{{{WAVE_FORMAT_96M08, WAVE_FORMAT_48M08, WAVE_FORMAT_4M08,
WAVE_FORMAT_2M08, WAVE_FORMAT_1M08},
{WAVE_FORMAT_96S08, WAVE_FORMAT_48S08, WAVE_FORMAT_4S08,
WAVE_FORMAT_2S08, WAVE_FORMAT_1S08}},
{{WAVE_FORMAT_96M16, WAVE_FORMAT_48M16, WAVE_FORMAT_4M16,
WAVE_FORMAT_2M16, WAVE_FORMAT_1M16},
{WAVE_FORMAT_96S16, WAVE_FORMAT_48S16, WAVE_FORMAT_4S16,
WAVE_FORMAT_2S16, WAVE_FORMAT_1S16}},
};
/******************************************************************
* OSS_WaveOutInit
*
*
*/
static BOOL OSS_WaveOutInit(OSS_DEVICE* ossdev)
static BOOL OSS_WaveOutInit(OSS_DEVICE* ossdev)
{
int smplrate;
int samplesize = 16;
int dsp_stereo = 1;
int bytespersmpl;
int caps;
int mask;
int rc,arg;
int f,c,r;
if (OSS_OpenDevice(ossdev, O_WRONLY, NULL, 0, 0, 0, 0) != 0) return FALSE;
memset(&ossdev->out_caps, 0, sizeof(ossdev->out_caps));
ioctl(ossdev->fd, SNDCTL_DSP_RESET, 0);
/* FIXME: some programs compare this string against the content of the
@ -440,70 +446,68 @@ static BOOL OSS_WaveOutInit(OSS_DEVICE* ossdev)
strcpy(ossdev->out_caps.szPname, "CS4236/37/38");
#endif
ossdev->out_caps.vDriverVersion = 0x0100;
ossdev->out_caps.wChannels = 1;
ossdev->out_caps.dwFormats = 0x00000000;
ossdev->out_caps.wReserved1 = 0;
ossdev->out_caps.dwSupport = WAVECAPS_VOLUME;
ioctl(ossdev->fd, SNDCTL_DSP_GETFMTS, &mask);
TRACE("OSS dsp out mask=%08x\n", mask);
/* First bytespersampl, then stereo */
bytespersmpl = (ioctl(ossdev->fd, SNDCTL_DSP_SAMPLESIZE, &samplesize) != 0) ? 1 : 2;
ossdev->out_caps.wChannels = (ioctl(ossdev->fd, SNDCTL_DSP_STEREO, &dsp_stereo) != 0) ? 1 : 2;
if (ossdev->out_caps.wChannels > 1) ossdev->out_caps.dwSupport |= WAVECAPS_LRVOLUME;
smplrate = 44100;
if (ioctl(ossdev->fd, SNDCTL_DSP_SPEED, &smplrate) == 0) {
if (mask & AFMT_U8) {
ossdev->out_caps.dwFormats |= WAVE_FORMAT_4M08;
if (ossdev->out_caps.wChannels > 1)
ossdev->out_caps.dwFormats |= WAVE_FORMAT_4S08;
}
if ((mask & AFMT_S16_LE) && bytespersmpl > 1) {
ossdev->out_caps.dwFormats |= WAVE_FORMAT_4M16;
if (ossdev->out_caps.wChannels > 1)
ossdev->out_caps.dwFormats |= WAVE_FORMAT_4S16;
}
if (WINE_TRACE_ON(wave)) {
/* Note that this only reports the formats supported by the hardware.
* The driver may support other formats and do the conversions in
* software which is why we don't use this value
*/
int oss_mask;
ioctl(ossdev->fd, SNDCTL_DSP_GETFMTS, &oss_mask);
TRACE("OSS dsp out mask=%08x\n", oss_mask);
}
smplrate = 22050;
if (ioctl(ossdev->fd, SNDCTL_DSP_SPEED, &smplrate) == 0) {
if (mask & AFMT_U8) {
ossdev->out_caps.dwFormats |= WAVE_FORMAT_2M08;
if (ossdev->out_caps.wChannels > 1)
ossdev->out_caps.dwFormats |= WAVE_FORMAT_2S08;
}
if ((mask & AFMT_S16_LE) && bytespersmpl > 1) {
ossdev->out_caps.dwFormats |= WAVE_FORMAT_2M16;
if (ossdev->out_caps.wChannels > 1)
ossdev->out_caps.dwFormats |= WAVE_FORMAT_2S16;
}
/* We must first set the format and the stereo mode as some sound cards
* may support 44kHz mono but not 44kHz stereo. Also we must
* systematically check the return value of these ioctls as they will
* always succeed (see OSS Linux) but will modify the parameter to match
* whatever they support. The OSS specs also say we must first set the
* sample size, then the stereo and then the sample rate.
*/
for (f=0;f<2;f++) {
arg=win_std_oss_fmts[f];
rc=ioctl(ossdev->fd, SNDCTL_DSP_SAMPLESIZE, &arg);
if (rc!=0 || arg!=win_std_oss_fmts[f])
continue;
for (c=0;c<2;c++) {
arg=c;
rc=ioctl(ossdev->fd, SNDCTL_DSP_STEREO, &arg);
if (rc!=0 || arg!=c)
continue;
if (c==1) {
ossdev->out_caps.wChannels=2;
ossdev->out_caps.dwSupport|=WAVECAPS_LRVOLUME;
}
for (r=0;r<sizeof(win_std_rates)/sizeof(*win_std_rates);r++) {
arg=win_std_rates[r];
rc=ioctl(ossdev->fd, SNDCTL_DSP_SPEED, &arg);
TRACE("DSP_SPEED: rc=%d returned %d for %dx%dx%d\n",
rc,arg,win_std_rates[r],win_std_oss_fmts[f],c+1);
if (rc==0 && NEAR_MATCH(arg,win_std_rates[r]))
ossdev->out_caps.dwFormats|=win_std_formats[f][c][r];
}
}
}
smplrate = 11025;
if (ioctl(ossdev->fd, SNDCTL_DSP_SPEED, &smplrate) == 0) {
if (mask & AFMT_U8) {
ossdev->out_caps.dwFormats |= WAVE_FORMAT_1M08;
if (ossdev->out_caps.wChannels > 1)
ossdev->out_caps.dwFormats |= WAVE_FORMAT_1S08;
}
if ((mask & AFMT_S16_LE) && bytespersmpl > 1) {
ossdev->out_caps.dwFormats |= WAVE_FORMAT_1M16;
if (ossdev->out_caps.wChannels > 1)
ossdev->out_caps.dwFormats |= WAVE_FORMAT_1S16;
}
}
if (ioctl(ossdev->fd, SNDCTL_DSP_GETCAPS, &caps) == 0) {
TRACE("OSS dsp out caps=%08X\n", caps);
if ((caps & DSP_CAP_REALTIME) && !(caps & DSP_CAP_BATCH)) {
ossdev->out_caps.dwSupport |= WAVECAPS_SAMPLEACCURATE;
}
/* well, might as well use the DirectSound cap flag for something */
if ((caps & DSP_CAP_TRIGGER) && (caps & DSP_CAP_MMAP) &&
!(caps & DSP_CAP_BATCH))
ossdev->out_caps.dwSupport |= WAVECAPS_DIRECTSOUND;
if (ioctl(ossdev->fd, SNDCTL_DSP_GETCAPS, &arg) == 0) {
TRACE("OSS dsp out caps=%08X\n", arg);
if ((arg & DSP_CAP_REALTIME) && !(arg & DSP_CAP_BATCH)) {
ossdev->out_caps.dwSupport |= WAVECAPS_SAMPLEACCURATE;
}
/* well, might as well use the DirectSound cap flag for something */
if ((arg & DSP_CAP_TRIGGER) && (arg & DSP_CAP_MMAP) &&
!(arg & DSP_CAP_BATCH))
ossdev->out_caps.dwSupport |= WAVECAPS_DIRECTSOUND;
}
OSS_CloseDevice(ossdev);
TRACE("out dwFormats = %08lX, dwSupport = %08lX\n",
ossdev->out_caps.dwFormats, ossdev->out_caps.dwSupport);
ossdev->out_caps.dwFormats, ossdev->out_caps.dwSupport);
return TRUE;
}
@ -514,81 +518,68 @@ static BOOL OSS_WaveOutInit(OSS_DEVICE* ossdev)
*/
static BOOL OSS_WaveInInit(OSS_DEVICE* ossdev)
{
int smplrate;
int samplesize = 16;
int dsp_stereo = 1;
int bytespersmpl;
int caps;
int mask;
int rc,arg;
int f,c,r;
if (OSS_OpenDevice(ossdev, O_RDONLY, NULL, 0, 0, 0, 0) != 0) return FALSE;
memset(&ossdev->in_caps, 0, sizeof(ossdev->in_caps));
ioctl(ossdev->fd, SNDCTL_DSP_RESET, 0);
/* See comment in OSS_WaveOutInit */
#ifdef EMULATE_SB16
ossdev->in_caps.wMid = 0x0002;
ossdev->in_caps.wPid = 0x0004;
strcpy(ossdev->in_caps.szPname, "SB16 Wave In");
#else
ossdev->in_caps.wMid = 0x00FF; /* Manufac ID */
ossdev->in_caps.wPid = 0x0001; /* Product ID */
ossdev->in_caps.wMid = 0x00FF; /* Manufac ID */
ossdev->in_caps.wPid = 0x0001; /* Product ID */
strcpy(ossdev->in_caps.szPname, "OpenSoundSystem WAVIN Driver");
#endif
ossdev->in_caps.dwFormats = 0x00000000;
ossdev->in_caps.wChannels = (ioctl(ossdev->fd, SNDCTL_DSP_STEREO, &dsp_stereo) != 0) ? 1 : 2;
ossdev->in_caps.wChannels = 1;
ossdev->in_caps.wReserved1 = 0;
ossdev->bTriggerSupport = FALSE;
if (ioctl(ossdev->fd, SNDCTL_DSP_GETCAPS, &caps) == 0) {
TRACE("OSS dsp in caps=%08X\n", caps);
if (caps & DSP_CAP_TRIGGER)
if (WINE_TRACE_ON(wave)) {
/* Note that this only reports the formats supported by the hardware.
* The driver may support other formats and do the conversions in
* software which is why we don't use this value
*/
int oss_mask;
ioctl(ossdev->fd, SNDCTL_DSP_GETFMTS, &oss_mask);
TRACE("OSS dsp out mask=%08x\n", oss_mask);
}
/* See the comment in OSS_WaveOutInit */
for (f=0;f<2;f++) {
arg=win_std_oss_fmts[f];
rc=ioctl(ossdev->fd, SNDCTL_DSP_SAMPLESIZE, &arg);
if (rc!=0 || arg!=win_std_oss_fmts[f])
continue;
for (c=0;c<2;c++) {
arg=c;
rc=ioctl(ossdev->fd, SNDCTL_DSP_STEREO, &arg);
if (rc!=0 || arg!=c)
continue;
if (c==1) {
ossdev->in_caps.wChannels=2;
}
for (r=0;r<sizeof(win_std_rates)/sizeof(*win_std_rates);r++) {
arg=win_std_rates[r];
rc=ioctl(ossdev->fd, SNDCTL_DSP_SPEED, &arg);
TRACE("DSP_SPEED: rc=%d returned %d for %dx%dx%d\n",rc,arg,win_std_rates[r],win_std_oss_fmts[f],c+1);
if (rc==0 && NEAR_MATCH(arg,win_std_rates[r]))
ossdev->in_caps.dwFormats|=win_std_formats[f][c][r];
}
}
}
if (ioctl(ossdev->fd, SNDCTL_DSP_GETCAPS, &arg) == 0) {
TRACE("OSS dsp in caps=%08X\n", arg);
if (arg & DSP_CAP_TRIGGER)
ossdev->bTriggerSupport = TRUE;
}
ioctl(ossdev->fd, SNDCTL_DSP_GETFMTS, &mask);
TRACE("OSS in dsp mask=%08x\n", mask);
bytespersmpl = (ioctl(ossdev->fd, SNDCTL_DSP_SAMPLESIZE, &samplesize) != 0) ? 1 : 2;
smplrate = 44100;
if (ioctl(ossdev->fd, SNDCTL_DSP_SPEED, &smplrate) == 0) {
if (mask & AFMT_U8) {
ossdev->in_caps.dwFormats |= WAVE_FORMAT_4M08;
if (ossdev->in_caps.wChannels > 1)
ossdev->in_caps.dwFormats |= WAVE_FORMAT_4S08;
}
if ((mask & AFMT_S16_LE) && bytespersmpl > 1) {
ossdev->in_caps.dwFormats |= WAVE_FORMAT_4M16;
if (ossdev->in_caps.wChannels > 1)
ossdev->in_caps.dwFormats |= WAVE_FORMAT_4S16;
}
}
smplrate = 22050;
if (ioctl(ossdev->fd, SNDCTL_DSP_SPEED, &smplrate) == 0) {
if (mask & AFMT_U8) {
ossdev->in_caps.dwFormats |= WAVE_FORMAT_2M08;
if (ossdev->in_caps.wChannels > 1)
ossdev->in_caps.dwFormats |= WAVE_FORMAT_2S08;
}
if ((mask & AFMT_S16_LE) && bytespersmpl > 1) {
ossdev->in_caps.dwFormats |= WAVE_FORMAT_2M16;
if (ossdev->in_caps.wChannels > 1)
ossdev->in_caps.dwFormats |= WAVE_FORMAT_2S16;
}
}
smplrate = 11025;
if (ioctl(ossdev->fd, SNDCTL_DSP_SPEED, &smplrate) == 0) {
if (mask & AFMT_U8) {
ossdev->in_caps.dwFormats |= WAVE_FORMAT_1M08;
if (ossdev->in_caps.wChannels > 1)
ossdev->in_caps.dwFormats |= WAVE_FORMAT_1S08;
}
if ((mask & AFMT_S16_LE) && bytespersmpl > 1) {
ossdev->in_caps.dwFormats |= WAVE_FORMAT_1M16;
if (ossdev->in_caps.wChannels > 1)
ossdev->in_caps.dwFormats |= WAVE_FORMAT_1S16;
}
}
OSS_CloseDevice(ossdev);
TRACE("in dwFormats = %08lX\n", ossdev->in_caps.dwFormats);
return TRUE;