182 lines
6.6 KiB
C
182 lines
6.6 KiB
C
/*
|
|
* Sample Wine Driver for Open Sound System (featured in Linux and FreeBSD)
|
|
*
|
|
* 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
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*/
|
|
|
|
#ifdef HAVE_OSS
|
|
|
|
/* unless someone makes a wineserver kernel module, Unix pipes are faster than win32 events */
|
|
#define USE_PIPE_SYNC
|
|
|
|
#define MAX_WAVEDRV (6)
|
|
|
|
/* states of the playing device */
|
|
#define WINE_WS_PLAYING 0
|
|
#define WINE_WS_PAUSED 1
|
|
#define WINE_WS_STOPPED 2
|
|
#define WINE_WS_CLOSED 3
|
|
|
|
/* events to be send to device */
|
|
enum win_wm_message {
|
|
WINE_WM_PAUSING = WM_USER + 1, WINE_WM_RESTARTING, WINE_WM_RESETTING, WINE_WM_HEADER,
|
|
WINE_WM_UPDATE, WINE_WM_BREAKLOOP, WINE_WM_CLOSING, WINE_WM_STARTING, WINE_WM_STOPPING
|
|
};
|
|
|
|
#ifdef USE_PIPE_SYNC
|
|
#define SIGNAL_OMR(omr) do { int x = 0; write((omr)->msg_pipe[1], &x, sizeof(x)); } while (0)
|
|
#define CLEAR_OMR(omr) do { int x = 0; read((omr)->msg_pipe[0], &x, sizeof(x)); } while (0)
|
|
#define RESET_OMR(omr) do { } while (0)
|
|
#define WAIT_OMR(omr, sleep) \
|
|
do { struct pollfd pfd; pfd.fd = (omr)->msg_pipe[0]; \
|
|
pfd.events = POLLIN; poll(&pfd, 1, sleep); } while (0)
|
|
#else
|
|
#define SIGNAL_OMR(omr) do { SetEvent((omr)->msg_event); } while (0)
|
|
#define CLEAR_OMR(omr) do { } while (0)
|
|
#define RESET_OMR(omr) do { ResetEvent((omr)->msg_event); } while (0)
|
|
#define WAIT_OMR(omr, sleep) \
|
|
do { WaitForSingleObject((omr)->msg_event, sleep); } while (0)
|
|
#endif
|
|
|
|
typedef struct {
|
|
enum win_wm_message msg; /* message identifier */
|
|
DWORD param; /* parameter for this message */
|
|
HANDLE hEvent; /* if message is synchronous, handle of event for synchro */
|
|
} OSS_MSG;
|
|
|
|
/* implement an in-process message ring for better performance
|
|
* (compared to passing thru the server)
|
|
* this ring will be used by the input (resp output) record (resp playback) routine
|
|
*/
|
|
#define OSS_RING_BUFFER_INCREMENT 64
|
|
typedef struct {
|
|
int ring_buffer_size;
|
|
OSS_MSG * messages;
|
|
int msg_tosave;
|
|
int msg_toget;
|
|
#ifdef USE_PIPE_SYNC
|
|
int msg_pipe[2];
|
|
#else
|
|
HANDLE msg_event;
|
|
#endif
|
|
CRITICAL_SECTION msg_crst;
|
|
} OSS_MSG_RING;
|
|
|
|
typedef struct tagOSS_DEVICE {
|
|
char* dev_name;
|
|
char* mixer_name;
|
|
char* interface_name;
|
|
unsigned open_count;
|
|
WAVEOUTCAPSA out_caps;
|
|
WAVEOUTCAPSA duplex_out_caps;
|
|
WAVEINCAPSA in_caps;
|
|
DWORD in_caps_support;
|
|
unsigned open_access;
|
|
int fd;
|
|
DWORD owner_tid;
|
|
int sample_rate;
|
|
int stereo;
|
|
int format;
|
|
unsigned audio_fragment;
|
|
BOOL full_duplex;
|
|
BOOL bTriggerSupport;
|
|
BOOL bOutputEnabled;
|
|
BOOL bInputEnabled;
|
|
DSDRIVERDESC ds_desc;
|
|
DSDRIVERCAPS ds_caps;
|
|
DSCDRIVERCAPS dsc_caps;
|
|
} OSS_DEVICE;
|
|
|
|
typedef struct {
|
|
OSS_DEVICE* ossdev;
|
|
volatile int state; /* one of the WINE_WS_ manifest constants */
|
|
WAVEOPENDESC waveDesc;
|
|
WORD wFlags;
|
|
WAVEFORMATPCMEX waveFormat;
|
|
DWORD volume;
|
|
|
|
/* OSS information */
|
|
DWORD dwFragmentSize; /* size of OSS buffer fragment */
|
|
DWORD dwBufferSize; /* size of whole OSS buffer in bytes */
|
|
LPWAVEHDR lpQueuePtr; /* start of queued WAVEHDRs (waiting to be notified) */
|
|
LPWAVEHDR lpPlayPtr; /* start of not yet fully played buffers */
|
|
DWORD dwPartialOffset; /* Offset of not yet written bytes in lpPlayPtr */
|
|
|
|
LPWAVEHDR lpLoopPtr; /* pointer of first buffer in loop, if any */
|
|
DWORD dwLoops; /* private copy of loop counter */
|
|
|
|
DWORD dwPlayedTotal; /* number of bytes actually played since opening */
|
|
DWORD dwWrittenTotal; /* number of bytes written to OSS buffer since opening */
|
|
BOOL bNeedPost; /* whether audio still needs to be physically started */
|
|
|
|
/* synchronization stuff */
|
|
HANDLE hStartUpEvent;
|
|
HANDLE hThread;
|
|
DWORD dwThreadID;
|
|
OSS_MSG_RING msgRing;
|
|
} WINE_WAVEOUT;
|
|
|
|
typedef struct {
|
|
OSS_DEVICE* ossdev;
|
|
volatile int state;
|
|
DWORD dwFragmentSize; /* OpenSound '/dev/dsp' give us that size */
|
|
WAVEOPENDESC waveDesc;
|
|
WORD wFlags;
|
|
WAVEFORMATPCMEX waveFormat;
|
|
LPWAVEHDR lpQueuePtr;
|
|
DWORD dwTotalRecorded;
|
|
DWORD dwTotalRead;
|
|
|
|
/* synchronization stuff */
|
|
HANDLE hThread;
|
|
DWORD dwThreadID;
|
|
HANDLE hStartUpEvent;
|
|
OSS_MSG_RING msgRing;
|
|
} WINE_WAVEIN;
|
|
|
|
extern OSS_DEVICE OSS_Devices[MAX_WAVEDRV];
|
|
extern WINE_WAVEOUT WOutDev[MAX_WAVEDRV];
|
|
extern WINE_WAVEIN WInDev[MAX_WAVEDRV];
|
|
extern unsigned numOutDev;
|
|
extern unsigned numInDev;
|
|
|
|
extern int getEnables(OSS_DEVICE *ossdev);
|
|
extern void copy_format(LPWAVEFORMATEX wf1, LPWAVEFORMATPCMEX wf2);
|
|
|
|
extern DWORD OSS_OpenDevice(OSS_DEVICE* ossdev, unsigned req_access,
|
|
int* frag, int strict_format,
|
|
int sample_rate, int stereo, int fmt);
|
|
|
|
extern void OSS_CloseDevice(OSS_DEVICE* ossdev);
|
|
|
|
extern DWORD wodOpen(WORD wDevID, LPWAVEOPENDESC lpDesc, DWORD dwFlags);
|
|
extern DWORD wodSetVolume(WORD wDevID, DWORD dwParam);
|
|
extern DWORD widOpen(WORD wDevID, LPWAVEOPENDESC lpDesc, DWORD dwFlags);
|
|
|
|
/* dscapture.c */
|
|
extern DWORD widDsCreate(UINT wDevID, PIDSCDRIVER* drv);
|
|
extern DWORD widDsDesc(UINT wDevID, PDSDRIVERDESC desc);
|
|
|
|
/* dsrender.c */
|
|
extern DWORD wodDsCreate(UINT wDevID, PIDSDRIVER* drv);
|
|
extern DWORD wodDsDesc(UINT wDevID, PDSDRIVERDESC desc);
|
|
|
|
#endif /* HAVE_OSS */
|