1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
/*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef __WINE_CONFIG_H
# error You must include config.h to use this header
#endif
#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)
#define MAX_CHANNELS 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 channels;
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 */