~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Wine Cross Reference
wine/dlls/wineesd.drv/audio.c

Version: ~ [ wine-1.1.4 ] ~ [ wine-1.1.3 ] ~ [ wine-1.1.2 ] ~ [ wine-1.1.1 ] ~ [ wine-1.1.0 ] ~ [ wine-1.0 ] ~ [ wine-1.0-rc5 ] ~ [ wine-1.0-rc4 ] ~ [ wine-1.0-rc3 ] ~ [ wine-1.0-rc2 ] ~ [ wine-1.0-rc1 ] ~ [ wine-0.9.61 ] ~ [ wine-0.9.60 ] ~ [ wine-0.9.59 ] ~ [ wine-0.9.58 ] ~ [ wine-0.9.57 ] ~ [ wine-0.9.56 ] ~ [ wine-0.9.55 ] ~ [ wine-0.9.54 ] ~ [ wine-0.9.53 ] ~ [ wine-0.9.52 ] ~ [ wine-0.9.51 ] ~ [ wine-0.9.50 ] ~ [ wine-0.9.49 ] ~ [ wine-0.9.48 ] ~ [ wine-0.9.47 ] ~ [ wine-0.9.46 ] ~ [ wine-0.9.45 ] ~ [ wine-0.9.44 ] ~ [ wine-0.9.43 ] ~ [ wine-0.9.42 ] ~ [ wine-0.9.41 ] ~ [ wine-0.9.40 ] ~ [ wine-0.9.39 ] ~ [ wine-0.9.38 ] ~ [ wine-0.9.37 ] ~ [ wine-0.9.36 ] ~ [ wine-0.9.35 ] ~ [ wine-0.9.34 ] ~ [ wine-0.9.33 ] ~ [ wine-0.9.32 ] ~ [ wine-0.9.31 ] ~ [ wine-0.9.30 ] ~ [ wine-0.9.29 ] ~ [ wine-0.9.28 ] ~ [ wine-0.9.27 ] ~ [ wine-0.9.26 ] ~ [ wine-0.9.25 ] ~ [ wine-0.9.24 ] ~ [ wine-0.9.23 ] ~ [ wine-0.9.22 ] ~ [ wine-0.9.21 ] ~ [ wine-0.9.20 ] ~ [ wine-0.9.19 ] ~ [ wine-0.9.18 ] ~ [ wine-0.9.17 ] ~ [ wine-0.9.16 ] ~ [ wine-0.9.15 ] ~ [ wine-0.9.14 ] ~ [ wine-0.9.13 ] ~ [ wine-0.9.12 ] ~ [ wine-0.9.11 ] ~ [ wine-0.9.10 ] ~ [ wine-0.9.9 ] ~ [ wine-0.9.8 ] ~ [ wine-0.9.7 ] ~ [ wine-0.9.6 ] ~ [ wine-0.9.5 ] ~ [ wine-0.9.4 ] ~ [ wine-0.9.3 ] ~ [ wine-0.9.2 ] ~ [ wine-0.9.1 ] ~ [ wine-0.9 ] ~ [ wine20050930 ] ~ [ wine20050830 ] ~ [ wine20050725 ] ~ [ wine20050628 ] ~ [ wine20050524 ] ~ [ wine20050419 ] ~ [ wine20050310 ] ~ [ wine20050211 ] ~ [ wine20050111 ] ~ [ wine20041201 ] ~ [ wine20041019 ] ~ [ wine20040914 ] ~ [ wine20040813 ] ~ [ wine20040716 ] ~ [ wine20040615 ] ~ [ wine20040505 ] ~ [ wine20040408 ] ~ [ wine20040309 ] ~ [ wine20040213 ] ~ [ wine20040121 ] ~ [ wine20031212 ] ~ [ wine20031118 ] ~ [ wine20031016 ] ~ [ wine20030911 ] ~ [ wine20030813 ] ~ [ wine20030709 ] ~ [ wine20030618 ] ~ [ wine20030508 ] ~ [ wine20030408 ] ~ [ wine20030318 ] ~ [ wine20030219 ] ~ [ wine20030115 ] ~ [ wine20021219 ] ~ [ wine20021125 ] ~ [ wine20021031 ] ~ [ wine20021007 ] ~ [ wine20020904 ] ~ [ wine20020804 ] ~ [ wine20020710 ] ~ [ wine20020605 ] ~ [ wine20020509 ] ~ [ wine20020411 ] ~ [ wine20020310 ] ~ [ wine20020228 ] ~ [ wine20011226 ] ~ [ wine20011108 ] ~ [ wine20011004 ] ~ [ wine20010824 ] ~ [ wine20010731 ] ~ [ wine20010629 ] ~ [ wine20010510 ] ~ [ wine20010418 ] ~ [ wine20010326 ] ~ [ wine20010305 ] ~ [ wine20010216 ] ~ [ wine20010112 ] ~ [ wine20001222 ] ~ [ wine20001202 ] ~ [ wine20001026 ] ~ [ wine20001002 ] ~ [ wine20000909 ] ~ [ wine20000821 ] ~ [ wine20000801 ] ~ [ wine20000716 ] ~ [ wine20000326 ] ~ [ wine20000227 ] ~ [ wine20000130 ] ~ [ wine20000109 ] ~

  1 /*
  2  * Wine Driver for EsounD Sound Server
  3  * http://www.tux.org/~ricdude/EsounD.html
  4  *
  5  * Copyright 1994 Martin Ayotte
  6  *           1999 Eric Pouech (async playing in waveOut/waveIn)
  7  *           2000 Eric Pouech (loops in waveOut)
  8  *           2004 Zhangrong Huang (EsounD version of this file)
  9  *
 10  * This library is free software; you can redistribute it and/or
 11  * modify it under the terms of the GNU Lesser General Public
 12  * License as published by the Free Software Foundation; either
 13  * version 2.1 of the License, or (at your option) any later version.
 14  *
 15  * This library is distributed in the hope that it will be useful,
 16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 18  * Lesser General Public License for more details.
 19  *
 20  * You should have received a copy of the GNU Lesser General Public
 21  * License along with this library; if not, write to the Free Software
 22  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 23  */
 24 /* NOTE:
 25  *    with esd we cannot stop the audio that is already in
 26  *    the server's buffer.
 27  *
 28  * FIXME:
 29  *      pause in waveOut does not work correctly in loop mode
 30  *
 31  *      does something need to be done in for WaveIn DirectSound?
 32  *
 33  */
 34 
 35 #include "config.h"
 36 
 37 #include <errno.h>
 38 #include <math.h>
 39 #include <stdlib.h>
 40 #include <stdarg.h>
 41 #include <stdio.h>
 42 #include <string.h>
 43 #ifdef HAVE_UNISTD_H
 44 # include <unistd.h>
 45 #endif
 46 #include <fcntl.h>
 47 #ifdef HAVE_POLL_H
 48 #include <poll.h>
 49 #endif
 50 #ifdef HAVE_SYS_POLL_H
 51 # include <sys/poll.h>
 52 #endif
 53 
 54 #include "windef.h"
 55 #include "winbase.h"
 56 #include "wingdi.h"
 57 #include "winerror.h"
 58 #include "wine/winuser16.h"
 59 #include "mmddk.h"
 60 #include "mmreg.h"
 61 #include "dsound.h"
 62 #include "dsdriver.h"
 63 #include "ks.h"
 64 #include "ksguid.h"
 65 #include "ksmedia.h"
 66 #include "esound.h"
 67 #include "wine/debug.h"
 68 
 69 WINE_DEFAULT_DEBUG_CHANNEL(wave);
 70 
 71 #ifdef HAVE_ESD
 72 
 73 #include <esd.h>
 74 
 75 /* unless someone makes a wineserver kernel module, Unix pipes are faster than win32 events */
 76 #define USE_PIPE_SYNC
 77 
 78 /* define if you want to use esd_monitor_stream instead of
 79  * esd_record_stream for waveIn stream
 80  */
 81 /*#define WID_USE_ESDMON*/
 82 
 83 #define BUFFER_REFILL_THRESHOLD 4
 84 
 85 #define MAX_WAVEOUTDRV  (10)
 86 #define MAX_WAVEINDRV   (10)
 87 #define MAX_CHANNELS    2
 88 
 89 /* state diagram for waveOut writing:
 90  *
 91  * +---------+-------------+---------------+---------------------------------+
 92  * |  state  |  function   |     event     |            new state            |
 93  * +---------+-------------+---------------+---------------------------------+
 94  * |         | open()      |               | STOPPED                         |
 95  * | PAUSED  | write()     |               | PAUSED                          |
 96  * | STOPPED | write()     | <thrd create> | PLAYING                         |
 97  * | PLAYING | write()     | HEADER        | PLAYING                         |
 98  * | (other) | write()     | <error>       |                                 |
 99  * | (any)   | pause()     | PAUSING       | PAUSED                          |
100  * | PAUSED  | restart()   | RESTARTING    | PLAYING (if no thrd => STOPPED) |
101  * | (any)   | reset()     | RESETTING     | STOPPED                         |
102  * | (any)   | close()     | CLOSING       | CLOSED                          |
103  * +---------+-------------+---------------+---------------------------------+
104  */
105 
106 /* states of the playing device */
107 #define WINE_WS_PLAYING         0
108 #define WINE_WS_PAUSED          1
109 #define WINE_WS_STOPPED         2
110 #define WINE_WS_CLOSED          3
111 
112 /* events to be send to device */
113 enum win_wm_message {
114     WINE_WM_PAUSING = WM_USER + 1, WINE_WM_RESTARTING, WINE_WM_RESETTING, WINE_WM_HEADER,
115     WINE_WM_UPDATE, WINE_WM_BREAKLOOP, WINE_WM_CLOSING, WINE_WM_STARTING, WINE_WM_STOPPING
116 };
117 
118 #ifdef USE_PIPE_SYNC
119 #define SIGNAL_OMR(mr) do { int x = 0; write((mr)->msg_pipe[1], &x, sizeof(x)); } while (0)
120 #define CLEAR_OMR(mr) do { int x = 0; read((mr)->msg_pipe[0], &x, sizeof(x)); } while (0)
121 #define RESET_OMR(mr) do { } while (0)
122 #define WAIT_OMR(mr, sleep) \
123   do { struct pollfd pfd; pfd.fd = (mr)->msg_pipe[0]; \
124        pfd.events = POLLIN; poll(&pfd, 1, sleep); } while (0)
125 #else
126 #define SIGNAL_OMR(mr) do { SetEvent((mr)->msg_event); } while (0)
127 #define CLEAR_OMR(mr) do { } while (0)
128 #define RESET_OMR(mr) do { ResetEvent((mr)->msg_event); } while (0)
129 #define WAIT_OMR(mr, sleep) \
130   do { WaitForSingleObject((mr)->msg_event, sleep); } while (0)
131 #endif
132 
133 typedef struct {
134     enum win_wm_message         msg;    /* message identifier */
135     DWORD                       param;  /* parameter for this message */
136     HANDLE                      hEvent; /* if message is synchronous, handle of event for synchro */
137 } RING_MSG;
138 
139 /* implement an in-process message ring for better performance
140  * (compared to passing thru the server)
141  * this ring will be used by the input (resp output) record (resp playback) routine
142  */
143 #define ESD_RING_BUFFER_INCREMENT      64
144 typedef struct {
145     RING_MSG                    * messages;
146     int                         ring_buffer_size;
147     int                         msg_tosave;
148     int                         msg_toget;
149 #ifdef USE_PIPE_SYNC
150     int                         msg_pipe[2];
151 #else
152     HANDLE                      msg_event;
153 #endif
154     CRITICAL_SECTION            msg_crst;
155 } ESD_MSG_RING;
156 
157 typedef struct {
158     volatile int                state;                  /* one of the WINE_WS_ manifest constants */
159     WAVEOPENDESC                waveDesc;
160     WORD                        wFlags;
161     WAVEFORMATPCMEX             waveFormat;
162     WAVEOUTCAPSW                caps;
163     char                        interface_name[32];
164 
165     DWORD                       dwSleepTime;            /* Num of milliseconds to sleep between filling the dsp buffers */
166 
167     /* esd information */
168     int                         esd_fd;         /* the socket fd we get from esd when opening a stream for playing */
169     int                         bytes_per_frame;
170     DWORD                       dwBufferSize;           /* size of whole buffer in bytes */
171 
172     char*                       sound_buffer;
173     long                        buffer_size;
174 
175     DWORD                       volume_left;            /* volume control information */
176     DWORD                       volume_right;
177 
178     LPWAVEHDR                   lpQueuePtr;             /* start of queued WAVEHDRs (waiting to be notified) */
179     LPWAVEHDR                   lpPlayPtr;              /* start of not yet fully played buffers */
180     DWORD                       dwPartialOffset;        /* Offset of not yet written bytes in lpPlayPtr */
181 
182     LPWAVEHDR                   lpLoopPtr;              /* pointer of first buffer in loop, if any */
183     DWORD                       dwLoops;                /* private copy of loop counter */
184 
185     DWORD                       dwPlayedTotal;          /* number of bytes actually played since opening */
186     DWORD                       dwWrittenTotal;         /* number of bytes written to the audio device since opening */
187 
188     /* synchronization stuff */
189     HANDLE                      hStartUpEvent;
190     HANDLE                      hThread;
191     DWORD                       dwThreadID;
192     ESD_MSG_RING                msgRing;
193 } WINE_WAVEOUT;
194 
195 typedef struct {
196     volatile int                state;                  /* one of the WINE_WS_ manifest constants */
197     WAVEOPENDESC                waveDesc;
198     WORD                        wFlags;
199     WAVEFORMATPCMEX             waveFormat;
200     WAVEINCAPSW                 caps;
201     char                        interface_name[32];
202 
203     /* esd information */
204     int                         esd_fd;         /* the socket fd we get from esd when opening a stream for recording */
205     int                         bytes_per_frame;
206 
207     LPWAVEHDR                   lpQueuePtr;
208     DWORD                       dwRecordedTotal;
209 
210     /* synchronization stuff */
211     HANDLE                      hStartUpEvent;
212     HANDLE                      hThread;
213     DWORD                       dwThreadID;
214     ESD_MSG_RING                msgRing;
215 } WINE_WAVEIN;
216 
217 static char* esd_host;  /* the esd host */
218 
219 static WINE_WAVEOUT     WOutDev   [MAX_WAVEOUTDRV];
220 static WINE_WAVEIN      WInDev    [MAX_WAVEINDRV];
221 
222 static DWORD wodDsCreate(UINT wDevID, PIDSDRIVER* drv);
223 static DWORD wodDsDesc(UINT wDevID, PDSDRIVERDESC desc);
224 
225 /* These strings used only for tracing */
226 static const char *wodPlayerCmdString[] = {
227     "WINE_WM_PAUSING",
228     "WINE_WM_RESTARTING",
229     "WINE_WM_RESETTING",
230     "WINE_WM_HEADER",
231     "WINE_WM_UPDATE",
232     "WINE_WM_BREAKLOOP",
233     "WINE_WM_CLOSING",
234     "WINE_WM_STARTING",
235     "WINE_WM_STOPPING",
236 };
237 
238 /*======================================================================*
239  *                  Low level WAVE implementation                       *
240  *======================================================================*/
241 
242 /* Volume functions derived from Alsaplayer source */
243 /* length is the number of 16 bit samples */
244 void volume_effect16(void *bufin, void* bufout, int length, int left,
245                 int right, int  nChannels)
246 {
247   short *d_out = (short *)bufout;
248   short *d_in = (short *)bufin;
249   int i, v;
250 
251 /*
252   TRACE("length == %d, nChannels == %d\n", length, nChannels);
253 */
254 
255   if (right == -1) right = left;
256 
257   for(i = 0; i < length; i+=(nChannels))
258   {
259     v = (int) ((*(d_in++) * left) / 100);
260     *(d_out++) = (v>32767) ? 32767 : ((v<-32768) ? -32768 : v);
261     if(nChannels == 2)
262     {
263       v = (int) ((*(d_in++) * right) / 100);
264       *(d_out++) = (v>32767) ? 32767 : ((v<-32768) ? -32768 : v);
265     }
266   }
267 }
268 
269 /* length is the number of 8 bit samples */
270 static void volume_effect8(void *bufin, void* bufout, int length, int left,
271                 int right, int  nChannels)
272 {
273   BYTE *d_out = (BYTE *)bufout;
274   BYTE *d_in = (BYTE *)bufin;
275   int i, v;
276 
277 /*
278   TRACE("length == %d, nChannels == %d\n", length, nChannels);
279 */
280 
281   if (right == -1) right = left;
282 
283   for(i = 0; i < length; i+=(nChannels))
284   {
285     v = (BYTE) ((*(d_in++) * left) / 100);
286     *(d_out++) = (v>255) ? 255 : ((v<0) ? 0 : v);
287     if(nChannels == 2)
288     {
289       v = (BYTE) ((*(d_in++) * right) / 100);
290       *(d_out++) = (v>255) ? 255 : ((v<0) ? 0 : v);
291     }
292   }
293 }
294 
295 static DWORD bytes_to_mmtime(LPMMTIME lpTime, DWORD position,
296                              WAVEFORMATPCMEX* format)
297 {
298     TRACE("wType=%04X wBitsPerSample=%u nSamplesPerSec=%u nChannels=%u nAvgBytesPerSec=%u\n",
299           lpTime->wType, format->Format.wBitsPerSample, format->Format.nSamplesPerSec,
300           format->Format.nChannels, format->Format.nAvgBytesPerSec);
301     TRACE("Position in bytes=%u\n", position);
302 
303     switch (lpTime->wType) {
304     case TIME_SAMPLES:
305         lpTime->u.sample = position / (format->Format.wBitsPerSample / 8 * format->Format.nChannels);
306         TRACE("TIME_SAMPLES=%u\n", lpTime->u.sample);
307         break;
308     case TIME_MS:
309         lpTime->u.ms = 1000.0 * position / (format->Format.wBitsPerSample / 8 * format->Format.nChannels * format->Format.nSamplesPerSec);
310         TRACE("TIME_MS=%u\n", lpTime->u.ms);
311         break;
312     case TIME_SMPTE:
313         lpTime->u.smpte.fps = 30;
314         position = position / (format->Format.wBitsPerSample / 8 * format->Format.nChannels);
315         position += (format->Format.nSamplesPerSec / lpTime->u.smpte.fps) - 1; /* round up */
316         lpTime->u.smpte.sec = position / format->Format.nSamplesPerSec;
317         position -= lpTime->u.smpte.sec * format->Format.nSamplesPerSec;
318         lpTime->u.smpte.min = lpTime->u.smpte.sec / 60;
319         lpTime->u.smpte.sec -= 60 * lpTime->u.smpte.min;
320         lpTime->u.smpte.hour = lpTime->u.smpte.min / 60;
321         lpTime->u.smpte.min -= 60 * lpTime->u.smpte.hour;
322         lpTime->u.smpte.fps = 30;
323         lpTime->u.smpte.frame = position * lpTime->u.smpte.fps / format->Format.nSamplesPerSec;
324         TRACE("TIME_SMPTE=%02u:%02u:%02u:%02u\n",
325               lpTime->u.smpte.hour, lpTime->u.smpte.min,
326               lpTime->u.smpte.sec, lpTime->u.smpte.frame);
327         break;
328     default:
329         WARN("Format %d not supported, using TIME_BYTES !\n", lpTime->wType);
330         lpTime->wType = TIME_BYTES;
331         /* fall through */
332     case TIME_BYTES:
333         lpTime->u.cb = position;
334         TRACE("TIME_BYTES=%u\n", lpTime->u.cb);
335         break;
336     }
337     return MMSYSERR_NOERROR;
338 }
339 
340 static BOOL supportedFormat(LPWAVEFORMATEX wf)
341 {
342     TRACE("(%p)\n",wf);
343                                                                                 
344     if (wf->nSamplesPerSec<DSBFREQUENCY_MIN||wf->nSamplesPerSec>DSBFREQUENCY_MAX)
345         return FALSE;
346                                                                                 
347     if (wf->wFormatTag == WAVE_FORMAT_PCM) {
348         if (wf->nChannels >= 1 && wf->nChannels <= MAX_CHANNELS) {
349             if (wf->wBitsPerSample==8||wf->wBitsPerSample==16)
350                 return TRUE;
351         }
352     } else if (wf->wFormatTag == WAVE_FORMAT_EXTENSIBLE) {
353         WAVEFORMATEXTENSIBLE * wfex = (WAVEFORMATEXTENSIBLE *)wf;
354                                                                                 
355         if (wf->cbSize == 22 && IsEqualGUID(&wfex->SubFormat, &KSDATAFORMAT_SUBTYPE_PCM)) {
356             if (wf->nChannels >=1 && wf->nChannels <= MAX_CHANNELS) {
357                 if (wf->wBitsPerSample==wfex->Samples.wValidBitsPerSample) {
358                     if (wf->wBitsPerSample==8||wf->wBitsPerSample==16)
359                         return TRUE;
360                 } else
361                     WARN("wBitsPerSample != wValidBitsPerSample not supported yet\n");
362             }
363         } else
364             WARN("only KSDATAFORMAT_SUBTYPE_PCM supported\n");
365     } else
366         WARN("only WAVE_FORMAT_PCM and WAVE_FORMAT_EXTENSIBLE supported\n");
367                                                                                 
368     return FALSE;
369 }
370 
371 void copy_format(LPWAVEFORMATEX wf1, LPWAVEFORMATPCMEX wf2)
372 {
373     ZeroMemory(wf2, sizeof(wf2));
374     if (wf1->wFormatTag == WAVE_FORMAT_PCM)
375         memcpy(wf2, wf1, sizeof(PCMWAVEFORMAT));
376     else if (wf1->wFormatTag == WAVE_FORMAT_EXTENSIBLE)
377         memcpy(wf2, wf1, sizeof(WAVEFORMATPCMEX));
378     else
379         memcpy(wf2, wf1, sizeof(WAVEFORMATEX) + wf1->cbSize);
380 }
381 
382 /******************************************************************
383  *              ESD_CloseWaveOutDevice
384  *
385  */
386 void            ESD_CloseWaveOutDevice(WINE_WAVEOUT* wwo)
387 {
388         esd_close(wwo->esd_fd);         /* close the esd socket fd */
389         wwo->esd_fd = -1;
390 
391   /* free up the buffer we use for volume and reset the size */
392   HeapFree(GetProcessHeap(), 0, wwo->sound_buffer);
393   wwo->sound_buffer = NULL;
394   wwo->buffer_size = 0;
395 }
396 
397 /******************************************************************
398  *              ESD_CloseWaveInDevice
399  *
400  */
401 void            ESD_CloseWaveInDevice(WINE_WAVEIN* wwi)
402 {
403         esd_close(wwi->esd_fd);         /* close the esd socket fd */
404         wwi->esd_fd = -1;
405 }
406 
407 /******************************************************************
408  *              ESD_WaveClose
409  */
410 LONG            ESD_WaveClose(void)
411 {
412     int iDevice;
413 
414     /* close all open devices */
415     for(iDevice = 0; iDevice < MAX_WAVEOUTDRV; iDevice++)
416     {
417       if(WOutDev[iDevice].esd_fd != -1)
418       {
419         ESD_CloseWaveOutDevice(&WOutDev[iDevice]);
420       }
421     }
422 
423     for(iDevice = 0; iDevice < MAX_WAVEINDRV; iDevice++)
424     {
425       if(WInDev[iDevice].esd_fd != -1)
426       {
427         ESD_CloseWaveInDevice(&WInDev[iDevice]);
428       }
429     }
430 
431     return 1;
432 }
433 
434 /******************************************************************
435  *              ESD_WaveInit
436  *
437  * Initialize internal structures from ESD server info
438  */
439 LONG ESD_WaveInit(void)
440 {
441     int         i;
442         int     fd;
443 
444     TRACE("called\n");
445 
446     /* FIXME: Maybe usefully to set the esd host. */
447     esd_host = NULL;
448 
449     /* Testing whether the esd host is alive. */
450     if ((fd = esd_open_sound(esd_host)) < 0)
451     {
452         WARN("esd_open_sound() failed (%d)\n", errno);
453         return -1;
454     }
455     esd_close(fd);
456 
457     /* initialize all device handles to -1 */
458     for (i = 0; i < MAX_WAVEOUTDRV; ++i)
459     {
460         static const WCHAR ini[] = {'E','s','o','u','n','D',' ','W','a','v','e','O','u','t','D','r','i','v','e','r',0};
461 
462         WOutDev[i].esd_fd = -1;
463         memset(&WOutDev[i].caps, 0, sizeof(WOutDev[i].caps)); /* zero out
464                                                         caps values */
465         WOutDev[i].caps.wMid = 0x00FF;  /* Manufacturer ID */
466         WOutDev[i].caps.wPid = 0x0001;  /* Product ID */
467         lstrcpyW(WOutDev[i].caps.szPname, ini);
468         snprintf(WOutDev[i].interface_name, sizeof(WOutDev[i].interface_name), "wineesd: %d", i);
469 
470         WOutDev[i].caps.vDriverVersion = 0x0100;
471         WOutDev[i].caps.dwFormats = 0x00000000;
472         WOutDev[i].caps.dwSupport = WAVECAPS_VOLUME;
473 
474         WOutDev[i].caps.wChannels = 2;
475         WOutDev[i].caps.dwSupport |= WAVECAPS_LRVOLUME;
476 
477         WOutDev[i].caps.dwFormats |= WAVE_FORMAT_4M08;
478         WOutDev[i].caps.dwFormats |= WAVE_FORMAT_4S08;
479         WOutDev[i].caps.dwFormats |= WAVE_FORMAT_4S16;
480         WOutDev[i].caps.dwFormats |= WAVE_FORMAT_4M16;
481         WOutDev[i].caps.dwFormats |= WAVE_FORMAT_2M08;
482         WOutDev[i].caps.dwFormats |= WAVE_FORMAT_2S08;
483         WOutDev[i].caps.dwFormats |= WAVE_FORMAT_2M16;
484         WOutDev[i].caps.dwFormats |= WAVE_FORMAT_2S16;
485         WOutDev[i].caps.dwFormats |= WAVE_FORMAT_1M08;
486         WOutDev[i].caps.dwFormats |= WAVE_FORMAT_1S08;
487         WOutDev[i].caps.dwFormats |= WAVE_FORMAT_1M16;
488         WOutDev[i].caps.dwFormats |= WAVE_FORMAT_1S16;
489     }
490 
491     for (i = 0; i < MAX_WAVEINDRV; ++i)
492     {
493         static const WCHAR ini[] = {'E','s','o','u','n','D',' ','W','a','v','e','I','n','D','r','i','v','e','r',0};
494 
495         WInDev[i].esd_fd = -1;
496         memset(&WInDev[i].caps, 0, sizeof(WInDev[i].caps)); /* zero out
497                                                         caps values */
498         WInDev[i].caps.wMid = 0x00FF;
499         WInDev[i].caps.wPid = 0x0001;
500         lstrcpyW(WInDev[i].caps.szPname, ini);
501         snprintf(WInDev[i].interface_name, sizeof(WInDev[i].interface_name), "wineesd: %d", i);
502 
503         WInDev[i].caps.vDriverVersion = 0x0100;
504         WInDev[i].caps.dwFormats = 0x00000000;
505 
506         WInDev[i].caps.wChannels = 2;
507 
508         WInDev[i].caps.dwFormats |= WAVE_FORMAT_4M08;
509         WInDev[i].caps.dwFormats |= WAVE_FORMAT_4S08;
510         WInDev[i].caps.dwFormats |= WAVE_FORMAT_4S16;
511         WInDev[i].caps.dwFormats |= WAVE_FORMAT_4M16;
512         WInDev[i].caps.dwFormats |= WAVE_FORMAT_2M08;
513         WInDev[i].caps.dwFormats |= WAVE_FORMAT_2S08;
514         WInDev[i].caps.dwFormats |= WAVE_FORMAT_2M16;
515         WInDev[i].caps.dwFormats |= WAVE_FORMAT_2S16;
516         WInDev[i].caps.dwFormats |= WAVE_FORMAT_1M08;
517         WInDev[i].caps.dwFormats |= WAVE_FORMAT_1S08;
518         WInDev[i].caps.dwFormats |= WAVE_FORMAT_1M16;
519         WInDev[i].caps.dwFormats |= WAVE_FORMAT_1S16;
520 
521         WInDev[i].caps.wReserved1 = 0;
522     }
523     return 0;
524 }
525 
526 /******************************************************************
527  *              ESD_InitRingMessage
528  *
529  * Initialize the ring of messages for passing between driver's caller and playback/record
530  * thread
531  */
532 static int ESD_InitRingMessage(ESD_MSG_RING* mr)
533 {
534     mr->msg_toget = 0;
535     mr->msg_tosave = 0;
536 #ifdef USE_PIPE_SYNC
537     if (pipe(mr->msg_pipe) < 0) {
538         mr->msg_pipe[0] = -1;
539         mr->msg_pipe[1] = -1;
540         ERR("could not create pipe, error=%s\n", strerror(errno));
541     }
542 #else
543     mr->msg_event = CreateEventW(NULL, FALSE, FALSE, NULL);
544 #endif
545     mr->ring_buffer_size = ESD_RING_BUFFER_INCREMENT;
546     mr->messages = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,mr->ring_buffer_size * sizeof(RING_MSG));
547     InitializeCriticalSection(&mr->msg_crst);
548     mr->msg_crst.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": ESD_MSG_RING.msg_crst");
549     return 0;
550 }
551 
552 /******************************************************************
553  *              ESD_DestroyRingMessage
554  *
555  */
556 static int ESD_DestroyRingMessage(ESD_MSG_RING* mr)
557 {
558 #ifdef USE_PIPE_SYNC
559     close(mr->msg_pipe[0]);
560     close(mr->msg_pipe[1]);
561 #else
562     CloseHandle(mr->msg_event);
563 #endif
564     HeapFree(GetProcessHeap(),0,mr->messages);
565     mr->messages=NULL;
566     mr->msg_crst.DebugInfo->Spare[0] = 0;
567     DeleteCriticalSection(&mr->msg_crst);
568     return 0;
569 }
570 
571 /******************************************************************
572  *              ESD_AddRingMessage
573  *
574  * Inserts a new message into the ring (should be called from DriverProc derived routines)
575  */
576 static int ESD_AddRingMessage(ESD_MSG_RING* mr, enum win_wm_message msg, DWORD param, BOOL wait)
577 {
578     HANDLE      hEvent = INVALID_HANDLE_VALUE;
579 
580     EnterCriticalSection(&mr->msg_crst);
581     if ((mr->msg_toget == ((mr->msg_tosave + 1) % mr->ring_buffer_size)))
582     {
583         int old_ring_buffer_size = mr->ring_buffer_size;
584         mr->ring_buffer_size += ESD_RING_BUFFER_INCREMENT;
585         TRACE("mr->ring_buffer_size=%d\n",mr->ring_buffer_size);
586         mr->messages = HeapReAlloc(GetProcessHeap(),0,mr->messages, mr->ring_buffer_size * sizeof(RING_MSG));
587         /* Now we need to rearrange the ring buffer so that the new
588            buffers just allocated are in between mr->msg_tosave and
589            mr->msg_toget.
590         */
591         if (mr->msg_tosave < mr->msg_toget)
592         {
593             memmove(&(mr->messages[mr->msg_toget + ESD_RING_BUFFER_INCREMENT]),
594                     &(mr->messages[mr->msg_toget]),
595                     sizeof(RING_MSG)*(old_ring_buffer_size - mr->msg_toget)
596                     );
597             mr->msg_toget += ESD_RING_BUFFER_INCREMENT;
598         }
599     }
600     if (wait)
601     {
602         hEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
603         if (hEvent == INVALID_HANDLE_VALUE)
604         {
605             ERR("can't create event !?\n");
606             LeaveCriticalSection(&mr->msg_crst);
607             return 0;
608         }
609         if (mr->msg_toget != mr->msg_tosave && mr->messages[mr->msg_toget].msg != WINE_WM_HEADER)
610             FIXME("two fast messages in the queue!!!!\n");
611 
612         /* fast messages have to be added at the start of the queue */
613         mr->msg_toget = (mr->msg_toget + mr->ring_buffer_size - 1) % mr->ring_buffer_size;
614 
615         mr->messages[mr->msg_toget].msg = msg;
616         mr->messages[mr->msg_toget].param = param;
617         mr->messages[mr->msg_toget].hEvent = hEvent;
618     }
619     else
620     {
621         mr->messages[mr->msg_tosave].msg = msg;
622         mr->messages[mr->msg_tosave].param = param;
623         mr->messages[mr->msg_tosave].hEvent = INVALID_HANDLE_VALUE;
624         mr->msg_tosave = (mr->msg_tosave + 1) % mr->ring_buffer_size;
625     }
626 
627     LeaveCriticalSection(&mr->msg_crst);
628 
629     /* signal a new message */
630     SIGNAL_OMR(mr);
631     if (wait)
632     {
633         /* wait for playback/record thread to have processed the message */
634         WaitForSingleObject(hEvent, INFINITE);
635         CloseHandle(hEvent);
636     }
637 
638     return 1;
639 }
640 
641 /******************************************************************
642  *              ESD_RetrieveRingMessage
643  *
644  * Get a message from the ring. Should be called by the playback/record thread.
645  */
646 static int ESD_RetrieveRingMessage(ESD_MSG_RING* mr,
647                                    enum win_wm_message *msg, DWORD *param, HANDLE *hEvent)
648 {
649     EnterCriticalSection(&mr->msg_crst);
650 
651     if (mr->msg_toget == mr->msg_tosave) /* buffer empty ? */
652     {
653         LeaveCriticalSection(&mr->msg_crst);
654         return 0;
655     }
656 
657     *msg = mr->messages[mr->msg_toget].msg;
658     mr->messages[mr->msg_toget].msg = 0;
659     *param = mr->messages[mr->msg_toget].param;
660     *hEvent = mr->messages[mr->msg_toget].hEvent;
661     mr->msg_toget = (mr->msg_toget + 1) % mr->ring_buffer_size;
662     CLEAR_OMR(mr);
663     LeaveCriticalSection(&mr->msg_crst);
664     return 1;
665 }
666 
667 /*======================================================================*
668  *                  Low level WAVE OUT implementation                   *
669  *======================================================================*/
670 
671 /**************************************************************************
672  *                      wodNotifyClient                 [internal]
673  */
674 static DWORD wodNotifyClient(WINE_WAVEOUT* wwo, WORD wMsg, DWORD dwParam1, DWORD dwParam2)
675 {
676     TRACE("wMsg = 0x%04x dwParm1 = %04X dwParam2 = %04X\n", wMsg, dwParam1, dwParam2);
677 
678     switch (wMsg) {
679     case WOM_OPEN:
680     case WOM_CLOSE:
681     case WOM_DONE:
682         if (wwo->wFlags != DCB_NULL &&
683             !DriverCallback(wwo->waveDesc.dwCallback, wwo->wFlags, (HDRVR)wwo->waveDesc.hWave,
684                             wMsg, wwo->waveDesc.dwInstance, dwParam1, dwParam2)) {
685             WARN("can't notify client !\n");
686             return MMSYSERR_ERROR;
687         }
688         break;
689     default:
690         FIXME("Unknown callback message %u\n", wMsg);
691         return MMSYSERR_INVALPARAM;
692     }
693     return MMSYSERR_NOERROR;
694 }
695 
696 /**************************************************************************
697  *                              wodUpdatePlayedTotal    [internal]
698  *
699  */
700 static BOOL wodUpdatePlayedTotal(WINE_WAVEOUT* wwo)
701 {
702     /* total played is the bytes written less the bytes to write ;-) */
703     wwo->dwPlayedTotal = wwo->dwWrittenTotal;
704 
705     return TRUE;
706 }
707 
708 /**************************************************************************
709  *                              wodPlayer_BeginWaveHdr          [internal]
710  *
711  * Makes the specified lpWaveHdr the currently playing wave header.
712  * If the specified wave header is a begin loop and we're not already in
713  * a loop, setup the loop.
714  */
715 static void wodPlayer_BeginWaveHdr(WINE_WAVEOUT* wwo, LPWAVEHDR lpWaveHdr)
716 {
717     wwo->lpPlayPtr = lpWaveHdr;
718 
719     if (!lpWaveHdr) return;
720 
721     if (lpWaveHdr->dwFlags & WHDR_BEGINLOOP) {
722         if (wwo->lpLoopPtr) {
723             WARN("Already in a loop. Discarding loop on this header (%p)\n", lpWaveHdr);
724             TRACE("Already in a loop. Discarding loop on this header (%p)\n", lpWaveHdr);
725         } else {
726             TRACE("Starting loop (%dx) with %p\n", lpWaveHdr->dwLoops, lpWaveHdr);
727             wwo->lpLoopPtr = lpWaveHdr;
728             /* Windows does not touch WAVEHDR.dwLoops,
729              * so we need to make an internal copy */
730             wwo->dwLoops = lpWaveHdr->dwLoops;
731         }
732     }
733     wwo->dwPartialOffset = 0;
734 }
735 
736 /**************************************************************************
737  *                              wodPlayer_PlayPtrNext           [internal]
738  *
739  * Advance the play pointer to the next waveheader, looping if required.
740  */
741 static LPWAVEHDR wodPlayer_PlayPtrNext(WINE_WAVEOUT* wwo)
742 {
743     LPWAVEHDR lpWaveHdr = wwo->lpPlayPtr;
744 
745     wwo->dwPartialOffset = 0;
746     if ((lpWaveHdr->dwFlags & WHDR_ENDLOOP) && wwo->lpLoopPtr) {
747         /* We're at the end of a loop, loop if required */
748         if (--wwo->dwLoops > 0) {
749             wwo->lpPlayPtr = wwo->lpLoopPtr;
750         } else {
751             /* Handle overlapping loops correctly */
752             if (wwo->lpLoopPtr != lpWaveHdr && (lpWaveHdr->dwFlags & WHDR_BEGINLOOP)) {
753                 FIXME("Correctly handled case ? (ending loop buffer also starts a new loop)\n");
754                 /* shall we consider the END flag for the closing loop or for
755                  * the opening one or for both ???
756                  * code assumes for closing loop only
757                  */
758             } else {
759                 lpWaveHdr = lpWaveHdr->lpNext;
760             }
761             wwo->lpLoopPtr = NULL;
762             wodPlayer_BeginWaveHdr(wwo, lpWaveHdr);
763         }
764     } else {
765         /* We're not in a loop.  Advance to the next wave header */
766         wodPlayer_BeginWaveHdr(wwo, lpWaveHdr = lpWaveHdr->lpNext);
767     }
768 
769     return lpWaveHdr;
770 }
771 
772 /**************************************************************************
773  *                           wodPlayer_NotifyWait               [internal]
774  * Returns the number of milliseconds to wait before attempting to notify
775  * completion of the specified wavehdr.
776  * This is based on the number of bytes remaining to be written in the
777  * wave.
778  */
779 static DWORD wodPlayer_NotifyWait(const WINE_WAVEOUT* wwo, LPWAVEHDR lpWaveHdr)
780 {
781     DWORD dwMillis;
782 
783     if(lpWaveHdr->reserved < wwo->dwPlayedTotal)
784     {
785         dwMillis = 1;
786     }
787     else
788     {
789         dwMillis = (lpWaveHdr->reserved - wwo->dwPlayedTotal) * 1000 / wwo->waveFormat.Format.nAvgBytesPerSec;
790         if(!dwMillis) dwMillis = 1;
791     }
792 
793     TRACE("dwMillis = %d\n", dwMillis);
794 
795     return dwMillis;
796 }
797 
798 
799 /**************************************************************************
800  *                           wodPlayer_WriteMaxFrags            [internal]
801  * Writes the maximum number of bytes possible to the DSP and returns
802  * the number of bytes written.
803  */
804 static int wodPlayer_WriteMaxFrags(WINE_WAVEOUT* wwo, DWORD* bytes)
805 {
806     /* Only attempt to write to free bytes */
807     DWORD dwLength = wwo->lpPlayPtr->dwBufferLength - wwo->dwPartialOffset;
808     int toWrite = min(dwLength, *bytes);
809     int written;
810 
811     TRACE("Writing wavehdr %p.%u[%u]\n",
812           wwo->lpPlayPtr, wwo->dwPartialOffset, wwo->lpPlayPtr->dwBufferLength);
813 
814     /* see if our buffer isn't large enough for the data we are writing */
815     if(wwo->buffer_size < toWrite)
816     {
817       if(wwo->sound_buffer)
818       {
819         wwo->sound_buffer = HeapReAlloc(GetProcessHeap(), 0, wwo->sound_buffer, toWrite);
820         wwo->buffer_size = toWrite;
821       }
822     }
823 
824     /* if we don't have a buffer then get one */
825     if(!wwo->sound_buffer)
826     {
827       /* allocate some memory for the buffer */
828       wwo->sound_buffer = HeapAlloc(GetProcessHeap(), 0, toWrite);
829       wwo->buffer_size = toWrite;
830     }
831 
832     /* if we don't have a buffer then error out */
833     if(!wwo->sound_buffer)
834     {
835       ERR("error allocating sound_buffer memory\n");
836       return 0;
837     }
838 
839     TRACE("toWrite == %d\n", toWrite);
840 
841     /* apply volume to the bits */
842     /* for single channel audio streams we only use the LEFT volume */
843     if(wwo->waveFormat.Format.wBitsPerSample == 16)
844     {
845       /* apply volume to the buffer we are about to send */
846       /* divide toWrite(bytes) by 2 as volume processes by 16 bits */
847       volume_effect16(wwo->lpPlayPtr->lpData + wwo->dwPartialOffset,
848                 wwo->sound_buffer, toWrite>>1, wwo->volume_left,
849                 wwo->volume_right, wwo->waveFormat.Format.nChannels);
850     } else if(wwo->waveFormat.Format.wBitsPerSample == 8)
851     {
852       /* apply volume to the buffer we are about to send */
853       volume_effect8(wwo->lpPlayPtr->lpData + wwo->dwPartialOffset,
854                 wwo->sound_buffer, toWrite, wwo->volume_left,
855                 wwo->volume_right, wwo->waveFormat.Format.nChannels);
856     } else
857     {
858       FIXME("unsupported wwo->format.wBitsPerSample of %d\n",
859         wwo->waveFormat.Format.wBitsPerSample);
860     }
861 
862     /* send the audio data to esd for playing */
863     written = write(wwo->esd_fd, wwo->sound_buffer, toWrite);
864 
865     TRACE("written = %d\n", written);
866 
867     if (written <= 0) 
868     {
869       *bytes = 0; /* apparently esd is actually full */
870       return written; /* if we wrote nothing just return */
871     }
872 
873     if (written >= dwLength)
874         wodPlayer_PlayPtrNext(wwo);   /* If we wrote all current wavehdr, skip to the next one */
875     else
876         wwo->dwPartialOffset += written;    /* Remove the amount written */
877 
878     if (written < toWrite)
879         *bytes = 0;
880     else
881         *bytes -= written;
882 
883     wwo->dwWrittenTotal += written; /* update stats on this wave device */
884 
885     return written; /* return the number of bytes written */
886 }
887 
888 
889 /**************************************************************************
890  *                              wodPlayer_NotifyCompletions     [internal]
891  *
892  * Notifies and remove from queue all wavehdrs which have been played to
893  * the speaker (ie. they have cleared the audio device).  If force is true,
894  * we notify all wavehdrs and remove them all from the queue even if they
895  * are unplayed or part of a loop.
896  */
897 static DWORD wodPlayer_NotifyCompletions(WINE_WAVEOUT* wwo, BOOL force)
898 {
899     LPWAVEHDR           lpWaveHdr;
900 
901     if (wwo->lpQueuePtr) {
902         TRACE("lpWaveHdr=(%p), lpPlayPtr=(%p), lpLoopPtr=(%p), reserved=(%d), dwWrittenTotal=(%d), force=(%d)\n",
903               wwo->lpQueuePtr,
904               wwo->lpPlayPtr,
905               wwo->lpLoopPtr,
906               wwo->lpQueuePtr->reserved,
907               wwo->dwWrittenTotal,
908               force);
909     } else {
910         TRACE("lpWaveHdr=(%p), lpPlayPtr=(%p), lpLoopPtr=(%p),  dwWrittenTotal=(%d), force=(%d)\n",
911               wwo->lpQueuePtr,
912               wwo->lpPlayPtr,
913               wwo->lpLoopPtr,
914               wwo->dwWrittenTotal,
915               force);
916     }
917 
918     /* Start from lpQueuePtr and keep notifying until:
919      * - we hit an unwritten wavehdr
920      * - we hit the beginning of a running loop
921      * - we hit a wavehdr which hasn't finished playing
922      */
923     while ((lpWaveHdr = wwo->lpQueuePtr) &&
924            (force ||
925             (lpWaveHdr != wwo->lpPlayPtr &&
926              lpWaveHdr != wwo->lpLoopPtr &&
927              lpWaveHdr->reserved <= wwo->dwWrittenTotal))) {
928 
929         wwo->lpQueuePtr = lpWaveHdr->lpNext;
930 
931         lpWaveHdr->