Break from the SNDCTL_DSP_CHANNELS loops on first error instead of
[wine] / dlls / winmm / wineoss / audio.h
1 /*
2  * Sample Wine Driver for Open Sound System (featured in Linux and FreeBSD)
3  *
4  * Copyright 1994 Martin Ayotte
5  *           1999 Eric Pouech (async playing in waveOut/waveIn)
6  *           2000 Eric Pouech (loops in waveOut)
7  *           2002 Eric Pouech (full duplex)
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  */
23
24 #ifdef HAVE_OSS
25
26 /* unless someone makes a wineserver kernel module, Unix pipes are faster than win32 events */
27 #define USE_PIPE_SYNC
28
29 #define MAX_WAVEDRV     (6)
30 #define MAX_CHANNELS    6
31
32 /* states of the playing device */
33 #define WINE_WS_PLAYING         0
34 #define WINE_WS_PAUSED          1
35 #define WINE_WS_STOPPED         2
36 #define WINE_WS_CLOSED          3
37
38 /* events to be send to device */
39 enum win_wm_message {
40     WINE_WM_PAUSING = WM_USER + 1, WINE_WM_RESTARTING, WINE_WM_RESETTING, WINE_WM_HEADER,
41     WINE_WM_UPDATE, WINE_WM_BREAKLOOP, WINE_WM_CLOSING, WINE_WM_STARTING, WINE_WM_STOPPING
42 };
43
44 #ifdef USE_PIPE_SYNC
45 #define SIGNAL_OMR(omr) do { int x = 0; write((omr)->msg_pipe[1], &x, sizeof(x)); } while (0)
46 #define CLEAR_OMR(omr) do { int x = 0; read((omr)->msg_pipe[0], &x, sizeof(x)); } while (0)
47 #define RESET_OMR(omr) do { } while (0)
48 #define WAIT_OMR(omr, sleep) \
49   do { struct pollfd pfd; pfd.fd = (omr)->msg_pipe[0]; \
50        pfd.events = POLLIN; poll(&pfd, 1, sleep); } while (0)
51 #else
52 #define SIGNAL_OMR(omr) do { SetEvent((omr)->msg_event); } while (0)
53 #define CLEAR_OMR(omr) do { } while (0)
54 #define RESET_OMR(omr) do { ResetEvent((omr)->msg_event); } while (0)
55 #define WAIT_OMR(omr, sleep) \
56   do { WaitForSingleObject((omr)->msg_event, sleep); } while (0)
57 #endif
58
59 typedef struct {
60     enum win_wm_message         msg;    /* message identifier */
61     DWORD                       param;  /* parameter for this message */
62     HANDLE                      hEvent; /* if message is synchronous, handle of event for synchro */
63 } OSS_MSG;
64
65 /* implement an in-process message ring for better performance
66  * (compared to passing thru the server)
67  * this ring will be used by the input (resp output) record (resp playback) routine
68  */
69 #define OSS_RING_BUFFER_INCREMENT       64
70 typedef struct {
71     int                         ring_buffer_size;
72     OSS_MSG                     * messages;
73     int                         msg_tosave;
74     int                         msg_toget;
75 #ifdef USE_PIPE_SYNC
76     int                         msg_pipe[2];
77 #else
78     HANDLE                      msg_event;
79 #endif
80     CRITICAL_SECTION            msg_crst;
81 } OSS_MSG_RING;
82
83 typedef struct tagOSS_DEVICE {
84     char*                       dev_name;
85     char*                       mixer_name;
86     char*                       interface_name;
87     unsigned                    open_count;
88     WAVEOUTCAPSW                out_caps;
89     WAVEOUTCAPSW                duplex_out_caps;
90     WAVEINCAPSW                 in_caps;
91     DWORD                       in_caps_support;
92     unsigned                    open_access;
93     int                         fd;
94     DWORD                       owner_tid;
95     int                         sample_rate;
96     int                         channels;
97     int                         format;
98     unsigned                    audio_fragment;
99     BOOL                        full_duplex;
100     BOOL                        bTriggerSupport;
101     BOOL                        bOutputEnabled;
102     BOOL                        bInputEnabled;
103     DSDRIVERDESC                ds_desc;
104     DSDRIVERCAPS                ds_caps;
105     DSCDRIVERCAPS               dsc_caps;
106 } OSS_DEVICE;
107
108 typedef struct {
109     OSS_DEVICE*                 ossdev;
110     volatile int                state;                  /* one of the WINE_WS_ manifest constants */
111     WAVEOPENDESC                waveDesc;
112     WORD                        wFlags;
113     WAVEFORMATPCMEX             waveFormat;
114     DWORD                       volume;
115
116     /* OSS information */
117     DWORD                       dwFragmentSize;         /* size of OSS buffer fragment */
118     DWORD                       dwBufferSize;           /* size of whole OSS buffer in bytes */
119     LPWAVEHDR                   lpQueuePtr;             /* start of queued WAVEHDRs (waiting to be notified) */
120     LPWAVEHDR                   lpPlayPtr;              /* start of not yet fully played buffers */
121     DWORD                       dwPartialOffset;        /* Offset of not yet written bytes in lpPlayPtr */
122
123     LPWAVEHDR                   lpLoopPtr;              /* pointer of first buffer in loop, if any */
124     DWORD                       dwLoops;                /* private copy of loop counter */
125
126     DWORD                       dwPlayedTotal;          /* number of bytes actually played since opening */
127     DWORD                       dwWrittenTotal;         /* number of bytes written to OSS buffer since opening */
128     BOOL                        bNeedPost;              /* whether audio still needs to be physically started */
129
130     /* synchronization stuff */
131     HANDLE                      hStartUpEvent;
132     HANDLE                      hThread;
133     DWORD                       dwThreadID;
134     OSS_MSG_RING                msgRing;
135
136     /* make accomodation for the inacuraccy of OSS when reporting buffer size remaining by using the clock instead of GETOSPACE */
137     DWORD                       dwProjectedFinishTime;
138
139 } WINE_WAVEOUT;
140
141 typedef struct {
142     OSS_DEVICE*                 ossdev;
143     volatile int                state;
144     DWORD                       dwFragmentSize;         /* OpenSound '/dev/dsp' give us that size */
145     WAVEOPENDESC                waveDesc;
146     WORD                        wFlags;
147     WAVEFORMATPCMEX             waveFormat;
148     LPWAVEHDR                   lpQueuePtr;
149     DWORD                       dwTotalRecorded;
150     DWORD                       dwTotalRead;
151
152     /* synchronization stuff */
153     HANDLE                      hThread;
154     DWORD                       dwThreadID;
155     HANDLE                      hStartUpEvent;
156     OSS_MSG_RING                msgRing;
157 } WINE_WAVEIN;
158
159 extern OSS_DEVICE       OSS_Devices[MAX_WAVEDRV];
160 extern WINE_WAVEOUT     WOutDev[MAX_WAVEDRV];
161 extern WINE_WAVEIN      WInDev[MAX_WAVEDRV];
162 extern unsigned         numOutDev;
163 extern unsigned         numInDev;
164
165 extern int getEnables(OSS_DEVICE *ossdev);
166 extern void copy_format(LPWAVEFORMATEX wf1, LPWAVEFORMATPCMEX wf2);
167
168 extern DWORD OSS_OpenDevice(OSS_DEVICE* ossdev, unsigned req_access,
169                             int* frag, int strict_format,
170                             int sample_rate, int stereo, int fmt);
171
172 extern void OSS_CloseDevice(OSS_DEVICE* ossdev);
173
174 extern DWORD wodOpen(WORD wDevID, LPWAVEOPENDESC lpDesc, DWORD dwFlags);
175 extern DWORD wodSetVolume(WORD wDevID, DWORD dwParam);
176 extern DWORD widOpen(WORD wDevID, LPWAVEOPENDESC lpDesc, DWORD dwFlags);
177
178 /* dscapture.c */
179 extern DWORD widDsCreate(UINT wDevID, PIDSCDRIVER* drv);
180 extern DWORD widDsDesc(UINT wDevID, PDSDRIVERDESC desc);
181
182 /* dsrender.c */
183 extern DWORD wodDsCreate(UINT wDevID, PIDSDRIVER* drv);
184 extern DWORD wodDsDesc(UINT wDevID, PDSDRIVERDESC desc);
185
186 #endif /* HAVE_OSS */