| /* | |
| * 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; | |
| WAVEOUTCAPSW out_caps; | |
| WAVEOUTCAPSW duplex_out_caps; | |
| WAVEINCAPSW 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; | |
| /* make accomodation for the inacuraccy of OSS when reporting buffer size remaining by using the clock instead of GETOSPACE */ | |
| DWORD dwProjectedFinishTime; | |
| } 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 */ |