Commit dcb44969 authored by Eric Pouech's avatar Eric Pouech Committed by Alexandre Julliard

Added support for several soundcard.

Remove non full duplex mode in code. OSS Commercial doesn't properly handle SNDCTL_DSP_RESET, so close/open device to workaround this issue (by Ove Kaaven).
parent 60f21c3d
......@@ -5,6 +5,7 @@
* Copyright 1994 Martin Ayotte
* 1999 Eric Pouech (async playing in waveOut/waveIn)
* 2000 Eric Pouech (loops in waveOut)
* 2002 Eric Pouech (full duplex)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
......@@ -23,8 +24,6 @@
/*
* FIXME:
* pause in waveOut does not work correctly in loop mode
* experimental full duplex mode
* only one sound card is currently supported
*/
/*#define EMULATE_SB16*/
......@@ -73,7 +72,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(wave);
#ifdef HAVE_OSS
#define MAX_WAVEDRV (1)
#define MAX_WAVEDRV (3)
/* state diagram for waveOut writing:
*
......@@ -144,8 +143,26 @@ typedef struct {
CRITICAL_SECTION msg_crst;
} OSS_MSG_RING;
typedef struct tagOSS_DEVICE {
const char* dev_name;
const char* mixer_name;
unsigned open_count;
WAVEOUTCAPSA out_caps;
WAVEINCAPSA in_caps;
unsigned open_access;
int fd;
DWORD owner_tid;
unsigned sample_rate;
unsigned stereo;
unsigned format;
unsigned audio_fragment;
BOOL full_duplex;
} OSS_DEVICE;
static OSS_DEVICE OSS_Devices[MAX_WAVEDRV];
typedef struct {
int unixdev;
OSS_DEVICE* ossdev;
volatile int state; /* one of the WINE_WS_ manifest constants */
WAVEOPENDESC waveDesc;
WORD wFlags;
......@@ -177,7 +194,7 @@ typedef struct {
} WINE_WAVEOUT;
typedef struct {
int unixdev;
OSS_DEVICE* ossdev;
volatile int state;
DWORD dwFragmentSize; /* OpenSound '/dev/dsp' give us that size */
WAVEOPENDESC waveDesc;
......@@ -215,27 +232,55 @@ static const char *wodPlayerCmdString[] = {
/*======================================================================*
* Low level WAVE implementation *
*======================================================================*/
#define USE_FULLDUPLEX
typedef struct tagOSS_DEVICE {
const char* dev_name;
const char* mixer_name;
unsigned open_count;
WAVEOUTCAPSA out_caps;
WAVEINCAPSA in_caps;
#ifdef USE_FULLDUPLEX
unsigned open_access;
int fd;
DWORD owner_tid;
unsigned sample_rate;
unsigned stereo;
unsigned format;
unsigned audio_fragment;
#endif
BOOL full_duplex;
} OSS_DEVICE;
/******************************************************************
* OSS_RawOpenDevice
*
* Low level device opening (from values stored in ossdev)
*/
static int OSS_RawOpenDevice(OSS_DEVICE* ossdev, int* frag)
{
int fd, val;
if ((fd = open(ossdev->dev_name, ossdev->open_access|O_NDELAY, 0)) == -1)
{
WARN("Couldn't open out %s (%s)\n", ossdev->dev_name, strerror(errno));
return (errno == EBUSY) ? MMSYSERR_ALLOCATED : MMSYSERR_ERROR;
}
fcntl(fd, F_SETFD, 1); /* set close on exec flag */
/* turn full duplex on if it has been requested */
if (ossdev->open_access == O_RDWR && ossdev->full_duplex)
ioctl(fd, SNDCTL_DSP_SETDUPLEX, 0);
OSS_DEVICE OSS_Devices[MAX_WAVEDRV];
if (ossdev->audio_fragment)
{
ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &ossdev->audio_fragment);
}
/* First size and stereo then samplerate */
if (ossdev->format)
{
val = ossdev->format;
ioctl(fd, SNDCTL_DSP_SETFMT, &val);
if (val != ossdev->format)
ERR("Can't set format to %d (%d)\n", ossdev->format, val);
}
if (ossdev->stereo)
{
val = ossdev->stereo;
ioctl(fd, SNDCTL_DSP_STEREO, &val);
if (val != ossdev->stereo)
ERR("Can't set stereo to %u (%d)\n", ossdev->stereo, val);
}
if (ossdev->sample_rate)
{
val = ossdev->sample_rate;
ioctl(fd, SNDCTL_DSP_SPEED, &ossdev->sample_rate);
if (!NEAR_MATCH(val, ossdev->sample_rate))
ERR("Can't set sample_rate to %u (%d)\n", ossdev->sample_rate, val);
}
return fd;
}
/******************************************************************
* OSS_OpenDevice
......@@ -244,71 +289,29 @@ OSS_DEVICE OSS_Devices[MAX_WAVEDRV];
* open the device for both waveout and wavein streams...
* this is hackish, but it's the way OSS interface is done...
*/
static DWORD OSS_OpenDevice(unsigned wDevID, int* pfd, unsigned req_access,
static DWORD OSS_OpenDevice(OSS_DEVICE* ossdev, unsigned req_access,
int* frag, int sample_rate, int stereo, int fmt)
{
OSS_DEVICE* ossdev;
int val;
int fd = -1;
if (wDevID >= MAX_WAVEDRV) return MMSYSERR_BADDEVICEID;
ossdev = &OSS_Devices[wDevID];
if (ossdev->full_duplex && (req_access == O_RDONLY || req_access == O_WRONLY))
req_access = O_RDWR;
/* FIXME: race with close */
/* FIXME: this should be protected, and it also contains a race with OSS_CloseDevice */
if (ossdev->open_count == 0)
{
if (access(ossdev->dev_name, 0) != 0) return MMSYSERR_NODRIVER;
if ((fd = open(ossdev->dev_name, req_access|O_NDELAY, 0)) == -1)
{
WARN("Couldn't open out %s (%s)\n", ossdev->dev_name, strerror(errno));
return (errno == EBUSY) ? MMSYSERR_ALLOCATED : MMSYSERR_ERROR;
}
fcntl(fd, F_SETFD, 1); /* set close on exec flag */
/* turn full duplex on if it has been requested */
if (req_access == O_RDWR && ossdev->full_duplex)
ioctl(fd, SNDCTL_DSP_SETDUPLEX, 0);
if (frag) ioctl(fd, SNDCTL_DSP_SETFRAGMENT, frag);
/* First size and stereo then samplerate */
if (fmt)
{
val = fmt;
ioctl(fd, SNDCTL_DSP_SETFMT, &val);
if (val != fmt)
ERR("Can't set format to %d (%d)\n", fmt, val);
}
if (stereo)
{
val = stereo;
ioctl(fd, SNDCTL_DSP_STEREO, &val);
if (val != stereo)
ERR("Can't set stereo to %u (%d)\n", stereo, val);
}
if (sample_rate)
{
val = sample_rate;
ioctl(fd, SNDCTL_DSP_SPEED, &sample_rate);
if (!NEAR_MATCH(val, sample_rate))
ERR("Can't set sample_rate to %u (%d)\n", sample_rate, val);
}
#ifdef USE_FULLDUPLEX
ossdev->audio_fragment = (frag) ? *frag : 0;
ossdev->sample_rate = sample_rate;
ossdev->stereo = stereo;
ossdev->format = fmt;
ossdev->open_access = req_access;
ossdev->owner_tid = GetCurrentThreadId();
ossdev->fd = fd;
#endif
if ((ossdev->fd = OSS_RawOpenDevice(ossdev, frag)) == -1)
return MMSYSERR_ERROR;
}
else
{
#ifdef USE_FULLDUPLEX
/* check we really open with the same parameters */
if (ossdev->open_access != req_access)
{
......@@ -337,13 +340,10 @@ static DWORD OSS_OpenDevice(unsigned wDevID, int* pfd, unsigned req_access,
WARN("Another thread is trying to access audio...\n");
return MMSYSERR_ERROR;
}
#endif
}
#ifdef USE_FULLDUPLEX
ossdev->open_count++;
#endif
*pfd = fd;
return MMSYSERR_NOERROR;
}
......@@ -352,19 +352,30 @@ static DWORD OSS_OpenDevice(unsigned wDevID, int* pfd, unsigned req_access,
*
*
*/
static void OSS_CloseDevice(unsigned wDevID, int fd)
static void OSS_CloseDevice(OSS_DEVICE* ossdev)
{
OSS_DEVICE* ossdev;
if (wDevID >= MAX_WAVEDRV) return;
#ifdef USE_FULLDUPLEX
ossdev = &OSS_Devices[wDevID];
if (fd != ossdev->fd) FIXME("What the heck????\n");
if (--ossdev->open_count == 0) close(ossdev->fd);
#else
/* wDevID: is not used yet, we handle only one global device /dev/dsp */
close(fd);
#endif
}
/******************************************************************
* OSS_ResetDevice
*
* Resets the device. OSS Commercial requires the device to be closed
* after a SNDCTL_DSP_RESET ioctl call... this function implements
* this behavior...
*/
static int OSS_ResetDevice(OSS_DEVICE* ossdev)
{
if (ioctl(ossdev->fd, SNDCTL_DSP_RESET, NULL) == -1)
{
perror("ioctl SNDCTL_DSP_RESET");
return -1;
}
TRACE("Changing fd from %d to ", ossdev->fd);
close(ossdev->fd);
OSS_RawOpenDevice(ossdev, &ossdev->audio_fragment);
TRACE("%d\n", ossdev->fd);
return ossdev->fd;
}
/******************************************************************
......@@ -374,7 +385,6 @@ static void OSS_CloseDevice(unsigned wDevID, int fd)
*/
static void OSS_WaveOutInit(unsigned devID, OSS_DEVICE* ossdev)
{
int audio;
int smplrate;
int samplesize = 16;
int dsp_stereo = 1;
......@@ -382,13 +392,14 @@ static void OSS_WaveOutInit(unsigned devID, OSS_DEVICE* ossdev)
int caps;
int mask;
WOutDev[devID].unixdev = -1;
WOutDev[devID].state = WINE_WS_CLOSED;
WOutDev[devID].ossdev = ossdev;
memset(&ossdev->out_caps, 0, sizeof(ossdev->out_caps));
if (OSS_OpenDevice(devID, &audio, O_WRONLY, NULL, 0, 0, 0) != 0) return;
if (OSS_OpenDevice(WOutDev[devID].ossdev, O_WRONLY, NULL, 0, 0, 0) != 0) return;
numOutDev++;
ioctl(audio, SNDCTL_DSP_RESET, 0);
ioctl(ossdev->fd, SNDCTL_DSP_RESET, 0);
/* FIXME: some programs compare this string against the content of the registry
* for MM drivers. The names have to match in order for the program to work
......@@ -408,17 +419,17 @@ static void OSS_WaveOutInit(unsigned devID, OSS_DEVICE* ossdev)
ossdev->out_caps.dwFormats = 0x00000000;
ossdev->out_caps.dwSupport = WAVECAPS_VOLUME;
ioctl(audio, SNDCTL_DSP_GETFMTS, &mask);
ioctl(ossdev->fd, SNDCTL_DSP_GETFMTS, &mask);
TRACE("OSS dsp out mask=%08x\n", mask);
/* First bytespersampl, then stereo */
bytespersmpl = (ioctl(audio, SNDCTL_DSP_SAMPLESIZE, &samplesize) != 0) ? 1 : 2;
bytespersmpl = (ioctl(ossdev->fd, SNDCTL_DSP_SAMPLESIZE, &samplesize) != 0) ? 1 : 2;
ossdev->out_caps.wChannels = (ioctl(audio, SNDCTL_DSP_STEREO, &dsp_stereo) != 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(audio, SNDCTL_DSP_SPEED, &smplrate) == 0) {
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)
......@@ -431,7 +442,7 @@ static void OSS_WaveOutInit(unsigned devID, OSS_DEVICE* ossdev)
}
}
smplrate = 22050;
if (ioctl(audio, SNDCTL_DSP_SPEED, &smplrate) == 0) {
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)
......@@ -444,7 +455,7 @@ static void OSS_WaveOutInit(unsigned devID, OSS_DEVICE* ossdev)
}
}
smplrate = 11025;
if (ioctl(audio, SNDCTL_DSP_SPEED, &smplrate) == 0) {
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)
......@@ -456,7 +467,7 @@ static void OSS_WaveOutInit(unsigned devID, OSS_DEVICE* ossdev)
ossdev->out_caps.dwFormats |= WAVE_FORMAT_1S16;
}
}
if (ioctl(audio, SNDCTL_DSP_GETCAPS, &caps) == 0) {
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;
......@@ -466,7 +477,7 @@ static void OSS_WaveOutInit(unsigned devID, OSS_DEVICE* ossdev)
!(caps & DSP_CAP_BATCH))
ossdev->out_caps.dwSupport |= WAVECAPS_DIRECTSOUND;
}
OSS_CloseDevice(devID, audio);
OSS_CloseDevice(ossdev);
TRACE("out dwFormats = %08lX, dwSupport = %08lX\n",
ossdev->out_caps.dwFormats, ossdev->out_caps.dwSupport);
......@@ -479,7 +490,6 @@ static void OSS_WaveOutInit(unsigned devID, OSS_DEVICE* ossdev)
*/
static void OSS_WaveInInit(unsigned devID, OSS_DEVICE* ossdev)
{
int audio;
int smplrate;
int samplesize = 16;
int dsp_stereo = 1;
......@@ -490,14 +500,15 @@ static void OSS_WaveInInit(unsigned devID, OSS_DEVICE* ossdev)
samplesize = 16;
dsp_stereo = 1;
WInDev[devID].unixdev = -1;
WInDev[devID].state = WINE_WS_CLOSED;
WInDev[devID].ossdev = ossdev;
memset(&ossdev->in_caps, 0, sizeof(ossdev->in_caps));
if (OSS_OpenDevice(0, &audio, O_RDONLY, NULL, 0, 0, 0) != 0) return;
if (OSS_OpenDevice(WInDev[devID].ossdev, O_RDONLY, NULL, 0, 0, 0) != 0) return;
numInDev++;
ioctl(audio, SNDCTL_DSP_RESET, 0);
ioctl(ossdev->fd, SNDCTL_DSP_RESET, 0);
#ifdef EMULATE_SB16
ossdev->in_caps.wMid = 0x0002;
......@@ -509,21 +520,21 @@ static void OSS_WaveInInit(unsigned devID, OSS_DEVICE* ossdev)
strcpy(ossdev->in_caps.szPname, "OpenSoundSystem WAVIN Driver");
#endif
ossdev->in_caps.dwFormats = 0x00000000;
ossdev->in_caps.wChannels = (ioctl(audio, SNDCTL_DSP_STEREO, &dsp_stereo) != 0) ? 1 : 2;
ossdev->in_caps.wChannels = (ioctl(ossdev->fd, SNDCTL_DSP_STEREO, &dsp_stereo) != 0) ? 1 : 2;
WInDev[devID].bTriggerSupport = FALSE;
if (ioctl(audio, SNDCTL_DSP_GETCAPS, &caps) == 0) {
if (ioctl(ossdev->fd, SNDCTL_DSP_GETCAPS, &caps) == 0) {
TRACE("OSS dsp in caps=%08X\n", caps);
if (caps & DSP_CAP_TRIGGER)
WInDev[devID].bTriggerSupport = TRUE;
}
ioctl(audio, SNDCTL_DSP_GETFMTS, &mask);
ioctl(ossdev->fd, SNDCTL_DSP_GETFMTS, &mask);
TRACE("OSS in dsp mask=%08x\n", mask);
bytespersmpl = (ioctl(audio, SNDCTL_DSP_SAMPLESIZE, &samplesize) != 0) ? 1 : 2;
bytespersmpl = (ioctl(ossdev->fd, SNDCTL_DSP_SAMPLESIZE, &samplesize) != 0) ? 1 : 2;
smplrate = 44100;
if (ioctl(audio, SNDCTL_DSP_SPEED, &smplrate) == 0) {
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)
......@@ -536,7 +547,7 @@ static void OSS_WaveInInit(unsigned devID, OSS_DEVICE* ossdev)
}
}
smplrate = 22050;
if (ioctl(audio, SNDCTL_DSP_SPEED, &smplrate) == 0) {
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)
......@@ -549,7 +560,7 @@ static void OSS_WaveInInit(unsigned devID, OSS_DEVICE* ossdev)
}
}
smplrate = 11025;
if (ioctl(audio, SNDCTL_DSP_SPEED, &smplrate) == 0) {
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)
......@@ -561,7 +572,7 @@ static void OSS_WaveInInit(unsigned devID, OSS_DEVICE* ossdev)
ossdev->in_caps.dwFormats |= WAVE_FORMAT_1S16;
}
}
OSS_CloseDevice(devID, audio);
OSS_CloseDevice(ossdev);
TRACE("in dwFormats = %08lX\n", ossdev->in_caps.dwFormats);
}
......@@ -570,19 +581,16 @@ static void OSS_WaveInInit(unsigned devID, OSS_DEVICE* ossdev)
*
*
*/
static void OSS_WaveFullDuplexInit(unsigned devID, OSS_DEVICE* ossdev)
static void OSS_WaveFullDuplexInit(OSS_DEVICE* ossdev)
{
#ifdef USE_FULLDUPLEX
int audio;
int caps;
if (OSS_OpenDevice(devID, &audio, O_RDWR, NULL, 0, 0, 0) != 0) return;
if (ioctl(audio, SNDCTL_DSP_GETCAPS, &caps) == 0)
if (OSS_OpenDevice(ossdev, O_RDWR, NULL, 0, 0, 0) != 0) return;
if (ioctl(ossdev->fd, SNDCTL_DSP_GETCAPS, &caps) == 0)
{
ossdev->full_duplex = (caps & DSP_CAP_DUPLEX);
}
OSS_CloseDevice(devID, audio);
#endif
OSS_CloseDevice(ossdev);
}
/******************************************************************
......@@ -596,8 +604,16 @@ LONG OSS_WaveInit(void)
/* FIXME: only one device is supported */
memset(&OSS_Devices, 0, sizeof(OSS_Devices));
OSS_Devices[0].dev_name = "/dev/dsp";
/* FIXME: should check that dsp actually points to dsp0, or that dsp0 exists
* we should also be able to configure (bitmap) which devices we want to use...
* - or even store the name of all drivers in our configuration
*/
OSS_Devices[0].dev_name = "/dev/dsp";
OSS_Devices[0].mixer_name = "/dev/mixer";
OSS_Devices[1].dev_name = "/dev/dsp1";
OSS_Devices[1].mixer_name = "/dev/mixer1";
OSS_Devices[2].dev_name = "/dev/dsp2";
OSS_Devices[2].mixer_name = "/dev/mixer2";
/* start with output device */
for (i = 0; i < MAX_WAVEDRV; ++i)
......@@ -609,7 +625,7 @@ LONG OSS_WaveInit(void)
/* finish with the full duplex bits */
for (i = 0; i < MAX_WAVEDRV; i++)
OSS_WaveFullDuplexInit(i, &OSS_Devices[i]);
OSS_WaveFullDuplexInit(&OSS_Devices[i]);
return 0;
}
......@@ -773,7 +789,7 @@ static BOOL wodUpdatePlayedTotal(WINE_WAVEOUT* wwo, audio_buf_info* info)
audio_buf_info dspspace;
if (!info) info = &dspspace;
if (ioctl(wwo->unixdev, SNDCTL_DSP_GETOSPACE, info) < 0) {
if (ioctl(wwo->ossdev->fd, SNDCTL_DSP_GETOSPACE, info) < 0) {
ERR("ioctl can't 'SNDCTL_DSP_GETOSPACE' !\n");
return FALSE;
}
......@@ -894,7 +910,7 @@ static BOOL wodPlayer_WriteMaxFrags(WINE_WAVEOUT* wwo, DWORD* bytes)
if (toWrite > 0)
{
written = write(wwo->unixdev, wwo->lpPlayPtr->lpData + wwo->dwPartialOffset, toWrite);
written = write(wwo->ossdev->fd, wwo->lpPlayPtr->lpData + wwo->dwPartialOffset, toWrite);
if (written <= 0) return FALSE;
}
else
......@@ -961,8 +977,8 @@ static void wodPlayer_Reset(WINE_WAVEOUT* wwo, BOOL reset)
wodPlayer_NotifyCompletions(wwo, FALSE);
/* flush all possible output */
if (ioctl(wwo->unixdev, SNDCTL_DSP_RESET, 0) == -1) {
perror("ioctl SNDCTL_DSP_RESET");
if (OSS_ResetDevice(wwo->ossdev) == -1)
{
wwo->hThread = 0;
wwo->state = WINE_WS_STOPPED;
ExitThread(-1);
......@@ -1136,7 +1152,7 @@ static DWORD wodPlayer_FeedDSP(WINE_WAVEOUT* wwo)
/* OSS doesn't start before it gets either 2 fragments or a SNDCTL_DSP_POST;
* if it didn't get one, we give it the other */
if (wwo->dwBufferSize < availInQ + 2 * wwo->dwFragmentSize)
ioctl(wwo->unixdev, SNDCTL_DSP_POST, 0);
ioctl(wwo->ossdev->fd, SNDCTL_DSP_POST, 0);
wwo->bNeedPost = FALSE;
}
}
......@@ -1176,7 +1192,7 @@ static DWORD CALLBACK wodPlayer(LPVOID pmt)
wodPlayer_ProcessMessages(wwo);
if (!wwo->lpPlayPtr) {
TRACE("flushing\n");
ioctl(wwo->unixdev, SNDCTL_DSP_SYNC, 0);
ioctl(wwo->ossdev->fd, SNDCTL_DSP_SYNC, 0);
wwo->dwPlayedTotal = wwo->dwWrittenTotal;
}
else {
......@@ -1267,16 +1283,17 @@ static DWORD wodOpen(WORD wDevID, LPWAVEOPENDESC lpDesc, DWORD dwFlags)
/* 16 fragments max, 2^10=1024 bytes per fragment */
audio_fragment = 0x000F000A;
}
if (wwo->unixdev != -1) return MMSYSERR_ALLOCATED;
if (wwo->state != WINE_WS_CLOSED) return MMSYSERR_ALLOCATED;
/* we want to be able to mmap() the device, which means it must be opened readable,
* otherwise mmap() will fail (at least under Linux) */
ret = OSS_OpenDevice(wDevID, &wwo->unixdev,
ret = OSS_OpenDevice(wwo->ossdev,
(dwFlags & WAVE_DIRECTSOUND) ? O_RDWR : O_WRONLY,
&audio_fragment, lpDesc->lpFormat->nSamplesPerSec,
(lpDesc->lpFormat->nChannels > 1) ? 1 : 0,
(lpDesc->lpFormat->wBitsPerSample == 16)
? AFMT_S16_LE : AFMT_U8);
if (ret != 0) return ret;
wwo->state = WINE_WS_STOPPED;
wwo->wFlags = HIWORD(dwFlags & CALLBACK_TYPEMASK);
......@@ -1291,10 +1308,10 @@ static DWORD wodOpen(WORD wDevID, LPWAVEOPENDESC lpDesc, DWORD dwFlags)
wwo->format.wf.nChannels;
}
/* Read output space info for future reference */
if (ioctl(wwo->unixdev, SNDCTL_DSP_GETOSPACE, &info) < 0) {
if (ioctl(wwo->ossdev->fd, SNDCTL_DSP_GETOSPACE, &info) < 0) {
ERR("ioctl can't 'SNDCTL_DSP_GETOSPACE' !\n");
OSS_CloseDevice(wDevID, wwo->unixdev);
wwo->unixdev = -1;
OSS_CloseDevice(wwo->ossdev);
wwo->state = WINE_WS_CLOSED;
return MMSYSERR_NOTENABLED;
}
......@@ -1327,7 +1344,7 @@ static DWORD wodOpen(WORD wDevID, LPWAVEOPENDESC lpDesc, DWORD dwFlags)
wwo->hStartUpEvent = INVALID_HANDLE_VALUE;
TRACE("fd=%d fragmentSize=%ld\n",
wwo->unixdev, wwo->dwFragmentSize);
wwo->ossdev->fd, wwo->dwFragmentSize);
if (wwo->dwFragmentSize % wwo->format.wf.nBlockAlign)
ERR("Fragment doesn't contain an integral number of data blocks\n");
......@@ -1349,7 +1366,7 @@ static DWORD wodClose(WORD wDevID)
TRACE("(%u);\n", wDevID);
if (wDevID >= MAX_WAVEDRV || WOutDev[wDevID].unixdev == -1) {
if (wDevID >= MAX_WAVEDRV || WOutDev[wDevID].state == WINE_WS_CLOSED) {
WARN("bad device ID !\n");
return MMSYSERR_BADDEVICEID;
}
......@@ -1369,8 +1386,8 @@ static DWORD wodClose(WORD wDevID)
OSS_DestroyRingMessage(&wwo->msgRing);
OSS_CloseDevice(wDevID, wwo->unixdev);
wwo->unixdev = -1;
OSS_CloseDevice(wwo->ossdev);
wwo->state = WINE_WS_CLOSED;
wwo->dwFragmentSize = 0;
ret = wodNotifyClient(wwo, WOM_CLOSE, 0L, 0L);
}
......@@ -1386,7 +1403,7 @@ static DWORD wodWrite(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
TRACE("(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
/* first, do the sanity checks... */
if (wDevID >= MAX_WAVEDRV || WOutDev[wDevID].unixdev == -1) {
if (wDevID >= MAX_WAVEDRV || WOutDev[wDevID].state == WINE_WS_CLOSED) {
WARN("bad dev ID !\n");
return MMSYSERR_BADDEVICEID;
}
......@@ -1460,7 +1477,7 @@ static DWORD wodPause(WORD wDevID)
{
TRACE("(%u);!\n", wDevID);
if (wDevID >= MAX_WAVEDRV || WOutDev[wDevID].unixdev == -1) {
if (wDevID >= MAX_WAVEDRV || WOutDev[wDevID].state == WINE_WS_CLOSED) {
WARN("bad device ID !\n");
return MMSYSERR_BADDEVICEID;
}
......@@ -1477,7 +1494,7 @@ static DWORD wodRestart(WORD wDevID)
{
TRACE("(%u);\n", wDevID);
if (wDevID >= MAX_WAVEDRV || WOutDev[wDevID].unixdev == -1) {
if (wDevID >= MAX_WAVEDRV || WOutDev[wDevID].state == WINE_WS_CLOSED) {
WARN("bad device ID !\n");
return MMSYSERR_BADDEVICEID;
}
......@@ -1499,7 +1516,7 @@ static DWORD wodReset(WORD wDevID)
{
TRACE("(%u);\n", wDevID);
if (wDevID >= MAX_WAVEDRV || WOutDev[wDevID].unixdev == -1) {
if (wDevID >= MAX_WAVEDRV || WOutDev[wDevID].state == WINE_WS_CLOSED) {
WARN("bad device ID !\n");
return MMSYSERR_BADDEVICEID;
}
......@@ -1520,7 +1537,7 @@ static DWORD wodGetPosition(WORD wDevID, LPMMTIME lpTime, DWORD uSize)
TRACE("(%u, %p, %lu);\n", wDevID, lpTime, uSize);
if (wDevID >= MAX_WAVEDRV || WOutDev[wDevID].unixdev == -1) {
if (wDevID >= MAX_WAVEDRV || WOutDev[wDevID].state == WINE_WS_CLOSED) {
WARN("bad device ID !\n");
return MMSYSERR_BADDEVICEID;
}
......@@ -1580,7 +1597,7 @@ static DWORD wodBreakLoop(WORD wDevID)
{
TRACE("(%u);\n", wDevID);
if (wDevID >= MAX_WAVEDRV || WOutDev[wDevID].unixdev == -1) {
if (wDevID >= MAX_WAVEDRV || WOutDev[wDevID].state == WINE_WS_CLOSED) {
WARN("bad device ID !\n");
return MMSYSERR_BADDEVICEID;
}
......@@ -1724,7 +1741,7 @@ static HRESULT DSDB_MapPrimary(IDsDriverBufferImpl *dsdb)
WINE_WAVEOUT *wwo = &(WOutDev[dsdb->drv->wDevID]);
if (!wwo->mapping) {
wwo->mapping = mmap(NULL, wwo->maplen, PROT_WRITE, MAP_SHARED,
wwo->unixdev, 0);
wwo->ossdev->fd, 0);
if (wwo->mapping == (LPBYTE)-1) {
ERR("(%p): Could not map sound device for direct access (%s)\n", dsdb, strerror(errno));
return DSERR_GENERIC;
......@@ -1867,11 +1884,11 @@ static HRESULT WINAPI IDsDriverBufferImpl_GetPosition(PIDSDRIVERBUFFER iface,
DWORD ptr;
TRACE("(%p)\n",iface);
if (WOutDev[This->drv->wDevID].unixdev == -1) {
if (WOutDev[This->drv->wDevID].state == WINE_WS_CLOSED) {
ERR("device not open, but accessing?\n");
return DSERR_UNINITIALIZED;
}
if (ioctl(WOutDev[This->drv->wDevID].unixdev, SNDCTL_DSP_GETOPTR, &info) < 0) {
if (ioctl(WOutDev[This->drv->wDevID].ossdev->fd, SNDCTL_DSP_GETOPTR, &info) < 0) {
ERR("ioctl failed (%d)\n", errno);
return DSERR_GENERIC;
}
......@@ -1895,7 +1912,7 @@ static HRESULT WINAPI IDsDriverBufferImpl_Play(PIDSDRIVERBUFFER iface, DWORD dwR
ICOM_THIS(IDsDriverBufferImpl,iface);
int enable = PCM_ENABLE_OUTPUT;
TRACE("(%p,%lx,%lx,%lx)\n",iface,dwRes1,dwRes2,dwFlags);
if (ioctl(WOutDev[This->drv->wDevID].unixdev, SNDCTL_DSP_SETTRIGGER, &enable) < 0) {
if (ioctl(WOutDev[This->drv->wDevID].ossdev->fd, SNDCTL_DSP_SETTRIGGER, &enable) < 0) {
ERR("ioctl failed (%d)\n", errno);
return DSERR_GENERIC;
}
......@@ -1908,7 +1925,7 @@ static HRESULT WINAPI IDsDriverBufferImpl_Stop(PIDSDRIVERBUFFER iface)
int enable = 0;
TRACE("(%p)\n",iface);
/* no more playing */
if (ioctl(WOutDev[This->drv->wDevID].unixdev, SNDCTL_DSP_SETTRIGGER, &enable) < 0) {
if (ioctl(WOutDev[This->drv->wDevID].ossdev->fd, SNDCTL_DSP_SETTRIGGER, &enable) < 0) {
ERR("ioctl failed (%d)\n", errno);
return DSERR_GENERIC;
}
......@@ -1995,7 +2012,7 @@ static HRESULT WINAPI IDsDriverImpl_Open(PIDSDRIVER iface)
TRACE("(%p)\n",iface);
/* make sure the card doesn't start playing before we want it to */
if (ioctl(WOutDev[This->wDevID].unixdev, SNDCTL_DSP_SETTRIGGER, &enable) < 0) {
if (ioctl(WOutDev[This->wDevID].ossdev->fd, SNDCTL_DSP_SETTRIGGER, &enable) < 0) {
ERR("ioctl failed (%d)\n", errno);
return DSERR_GENERIC;
}
......@@ -2057,7 +2074,7 @@ static HRESULT WINAPI IDsDriverImpl_CreateSoundBuffer(PIDSDRIVER iface,
(*ippdsdb)->drv = This;
/* check how big the DMA buffer is now */
if (ioctl(WOutDev[This->wDevID].unixdev, SNDCTL_DSP_GETOSPACE, &info) < 0) {
if (ioctl(WOutDev[This->wDevID].ossdev->fd, SNDCTL_DSP_GETOSPACE, &info) < 0) {
ERR("ioctl failed (%d)\n", errno);
HeapFree(GetProcessHeap(),0,*ippdsdb);
*ippdsdb = NULL;
......@@ -2078,7 +2095,7 @@ static HRESULT WINAPI IDsDriverImpl_CreateSoundBuffer(PIDSDRIVER iface,
*ppbBuffer = WOutDev[This->wDevID].mapping;
/* some drivers need some extra nudging after mapping */
if (ioctl(WOutDev[This->wDevID].unixdev, SNDCTL_DSP_SETTRIGGER, &enable) < 0) {
if (ioctl(WOutDev[This->wDevID].ossdev->fd, SNDCTL_DSP_SETTRIGGER, &enable) < 0) {
ERR("ioctl failed (%d)\n", errno);
return DSERR_GENERIC;
}
......@@ -2208,7 +2225,7 @@ static DWORD CALLBACK widRecorder(LPVOID pmt)
/* the soundblaster live needs a micro wake to get its recording started
* (or GETISPACE will have 0 frags all the time)
*/
read(wwi->unixdev,&xs,4);
read(wwi->ossdev->fd, &xs, 4);
/* make sleep time to be # of ms to output a fragment */
dwSleepTime = (wwi->dwFragmentSize * 1000) / wwi->format.wf.nAvgBytesPerSec;
......@@ -2224,7 +2241,7 @@ static DWORD CALLBACK widRecorder(LPVOID pmt)
{
lpWaveHdr = wwi->lpQueuePtr;
ioctl(wwi->unixdev, SNDCTL_DSP_GETISPACE, &info);
ioctl(wwi->ossdev->fd, SNDCTL_DSP_GETISPACE, &info);
TRACE("info={frag=%d fsize=%d ftotal=%d bytes=%d}\n", info.fragments, info.fragsize, info.fragstotal, info.bytes);
/* read all the fragments accumulated so far */
......@@ -2235,7 +2252,7 @@ static DWORD CALLBACK widRecorder(LPVOID pmt)
if (lpWaveHdr->dwBufferLength - lpWaveHdr->dwBytesRecorded >= wwi->dwFragmentSize)
{
/* directly read fragment in wavehdr */
bytesRead = read(wwi->unixdev,
bytesRead = read(wwi->ossdev->fd,
lpWaveHdr->lpData + lpWaveHdr->dwBytesRecorded,
wwi->dwFragmentSize);
......@@ -2265,7 +2282,7 @@ static DWORD CALLBACK widRecorder(LPVOID pmt)
else
{
/* read the fragment in a local buffer */
bytesRead = read(wwi->unixdev, buffer, wwi->dwFragmentSize);
bytesRead = read(wwi->ossdev->fd, buffer, wwi->dwFragmentSize);
pOffset = buffer;
TRACE("bytesRead=%ld (local)\n", bytesRead);
......@@ -2334,7 +2351,7 @@ static DWORD CALLBACK widRecorder(LPVOID pmt)
if (wwi->bTriggerSupport)
{
/* start the recording */
if (ioctl(wwi->unixdev, SNDCTL_DSP_SETTRIGGER, &enable) < 0)
if (ioctl(wwi->ossdev->fd, SNDCTL_DSP_SETTRIGGER, &enable) < 0)
{
ERR("ioctl(SNDCTL_DSP_SETTRIGGER) failed (%d)\n", errno);
}
......@@ -2343,7 +2360,7 @@ static DWORD CALLBACK widRecorder(LPVOID pmt)
{
unsigned char data[4];
/* read 4 bytes to start the recording */
read(wwi->unixdev, data, 4);
read(wwi->ossdev->fd, data, 4);
}
SetEvent(ev);
......@@ -2428,7 +2445,7 @@ static DWORD widOpen(WORD wDevID, LPWAVEOPENDESC lpDesc, DWORD dwFlags)
wwi = &WInDev[wDevID];
if (wwi->unixdev != -1) return MMSYSERR_ALLOCATED;
if (wwi->state != WINE_WS_CLOSED) return MMSYSERR_ALLOCATED;
/* This is actually hand tuned to work so that my SB Live:
* - does not skip
* - does not buffer too much
......@@ -2436,13 +2453,14 @@ static DWORD widOpen(WORD wDevID, LPWAVEOPENDESC lpDesc, DWORD dwFlags)
*/
/* 15 fragments max, 2^10 = 1024 bytes per fragment */
audio_fragment = 0x000F000A;
ret = OSS_OpenDevice(wDevID, &wwi->unixdev,
O_RDONLY, &audio_fragment,
ret = OSS_OpenDevice(wwi->ossdev, O_RDONLY, &audio_fragment,
lpDesc->lpFormat->nSamplesPerSec,
(lpDesc->lpFormat->nChannels > 1) ? 1 : 0,
(lpDesc->lpFormat->wBitsPerSample == 16)
? AFMT_S16_LE : AFMT_U8);
if (ret != 0) return ret;
wwi->state = WINE_WS_STOPPED;
if (wwi->lpQueuePtr) {
WARN("Should have an empty queue (%p)\n", wwi->lpQueuePtr);
wwi->lpQueuePtr = NULL;
......@@ -2461,11 +2479,11 @@ static DWORD widOpen(WORD wDevID, LPWAVEOPENDESC lpDesc, DWORD dwFlags)
wwi->format.wf.nChannels;
}
ioctl(wwi->unixdev, SNDCTL_DSP_GETBLKSIZE, &fragment_size);
ioctl(wwi->ossdev->fd, SNDCTL_DSP_GETBLKSIZE, &fragment_size);
if (fragment_size == -1) {
WARN("IOCTL can't 'SNDCTL_DSP_GETBLKSIZE' !\n");
OSS_CloseDevice(wDevID, wwi->unixdev);
wwi->unixdev = -1;
OSS_CloseDevice(wwi->ossdev);
wwi->state = WINE_WS_CLOSED;
return MMSYSERR_NOTENABLED;
}
wwi->dwFragmentSize = fragment_size;
......@@ -2494,7 +2512,7 @@ static DWORD widClose(WORD wDevID)
WINE_WAVEIN* wwi;
TRACE("(%u);\n", wDevID);
if (wDevID >= MAX_WAVEDRV || WInDev[wDevID].unixdev == -1) {
if (wDevID >= MAX_WAVEDRV || WInDev[wDevID].state == WINE_WS_CLOSED) {
WARN("can't close !\n");
return MMSYSERR_INVALHANDLE;
}
......@@ -2507,8 +2525,8 @@ static DWORD widClose(WORD wDevID)
}
OSS_AddRingMessage(&wwi->msgRing, WINE_WM_CLOSING, 0, TRUE);
OSS_CloseDevice(wDevID, wwi->unixdev);
wwi->unixdev = -1;
OSS_CloseDevice(wwi->ossdev);
wwi->state = WINE_WS_CLOSED;
wwi->dwFragmentSize = 0;
OSS_DestroyRingMessage(&wwi->msgRing);
return widNotifyClient(wwi, WIM_CLOSE, 0L, 0L);
......@@ -2521,7 +2539,7 @@ static DWORD widAddBuffer(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
{
TRACE("(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
if (wDevID >= MAX_WAVEDRV || WInDev[wDevID].unixdev == -1) {
if (wDevID >= MAX_WAVEDRV || WInDev[wDevID].state == WINE_WS_CLOSED) {
WARN("can't do it !\n");
return MMSYSERR_INVALHANDLE;
}
......@@ -2585,7 +2603,7 @@ static DWORD widUnprepare(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
static DWORD widStart(WORD wDevID)
{
TRACE("(%u);\n", wDevID);
if (wDevID >= MAX_WAVEDRV || WInDev[wDevID].unixdev == -1) {
if (wDevID >= MAX_WAVEDRV || WInDev[wDevID].state == WINE_WS_CLOSED) {
WARN("can't start recording !\n");
return MMSYSERR_INVALHANDLE;
}
......@@ -2600,7 +2618,7 @@ static DWORD widStart(WORD wDevID)
static DWORD widStop(WORD wDevID)
{
TRACE("(%u);\n", wDevID);
if (wDevID >= MAX_WAVEDRV || WInDev[wDevID].unixdev == -1) {
if (wDevID >= MAX_WAVEDRV || WInDev[wDevID].state == WINE_WS_CLOSED) {
WARN("can't stop !\n");
return MMSYSERR_INVALHANDLE;
}
......@@ -2616,7 +2634,7 @@ static DWORD widStop(WORD wDevID)
static DWORD widReset(WORD wDevID)
{
TRACE("(%u);\n", wDevID);
if (wDevID >= MAX_WAVEDRV || WInDev[wDevID].unixdev == -1) {
if (wDevID >= MAX_WAVEDRV || WInDev[wDevID].state == WINE_WS_CLOSED) {
WARN("can't reset !\n");
return MMSYSERR_INVALHANDLE;
}
......@@ -2634,7 +2652,7 @@ static DWORD widGetPosition(WORD wDevID, LPMMTIME lpTime, DWORD uSize)
TRACE("(%u, %p, %lu);\n", wDevID, lpTime, uSize);
if (wDevID >= MAX_WAVEDRV || WInDev[wDevID].unixdev == -1) {
if (wDevID >= MAX_WAVEDRV || WInDev[wDevID].state == WINE_WS_CLOSED) {
WARN("can't get pos !\n");
return MMSYSERR_INVALHANDLE;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment