Unicodify wineesd.
[wine] / dlls / winmm / wineesd / audio.c
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23  */
24 /* NOTE:
25  *    with esd we cannot stop the audio that is already in
26  *    the servers 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 <math.h>
38 #include <stdlib.h>
39 #include <stdarg.h>
40 #include <stdio.h>
41 #include <string.h>
42 #ifdef HAVE_UNISTD_H
43 # include <unistd.h>
44 #endif
45 #include <fcntl.h>
46 #include "windef.h"
47 #include "winbase.h"
48 #include "wingdi.h"
49 #include "winerror.h"
50 #include "wine/winuser16.h"
51 #include "mmddk.h"
52 #include "dsound.h"
53 #include "dsdriver.h"
54 #include "esound.h"
55 #include "wine/debug.h"
56
57 WINE_DEFAULT_DEBUG_CHANNEL(wave);
58
59 #ifdef HAVE_ESD
60
61 #include <esd.h>
62
63 /* define if you want to use esd_monitor_stream instead of
64  * esd_record_stream for waveIn stream
65  */
66 /*#define WID_USE_ESDMON*/
67
68 #define BUFFER_REFILL_THRESHOLD 4
69
70 #define MAX_WAVEOUTDRV  (10)
71 #define MAX_WAVEINDRV   (10)
72
73 /* state diagram for waveOut writing:
74  *
75  * +---------+-------------+---------------+---------------------------------+
76  * |  state  |  function   |     event     |            new state            |
77  * +---------+-------------+---------------+---------------------------------+
78  * |         | open()      |               | STOPPED                         |
79  * | PAUSED  | write()     |               | PAUSED                          |
80  * | STOPPED | write()     | <thrd create> | PLAYING                         |
81  * | PLAYING | write()     | HEADER        | PLAYING                         |
82  * | (other) | write()     | <error>       |                                 |
83  * | (any)   | pause()     | PAUSING       | PAUSED                          |
84  * | PAUSED  | restart()   | RESTARTING    | PLAYING (if no thrd => STOPPED) |
85  * | (any)   | reset()     | RESETTING     | STOPPED                         |
86  * | (any)   | close()     | CLOSING       | CLOSED                          |
87  * +---------+-------------+---------------+---------------------------------+
88  */
89
90 /* states of the playing device */
91 #define WINE_WS_PLAYING         0
92 #define WINE_WS_PAUSED          1
93 #define WINE_WS_STOPPED         2
94 #define WINE_WS_CLOSED          3
95
96 /* events to be send to device */
97 enum win_wm_message {
98     WINE_WM_PAUSING = WM_USER + 1, WINE_WM_RESTARTING, WINE_WM_RESETTING, WINE_WM_HEADER,
99     WINE_WM_UPDATE, WINE_WM_BREAKLOOP, WINE_WM_CLOSING, WINE_WM_STARTING, WINE_WM_STOPPING
100 };
101
102 typedef struct {
103     enum win_wm_message         msg;    /* message identifier */
104     DWORD                       param;  /* parameter for this message */
105     HANDLE                      hEvent; /* if message is synchronous, handle of event for synchro */
106 } RING_MSG;
107
108 /* implement an in-process message ring for better performance
109  * (compared to passing thru the server)
110  * this ring will be used by the input (resp output) record (resp playback) routine
111  */
112 #define ESD_RING_BUFFER_INCREMENT      64
113 typedef struct {
114     RING_MSG                    * messages;
115     int                         ring_buffer_size;
116     int                         msg_tosave;
117     int                         msg_toget;
118     HANDLE                      msg_event;
119     CRITICAL_SECTION            msg_crst;
120 } ESD_MSG_RING;
121
122 typedef struct {
123     volatile int                state;                  /* one of the WINE_WS_ manifest constants */
124     WAVEOPENDESC                waveDesc;
125     WORD                        wFlags;
126     PCMWAVEFORMAT               format;
127     WAVEOUTCAPSW                caps;
128     char                        interface_name[32];
129
130     DWORD                       dwSleepTime;            /* Num of milliseconds to sleep between filling the dsp buffers */
131
132     /* esd information */
133     int                         esd_fd;         /* the socket fd we get from esd when opening a stream for playing */
134     int                         bytes_per_frame;
135     DWORD                       dwBufferSize;           /* size of whole buffer in bytes */
136
137     char*                       sound_buffer;
138     long                        buffer_size;
139
140     DWORD                       volume_left;            /* volume control information */
141     DWORD                       volume_right;
142
143     LPWAVEHDR                   lpQueuePtr;             /* start of queued WAVEHDRs (waiting to be notified) */
144     LPWAVEHDR                   lpPlayPtr;              /* start of not yet fully played buffers */
145     DWORD                       dwPartialOffset;        /* Offset of not yet written bytes in lpPlayPtr */
146
147     LPWAVEHDR                   lpLoopPtr;              /* pointer of first buffer in loop, if any */
148     DWORD                       dwLoops;                /* private copy of loop counter */
149
150     DWORD                       dwPlayedTotal;          /* number of bytes actually played since opening */
151     DWORD                       dwWrittenTotal;         /* number of bytes written to the audio device since opening */
152
153     /* synchronization stuff */
154     HANDLE                      hStartUpEvent;
155     HANDLE                      hThread;
156     DWORD                       dwThreadID;
157     ESD_MSG_RING                msgRing;
158 } WINE_WAVEOUT;
159
160 typedef struct {
161     volatile int                state;                  /* one of the WINE_WS_ manifest constants */
162     WAVEOPENDESC                waveDesc;
163     WORD                        wFlags;
164     PCMWAVEFORMAT               format;
165     WAVEINCAPSW                 caps;
166     char                        interface_name[32];
167
168     /* esd information */
169     int                         esd_fd;         /* the socket fd we get from esd when opening a stream for recording */
170     int                         bytes_per_frame;
171
172     LPWAVEHDR                   lpQueuePtr;
173     DWORD                       dwRecordedTotal;
174
175     /* synchronization stuff */
176     HANDLE                      hStartUpEvent;
177     HANDLE                      hThread;
178     DWORD                       dwThreadID;
179     ESD_MSG_RING                msgRing;
180 } WINE_WAVEIN;
181
182 static char* esd_host;  /* the esd host */
183
184 static WINE_WAVEOUT     WOutDev   [MAX_WAVEOUTDRV];
185 static WINE_WAVEIN      WInDev    [MAX_WAVEINDRV];
186
187 static DWORD wodDsCreate(UINT wDevID, PIDSDRIVER* drv);
188 static DWORD wodDsDesc(UINT wDevID, PDSDRIVERDESC desc);
189
190 /* These strings used only for tracing */
191 static const char *wodPlayerCmdString[] = {
192     "WINE_WM_PAUSING",
193     "WINE_WM_RESTARTING",
194     "WINE_WM_RESETTING",
195     "WINE_WM_HEADER",
196     "WINE_WM_UPDATE",
197     "WINE_WM_BREAKLOOP",
198     "WINE_WM_CLOSING",
199     "WINE_WM_STARTING",
200     "WINE_WM_STOPPING",
201 };
202
203 /*======================================================================*
204  *                  Low level WAVE implementation                       *
205  *======================================================================*/
206
207 /* Volume functions derived from Alsaplayer source */
208 /* length is the number of 16 bit samples */
209 void volume_effect16(void *bufin, void* bufout, int length, int left,
210                 int right, int  nChannels)
211 {
212   short *d_out = (short *)bufout;
213   short *d_in = (short *)bufin;
214   int i, v;
215
216 /*
217   TRACE("length == %d, nChannels == %d\n", length, nChannels);
218 */
219
220   if (right == -1) right = left;
221
222   for(i = 0; i < length; i+=(nChannels))
223   {
224     v = (int) ((*(d_in++) * left) / 100);
225     *(d_out++) = (v>32767) ? 32767 : ((v<-32768) ? -32768 : v);
226     if(nChannels == 2)
227     {
228       v = (int) ((*(d_in++) * right) / 100);
229       *(d_out++) = (v>32767) ? 32767 : ((v<-32768) ? -32768 : v);
230     }
231   }
232 }
233
234 /* length is the number of 8 bit samples */
235 void volume_effect8(void *bufin, void* bufout, int length, int left,
236                 int right, int  nChannels)
237 {
238   BYTE *d_out = (BYTE *)bufout;
239   BYTE *d_in = (BYTE *)bufin;
240   int i, v;
241
242 /*
243   TRACE("length == %d, nChannels == %d\n", length, nChannels);
244 */
245
246   if (right == -1) right = left;
247
248   for(i = 0; i < length; i+=(nChannels))
249   {
250     v = (BYTE) ((*(d_in++) * left) / 100);
251     *(d_out++) = (v>255) ? 255 : ((v<0) ? 0 : v);
252     if(nChannels == 2)
253     {
254       v = (BYTE) ((*(d_in++) * right) / 100);
255       *(d_out++) = (v>255) ? 255 : ((v<0) ? 0 : v);
256     }
257   }
258 }
259
260 /******************************************************************
261  *              ESD_CloseWaveOutDevice
262  *
263  */
264 void            ESD_CloseWaveOutDevice(WINE_WAVEOUT* wwo)
265 {
266         esd_close(wwo->esd_fd);         /* close the esd socket fd */
267         wwo->esd_fd = -1;
268
269   /* free up the buffer we use for volume and reset the size */
270   if(wwo->sound_buffer)
271   {
272     HeapFree(GetProcessHeap(), 0, wwo->sound_buffer);
273     wwo->sound_buffer = NULL;
274   }
275
276   wwo->buffer_size = 0;
277 }
278
279 /******************************************************************
280  *              ESD_CloseWaveInDevice
281  *
282  */
283 void            ESD_CloseWaveInDevice(WINE_WAVEIN* wwi)
284 {
285         esd_close(wwi->esd_fd);         /* close the esd socket fd */
286         wwi->esd_fd = -1;
287 }
288
289 /******************************************************************
290  *              ESD_WaveClose
291  */
292 LONG            ESD_WaveClose(void)
293 {
294     int iDevice;
295
296     /* close all open devices */
297     for(iDevice = 0; iDevice < MAX_WAVEOUTDRV; iDevice++)
298     {
299       if(WOutDev[iDevice].esd_fd != -1)
300       {
301         ESD_CloseWaveOutDevice(&WOutDev[iDevice]);
302       }
303     }
304
305     for(iDevice = 0; iDevice < MAX_WAVEINDRV; iDevice++)
306     {
307       if(WInDev[iDevice].esd_fd != -1)
308       {
309         ESD_CloseWaveInDevice(&WInDev[iDevice]);
310       }
311     }
312
313     return 1;
314 }
315
316 /******************************************************************
317  *              ESD_WaveInit
318  *
319  * Initialize internal structures from ESD server info
320  */
321 LONG ESD_WaveInit(void)
322 {
323     int         i;
324         int     fd;
325
326     TRACE("called\n");
327
328     /* FIXME: Maybe usefully to set the esd host. */
329     esd_host = NULL;
330
331     /* Testing whether the esd host is alive. */
332     if ((fd = esd_open_sound(esd_host)) < 0)
333     {
334         WARN("esd_open_sound() failed (%d)\n", errno);
335         return -1;
336     }
337     esd_close(fd);
338
339     /* initialize all device handles to -1 */
340     for (i = 0; i < MAX_WAVEOUTDRV; ++i)
341     {
342         static const WCHAR ini[] = {'E','s','o','u','n','D',' ','W','a','v','e','O','u','t','D','r','i','v','e','r',0};
343
344         WOutDev[i].esd_fd = -1;
345         memset(&WOutDev[i].caps, 0, sizeof(WOutDev[i].caps)); /* zero out
346                                                         caps values */
347         WOutDev[i].caps.wMid = 0x00FF;  /* Manufac ID */
348         WOutDev[i].caps.wPid = 0x0001;  /* Product ID */
349         lstrcpyW(WOutDev[i].caps.szPname, ini);
350         snprintf(WOutDev[i].interface_name, sizeof(WOutDev[i].interface_name), "wineesd: %d", i);
351
352         WOutDev[i].caps.vDriverVersion = 0x0100;
353         WOutDev[i].caps.dwFormats = 0x00000000;
354         WOutDev[i].caps.dwSupport = WAVECAPS_VOLUME;
355
356         WOutDev[i].caps.wChannels = 2;
357         WOutDev[i].caps.dwSupport |= WAVECAPS_LRVOLUME;
358
359         WOutDev[i].caps.dwFormats |= WAVE_FORMAT_4M08;
360         WOutDev[i].caps.dwFormats |= WAVE_FORMAT_4S08;
361         WOutDev[i].caps.dwFormats |= WAVE_FORMAT_4S16;
362         WOutDev[i].caps.dwFormats |= WAVE_FORMAT_4M16;
363         WOutDev[i].caps.dwFormats |= WAVE_FORMAT_2M08;
364         WOutDev[i].caps.dwFormats |= WAVE_FORMAT_2S08;
365         WOutDev[i].caps.dwFormats |= WAVE_FORMAT_2M16;
366         WOutDev[i].caps.dwFormats |= WAVE_FORMAT_2S16;
367         WOutDev[i].caps.dwFormats |= WAVE_FORMAT_1M08;
368         WOutDev[i].caps.dwFormats |= WAVE_FORMAT_1S08;
369         WOutDev[i].caps.dwFormats |= WAVE_FORMAT_1M16;
370         WOutDev[i].caps.dwFormats |= WAVE_FORMAT_1S16;
371     }
372
373     for (i = 0; i < MAX_WAVEINDRV; ++i)
374     {
375         static const WCHAR ini[] = {'E','s','o','u','n','D',' ','W','a','v','e','I','n','D','r','i','v','e','r',0};
376
377         WInDev[i].esd_fd = -1;
378         memset(&WInDev[i].caps, 0, sizeof(WInDev[i].caps)); /* zero out
379                                                         caps values */
380         WInDev[i].caps.wMid = 0x00FF;
381         WInDev[i].caps.wPid = 0x0001;
382         lstrcpyW(WInDev[i].caps.szPname, ini);
383         snprintf(WInDev[i].interface_name, sizeof(WInDev[i].interface_name), "wineesd: %d", i);
384
385         WInDev[i].caps.vDriverVersion = 0x0100;
386         WInDev[i].caps.dwFormats = 0x00000000;
387
388         WInDev[i].caps.wChannels = 2;
389
390         WInDev[i].caps.dwFormats |= WAVE_FORMAT_4M08;
391         WInDev[i].caps.dwFormats |= WAVE_FORMAT_4S08;
392         WInDev[i].caps.dwFormats |= WAVE_FORMAT_4S16;
393         WInDev[i].caps.dwFormats |= WAVE_FORMAT_4M16;
394         WInDev[i].caps.dwFormats |= WAVE_FORMAT_2M08;
395         WInDev[i].caps.dwFormats |= WAVE_FORMAT_2S08;
396         WInDev[i].caps.dwFormats |= WAVE_FORMAT_2M16;
397         WInDev[i].caps.dwFormats |= WAVE_FORMAT_2S16;
398         WInDev[i].caps.dwFormats |= WAVE_FORMAT_1M08;
399         WInDev[i].caps.dwFormats |= WAVE_FORMAT_1S08;
400         WInDev[i].caps.dwFormats |= WAVE_FORMAT_1M16;
401         WInDev[i].caps.dwFormats |= WAVE_FORMAT_1S16;
402
403         WInDev[i].caps.wReserved1 = 0;
404     }
405     return 0;
406 }
407
408 /******************************************************************
409  *              ESD_InitRingMessage
410  *
411  * Initialize the ring of messages for passing between driver's caller and playback/record
412  * thread
413  */
414 static int ESD_InitRingMessage(ESD_MSG_RING* mr)
415 {
416     mr->msg_toget = 0;
417     mr->msg_tosave = 0;
418     mr->msg_event = CreateEventW(NULL, FALSE, FALSE, NULL);
419     mr->ring_buffer_size = ESD_RING_BUFFER_INCREMENT;
420     mr->messages = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,mr->ring_buffer_size * sizeof(RING_MSG));
421     InitializeCriticalSection(&mr->msg_crst);
422     return 0;
423 }
424
425 /******************************************************************
426  *              ESD_DestroyRingMessage
427  *
428  */
429 static int ESD_DestroyRingMessage(ESD_MSG_RING* mr)
430 {
431     CloseHandle(mr->msg_event);
432     HeapFree(GetProcessHeap(),0,mr->messages);
433     mr->messages=NULL;
434     DeleteCriticalSection(&mr->msg_crst);
435     return 0;
436 }
437
438 /******************************************************************
439  *              ESD_AddRingMessage
440  *
441  * Inserts a new message into the ring (should be called from DriverProc derivated routines)
442  */
443 static int ESD_AddRingMessage(ESD_MSG_RING* mr, enum win_wm_message msg, DWORD param, BOOL wait)
444 {
445     HANDLE      hEvent = INVALID_HANDLE_VALUE;
446
447     EnterCriticalSection(&mr->msg_crst);
448     if ((mr->msg_toget == ((mr->msg_tosave + 1) % mr->ring_buffer_size)))
449     {
450         int old_ring_buffer_size = mr->ring_buffer_size;
451         mr->ring_buffer_size += ESD_RING_BUFFER_INCREMENT;
452         TRACE("mr->ring_buffer_size=%d\n",mr->ring_buffer_size);
453         mr->messages = HeapReAlloc(GetProcessHeap(),0,mr->messages, mr->ring_buffer_size * sizeof(RING_MSG));
454         /* Now we need to rearrange the ring buffer so that the new
455            buffers just allocated are in between mr->msg_tosave and
456            mr->msg_toget.
457         */
458         if (mr->msg_tosave < mr->msg_toget)
459         {
460             memmove(&(mr->messages[mr->msg_toget + ESD_RING_BUFFER_INCREMENT]),
461                     &(mr->messages[mr->msg_toget]),
462                     sizeof(RING_MSG)*(old_ring_buffer_size - mr->msg_toget)
463                     );
464             mr->msg_toget += ESD_RING_BUFFER_INCREMENT;
465         }
466     }
467     if (wait)
468     {
469         hEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
470         if (hEvent == INVALID_HANDLE_VALUE)
471         {
472             ERR("can't create event !?\n");
473             LeaveCriticalSection(&mr->msg_crst);
474             return 0;
475         }
476         if (mr->msg_toget != mr->msg_tosave && mr->messages[mr->msg_toget].msg != WINE_WM_HEADER)
477             FIXME("two fast messages in the queue!!!!\n");
478
479         /* fast messages have to be added at the start of the queue */
480         mr->msg_toget = (mr->msg_toget + mr->ring_buffer_size - 1) % mr->ring_buffer_size;
481
482         mr->messages[mr->msg_toget].msg = msg;
483         mr->messages[mr->msg_toget].param = param;
484         mr->messages[mr->msg_toget].hEvent = hEvent;
485     }
486     else
487     {
488         mr->messages[mr->msg_tosave].msg = msg;
489         mr->messages[mr->msg_tosave].param = param;
490         mr->messages[mr->msg_tosave].hEvent = INVALID_HANDLE_VALUE;
491         mr->msg_tosave = (mr->msg_tosave + 1) % mr->ring_buffer_size;
492     }
493
494     LeaveCriticalSection(&mr->msg_crst);
495
496     SetEvent(mr->msg_event);    /* signal a new message */
497
498     if (wait)
499     {
500         /* wait for playback/record thread to have processed the message */
501         WaitForSingleObject(hEvent, INFINITE);
502         CloseHandle(hEvent);
503     }
504
505     return 1;
506 }
507
508 /******************************************************************
509  *              ESD_RetrieveRingMessage
510  *
511  * Get a message from the ring. Should be called by the playback/record thread.
512  */
513 static int ESD_RetrieveRingMessage(ESD_MSG_RING* mr,
514                                    enum win_wm_message *msg, DWORD *param, HANDLE *hEvent)
515 {
516     EnterCriticalSection(&mr->msg_crst);
517
518     if (mr->msg_toget == mr->msg_tosave) /* buffer empty ? */
519     {
520         LeaveCriticalSection(&mr->msg_crst);
521         return 0;
522     }
523
524     *msg = mr->messages[mr->msg_toget].msg;
525     mr->messages[mr->msg_toget].msg = 0;
526     *param = mr->messages[mr->msg_toget].param;
527     *hEvent = mr->messages[mr->msg_toget].hEvent;
528     mr->msg_toget = (mr->msg_toget + 1) % mr->ring_buffer_size;
529     LeaveCriticalSection(&mr->msg_crst);
530     return 1;
531 }
532
533 /*======================================================================*
534  *                  Low level WAVE OUT implementation                   *
535  *======================================================================*/
536
537 /**************************************************************************
538  *                      wodNotifyClient                 [internal]
539  */
540 static DWORD wodNotifyClient(WINE_WAVEOUT* wwo, WORD wMsg, DWORD dwParam1, DWORD dwParam2)
541 {
542     TRACE("wMsg = 0x%04x dwParm1 = %04lX dwParam2 = %04lX\n", wMsg, dwParam1, dwParam2);
543
544     switch (wMsg) {
545     case WOM_OPEN:
546     case WOM_CLOSE:
547     case WOM_DONE:
548         if (wwo->wFlags != DCB_NULL &&
549             !DriverCallback(wwo->waveDesc.dwCallback, wwo->wFlags, (HDRVR)wwo->waveDesc.hWave,
550                             wMsg, wwo->waveDesc.dwInstance, dwParam1, dwParam2)) {
551             WARN("can't notify client !\n");
552             return MMSYSERR_ERROR;
553         }
554         break;
555     default:
556         FIXME("Unknown callback message %u\n", wMsg);
557         return MMSYSERR_INVALPARAM;
558     }
559     return MMSYSERR_NOERROR;
560 }
561
562 /**************************************************************************
563  *                              wodUpdatePlayedTotal    [internal]
564  *
565  */
566 static BOOL wodUpdatePlayedTotal(WINE_WAVEOUT* wwo)
567 {
568     /* total played is the bytes written less the bytes to write ;-) */
569     wwo->dwPlayedTotal = wwo->dwWrittenTotal;
570
571     return TRUE;
572 }
573
574 /**************************************************************************
575  *                              wodPlayer_BeginWaveHdr          [internal]
576  *
577  * Makes the specified lpWaveHdr the currently playing wave header.
578  * If the specified wave header is a begin loop and we're not already in
579  * a loop, setup the loop.
580  */
581 static void wodPlayer_BeginWaveHdr(WINE_WAVEOUT* wwo, LPWAVEHDR lpWaveHdr)
582 {
583     wwo->lpPlayPtr = lpWaveHdr;
584
585     if (!lpWaveHdr) return;
586
587     if (lpWaveHdr->dwFlags & WHDR_BEGINLOOP) {
588         if (wwo->lpLoopPtr) {
589             WARN("Already in a loop. Discarding loop on this header (%p)\n", lpWaveHdr);
590             TRACE("Already in a loop. Discarding loop on this header (%p)\n", lpWaveHdr);
591         } else {
592             TRACE("Starting loop (%ldx) with %p\n", lpWaveHdr->dwLoops, lpWaveHdr);
593             wwo->lpLoopPtr = lpWaveHdr;
594             /* Windows does not touch WAVEHDR.dwLoops,
595              * so we need to make an internal copy */
596             wwo->dwLoops = lpWaveHdr->dwLoops;
597         }
598     }
599     wwo->dwPartialOffset = 0;
600 }
601
602 /**************************************************************************
603  *                              wodPlayer_PlayPtrNext           [internal]
604  *
605  * Advance the play pointer to the next waveheader, looping if required.
606  */
607 static LPWAVEHDR wodPlayer_PlayPtrNext(WINE_WAVEOUT* wwo)
608 {
609     LPWAVEHDR lpWaveHdr = wwo->lpPlayPtr;
610
611     wwo->dwPartialOffset = 0;
612     if ((lpWaveHdr->dwFlags & WHDR_ENDLOOP) && wwo->lpLoopPtr) {
613         /* We're at the end of a loop, loop if required */
614         if (--wwo->dwLoops > 0) {
615             wwo->lpPlayPtr = wwo->lpLoopPtr;
616         } else {
617             /* Handle overlapping loops correctly */
618             if (wwo->lpLoopPtr != lpWaveHdr && (lpWaveHdr->dwFlags & WHDR_BEGINLOOP)) {
619                 FIXME("Correctly handled case ? (ending loop buffer also starts a new loop)\n");
620                 /* shall we consider the END flag for the closing loop or for
621                  * the opening one or for both ???
622                  * code assumes for closing loop only
623                  */
624             } else {
625                 lpWaveHdr = lpWaveHdr->lpNext;
626             }
627             wwo->lpLoopPtr = NULL;
628             wodPlayer_BeginWaveHdr(wwo, lpWaveHdr);
629         }
630     } else {
631         /* We're not in a loop.  Advance to the next wave header */
632         wodPlayer_BeginWaveHdr(wwo, lpWaveHdr = lpWaveHdr->lpNext);
633     }
634
635     return lpWaveHdr;
636 }
637
638 /**************************************************************************
639  *                           wodPlayer_NotifyWait               [internal]
640  * Returns the number of milliseconds to wait before attempting to notify
641  * completion of the specified wavehdr.
642  * This is based on the number of bytes remaining to be written in the
643  * wave.
644  */
645 static DWORD wodPlayer_NotifyWait(const WINE_WAVEOUT* wwo, LPWAVEHDR lpWaveHdr)
646 {
647     DWORD dwMillis;
648
649     if(lpWaveHdr->reserved < wwo->dwPlayedTotal)
650     {
651         dwMillis = 1;
652     }
653     else
654     {
655         dwMillis = (lpWaveHdr->reserved - wwo->dwPlayedTotal) * 1000 / wwo->format.wf.nAvgBytesPerSec;
656         if(!dwMillis) dwMillis = 1;
657     }
658
659     TRACE("dwMillis = %ld\n", dwMillis);
660
661     return dwMillis;
662 }
663
664
665 /**************************************************************************
666  *                           wodPlayer_WriteMaxFrags            [internal]
667  * Writes the maximum number of bytes possible to the DSP and returns
668  * the number of bytes written.
669  */
670 static int wodPlayer_WriteMaxFrags(WINE_WAVEOUT* wwo, DWORD* bytes)
671 {
672     /* Only attempt to write to free bytes */
673     DWORD dwLength = wwo->lpPlayPtr->dwBufferLength - wwo->dwPartialOffset;
674     int toWrite = min(dwLength, *bytes);
675     int written;
676
677     TRACE("Writing wavehdr %p.%lu[%lu]\n",
678           wwo->lpPlayPtr, wwo->dwPartialOffset, wwo->lpPlayPtr->dwBufferLength);
679
680     /* see if our buffer isn't large enough for the data we are writing */
681     if(wwo->buffer_size < toWrite)
682     {
683       if(wwo->sound_buffer)
684       {
685         wwo->sound_buffer = HeapReAlloc(GetProcessHeap(), 0, wwo->sound_buffer, toWrite);
686         wwo->buffer_size = toWrite;
687       }
688     }
689
690     /* if we don't have a buffer then get one */
691     if(!wwo->sound_buffer)
692     {
693       /* allocate some memory for the buffer */
694       wwo->sound_buffer = HeapAlloc(GetProcessHeap(), 0, toWrite);
695       wwo->buffer_size = toWrite;
696     }
697
698     /* if we don't have a buffer then error out */
699     if(!wwo->sound_buffer)
700     {
701       ERR("error allocating sound_buffer memory\n");
702       return 0;
703     }
704
705     TRACE("toWrite == %d\n", toWrite);
706
707     /* apply volume to the bits */
708     /* for single channel audio streams we only use the LEFT volume */
709     if(wwo->format.wBitsPerSample == 16)
710     {
711       /* apply volume to the buffer we are about to send */
712       /* divide toWrite(bytes) by 2 as volume processes by 16 bits */
713       volume_effect16(wwo->lpPlayPtr->lpData + wwo->dwPartialOffset,
714                 wwo->sound_buffer, toWrite>>1, wwo->volume_left,
715                 wwo->volume_right, wwo->format.wf.nChannels);
716     } else if(wwo->format.wBitsPerSample == 8)
717     {
718       /* apply volume to the buffer we are about to send */
719       volume_effect8(wwo->lpPlayPtr->lpData + wwo->dwPartialOffset,
720                 wwo->sound_buffer, toWrite, wwo->volume_left,
721                 wwo->volume_right, wwo->format.wf.nChannels);
722     } else
723     {
724       FIXME("unsupported wwo->format.wBitsPerSample of %d\n",
725         wwo->format.wBitsPerSample);
726     }
727
728     /* send the audio data to esd for playing */
729     written = write(wwo->esd_fd, wwo->sound_buffer, toWrite);
730
731     TRACE("written = %d\n", written);
732
733     if (written <= 0) 
734     {
735       *bytes = 0; /* apparently esd is actually full */
736       return written; /* if we wrote nothing just return */
737     }
738
739     if (written >= dwLength)
740         wodPlayer_PlayPtrNext(wwo);   /* If we wrote all current wavehdr, skip to the next one */
741     else
742         wwo->dwPartialOffset += written;    /* Remove the amount written */
743
744     if (written < toWrite)
745         *bytes = 0;
746     else
747         *bytes -= written;
748
749     wwo->dwWrittenTotal += written; /* update stats on this wave device */
750
751     return written; /* return the number of bytes written */
752 }
753
754
755 /**************************************************************************
756  *                              wodPlayer_NotifyCompletions     [internal]
757  *
758  * Notifies and remove from queue all wavehdrs which have been played to
759  * the speaker (ie. they have cleared the audio device).  If force is true,
760  * we notify all wavehdrs and remove them all from the queue even if they
761  * are unplayed or part of a loop.
762  */
763 static DWORD wodPlayer_NotifyCompletions(WINE_WAVEOUT* wwo, BOOL force)
764 {
765     LPWAVEHDR           lpWaveHdr;
766
767     if (wwo->lpQueuePtr) {
768         TRACE("lpWaveHdr=(%p), lpPlayPtr=(%p), lpLoopPtr=(%p), reserved=(%ld), dwWrittenTotal=(%ld), force=(%d)\n", 
769               wwo->lpQueuePtr,
770               wwo->lpPlayPtr,
771               wwo->lpLoopPtr,
772               wwo->lpQueuePtr->reserved,
773               wwo->dwWrittenTotal,
774               force);
775     } else {
776         TRACE("lpWaveHdr=(%p), lpPlayPtr=(%p), lpLoopPtr=(%p),  dwWrittenTotal=(%ld), force=(%d)\n", 
777               wwo->lpQueuePtr,
778               wwo->lpPlayPtr,
779               wwo->lpLoopPtr,
780               wwo->dwWrittenTotal,
781               force);
782     }
783
784     /* Start from lpQueuePtr and keep notifying until:
785      * - we hit an unwritten wavehdr
786      * - we hit the beginning of a running loop
787      * - we hit a wavehdr which hasn't finished playing
788      */
789     while ((lpWaveHdr = wwo->lpQueuePtr) &&
790            (force ||
791             (lpWaveHdr != wwo->lpPlayPtr &&
792              lpWaveHdr != wwo->lpLoopPtr &&
793              lpWaveHdr->reserved <= wwo->dwWrittenTotal))) {
794
795         wwo->lpQueuePtr = lpWaveHdr->lpNext;
796
797         lpWaveHdr->dwFlags &= ~WHDR_INQUEUE;
798         lpWaveHdr->dwFlags |= WHDR_DONE;
799
800         wodNotifyClient(wwo, WOM_DONE, (DWORD)lpWaveHdr, 0);
801     }
802     return  (lpWaveHdr && lpWaveHdr != wwo->lpPlayPtr && lpWaveHdr != wwo->lpLoopPtr) ?
803         wodPlayer_NotifyWait(wwo, lpWaveHdr) : INFINITE;
804 }
805
806 /**************************************************************************
807  *                              wodPlayer_Reset                 [internal]
808  *
809  * wodPlayer helper. Resets current output stream.
810  */
811 static  void    wodPlayer_Reset(WINE_WAVEOUT* wwo, BOOL reset)
812 {
813     wodUpdatePlayedTotal(wwo);
814
815     wodPlayer_NotifyCompletions(wwo, FALSE); /* updates current notify list */
816
817     /* we aren't able to flush any data that has already been written */
818     /* to esd, otherwise we would do the flushing here */
819
820     if (reset) {
821         enum win_wm_message     msg;
822         DWORD                   param;
823         HANDLE                  ev;
824
825         /* remove any buffer */
826         wodPlayer_NotifyCompletions(wwo, TRUE);
827
828         wwo->lpPlayPtr = wwo->lpQueuePtr = wwo->lpLoopPtr = NULL;
829         wwo->state = WINE_WS_STOPPED;
830         wwo->dwPlayedTotal = wwo->dwWrittenTotal = 0;
831
832         wwo->dwPartialOffset = 0;        /* Clear partial wavehdr */
833
834         /* remove any existing message in the ring */
835         EnterCriticalSection(&wwo->msgRing.msg_crst);
836
837         /* return all pending headers in queue */
838         while (ESD_RetrieveRingMessage(&wwo->msgRing, &msg, &param, &ev))
839         {
840             TRACE("flushing msg\n");
841             if (msg != WINE_WM_HEADER)
842             {
843                 FIXME("shouldn't have headers left\n");
844                 SetEvent(ev);
845                 continue;
846             }
847             ((LPWAVEHDR)param)->dwFlags &= ~WHDR_INQUEUE;
848             ((LPWAVEHDR)param)->dwFlags |= WHDR_DONE;
849
850             wodNotifyClient(wwo, WOM_DONE, param, 0);
851         }
852         ResetEvent(wwo->msgRing.msg_event);
853         LeaveCriticalSection(&wwo->msgRing.msg_crst);
854     } else {
855         if (wwo->lpLoopPtr) {
856             /* complicated case, not handled yet (could imply modifying the loop counter */
857             FIXME("Pausing while in loop isn't correctly handled yet, except strange results\n");
858             wwo->lpPlayPtr = wwo->lpLoopPtr;
859             wwo->dwPartialOffset = 0;
860             wwo->dwWrittenTotal = wwo->dwPlayedTotal; /* this is wrong !!! */
861         } else {
862             /* the data already written is going to be played, so take */
863             /* this fact into account here */
864             wwo->dwPlayedTotal = wwo->dwWrittenTotal;
865         }
866         wwo->state = WINE_WS_PAUSED;
867     }
868 }
869
870 /**************************************************************************
871  *                    wodPlayer_ProcessMessages                 [internal]
872  */
873 static void wodPlayer_ProcessMessages(WINE_WAVEOUT* wwo)
874 {
875     LPWAVEHDR           lpWaveHdr;
876     enum win_wm_message msg;
877     DWORD               param;
878     HANDLE              ev;
879
880     while (ESD_RetrieveRingMessage(&wwo->msgRing, &msg, &param, &ev)) {
881         TRACE("Received %s %lx\n", wodPlayerCmdString[msg - WM_USER - 1], param);
882         switch (msg) {
883         case WINE_WM_PAUSING:
884             wodPlayer_Reset(wwo, FALSE);
885             SetEvent(ev);
886             break;
887         case WINE_WM_RESTARTING:
888             wwo->state = WINE_WS_PLAYING;
889             SetEvent(ev);
890             break;
891         case WINE_WM_HEADER:
892             lpWaveHdr = (LPWAVEHDR)param;
893
894             /* insert buffer at the end of queue */
895             {
896                 LPWAVEHDR*      wh;
897                 for (wh = &(wwo->lpQueuePtr); *wh; wh = &((*wh)->lpNext));
898                 *wh = lpWaveHdr;
899             }
900             if (!wwo->lpPlayPtr)
901                 wodPlayer_BeginWaveHdr(wwo,lpWaveHdr);
902             if (wwo->state == WINE_WS_STOPPED)
903                 wwo->state = WINE_WS_PLAYING;
904             break;
905         case WINE_WM_RESETTING:
906             wodPlayer_Reset(wwo, TRUE);
907             SetEvent(ev);
908             break;
909         case WINE_WM_UPDATE:
910             wodUpdatePlayedTotal(wwo);
911             SetEvent(ev);
912             break;
913         case WINE_WM_BREAKLOOP:
914             if (wwo->state == WINE_WS_PLAYING && wwo->lpLoopPtr != NULL) {
915                 /* ensure exit at end of current loop */
916                 wwo->dwLoops = 1;
917             }
918             SetEvent(ev);
919             break;
920         case WINE_WM_CLOSING:
921             /* sanity check: this should not happen since the device must have been reset before */
922             if (wwo->lpQueuePtr || wwo->lpPlayPtr) ERR("out of sync\n");
923             wwo->hThread = 0;
924             wwo->state = WINE_WS_CLOSED;
925             SetEvent(ev);
926             ExitThread(0);
927             /* shouldn't go here */
928         default:
929             FIXME("unknown message %d\n", msg);
930             break;
931         }
932     }
933 }
934
935 /**************************************************************************
936  *                           wodPlayer_FeedDSP                  [internal]
937  * Feed as much sound data as we can into the DSP and return the number of
938  * milliseconds before it will be necessary to feed the DSP again.
939  */
940 static DWORD wodPlayer_FeedDSP(WINE_WAVEOUT* wwo)
941 {
942     DWORD       availInQ;
943
944     wodUpdatePlayedTotal(wwo);
945     /* better way to set availInQ? */
946     availInQ = ESD_BUF_SIZE;
947     TRACE("availInQ = %ld\n", availInQ);
948
949     /* input queue empty */
950     if (!wwo->lpPlayPtr) {
951         TRACE("Run out of wavehdr:s... flushing\n");
952         return INFINITE;
953     }
954
955 #if 0
956     /* no more room... no need to try to feed */
957     if(!availInQ)
958     {
959         TRACE("no more room, no need to try to feed\n");
960         return wwo->dwSleepTime;
961     }
962 #endif
963
964     /* Feed from partial wavehdr */
965     if (wwo->lpPlayPtr && wwo->dwPartialOffset != 0)
966     {
967         TRACE("feeding from partial wavehdr\n");
968         wodPlayer_WriteMaxFrags(wwo, &availInQ);
969     }
970
971     /* Feed wavehdrs until we run out of wavehdrs or DSP space */
972     if (!wwo->dwPartialOffset)
973     {
974         while(wwo->lpPlayPtr && availInQ)
975         {
976             TRACE("feeding waveheaders until we run out of space\n");
977             /* note the value that dwPlayedTotal will return when this wave finishes playing */
978             wwo->lpPlayPtr->reserved = wwo->dwWrittenTotal + wwo->lpPlayPtr->dwBufferLength;
979             TRACE("reserved=(%ld) dwWrittenTotal=(%ld) dwBufferLength=(%ld)\n",
980                   wwo->lpPlayPtr->reserved,
981                   wwo->dwWrittenTotal,
982                   wwo->lpPlayPtr->dwBufferLength
983                 );
984             wodPlayer_WriteMaxFrags(wwo, &availInQ);
985         }
986     }
987
988     if (!wwo->lpPlayPtr) {
989         TRACE("Ran out of wavehdrs\n");
990         return INFINITE;
991     }
992
993     return wwo->dwSleepTime;
994 }
995
996
997 /**************************************************************************
998  *                              wodPlayer                       [internal]
999  */
1000 static  DWORD   CALLBACK        wodPlayer(LPVOID pmt)
1001 {
1002     WORD          uDevID = (DWORD)pmt;
1003     WINE_WAVEOUT* wwo = (WINE_WAVEOUT*)&WOutDev[uDevID];
1004     DWORD         dwNextFeedTime = INFINITE;   /* Time before DSP needs feeding */
1005     DWORD         dwNextNotifyTime = INFINITE; /* Time before next wave completion */
1006     DWORD         dwSleepTime;
1007
1008     wwo->state = WINE_WS_STOPPED;
1009     SetEvent(wwo->hStartUpEvent);
1010
1011     for (;;) {
1012         /** Wait for the shortest time before an action is required.  If there
1013          *  are no pending actions, wait forever for a command.
1014          */
1015         dwSleepTime = min(dwNextFeedTime, dwNextNotifyTime);
1016         TRACE("waiting %lums (%lu,%lu)\n", dwSleepTime, dwNextFeedTime, dwNextNotifyTime);
1017         WaitForSingleObject(wwo->msgRing.msg_event, dwSleepTime);
1018         wodPlayer_ProcessMessages(wwo);
1019         if (wwo->state == WINE_WS_PLAYING) {
1020             dwNextFeedTime = wodPlayer_FeedDSP(wwo);
1021             dwNextNotifyTime = wodPlayer_NotifyCompletions(wwo, FALSE);
1022         } else {
1023             dwNextFeedTime = dwNextNotifyTime = INFINITE;
1024         }
1025     }
1026 }
1027
1028 /**************************************************************************
1029  *                      wodGetDevCaps                           [internal]
1030  */
1031 static DWORD wodGetDevCaps(WORD wDevID, LPWAVEOUTCAPSW lpCaps, DWORD dwSize)
1032 {
1033     TRACE("(%u, %p, %lu);\n", wDevID, lpCaps, dwSize);
1034
1035     if (lpCaps == NULL) return MMSYSERR_NOTENABLED;
1036
1037     if (wDevID >= MAX_WAVEOUTDRV) {
1038         TRACE("MAX_WAVOUTDRV reached !\n");
1039         return MMSYSERR_BADDEVICEID;
1040     }
1041
1042     memcpy(lpCaps, &WOutDev[wDevID].caps, min(dwSize, sizeof(*lpCaps)));
1043     return MMSYSERR_NOERROR;
1044 }
1045
1046 /**************************************************************************
1047  *                              wodOpen                         [internal]
1048  */
1049 static DWORD wodOpen(WORD wDevID, LPWAVEOPENDESC lpDesc, DWORD dwFlags)
1050 {
1051     WINE_WAVEOUT*       wwo;
1052     /* output to esound... */
1053     int                 out_bits = ESD_BITS8, out_channels = ESD_MONO, out_rate;
1054     int                 out_mode = ESD_STREAM, out_func = ESD_PLAY;
1055     esd_format_t        out_format;
1056
1057     TRACE("(%u, %p, %08lX);\n", wDevID, lpDesc, dwFlags);
1058     if (lpDesc == NULL) {
1059         WARN("Invalid Parameter !\n");
1060         return MMSYSERR_INVALPARAM;
1061     }
1062     if (wDevID >= MAX_WAVEOUTDRV) {
1063         TRACE("MAX_WAVOUTDRV reached !\n");
1064         return MMSYSERR_BADDEVICEID;
1065     }
1066
1067     /* if this device is already open tell the app that it is allocated */
1068     if(WOutDev[wDevID].esd_fd != -1)
1069     {
1070       TRACE("device already allocated\n");
1071       return MMSYSERR_ALLOCATED;
1072     }
1073
1074     /* only PCM format is supported so far... */
1075     if (lpDesc->lpFormat->wFormatTag != WAVE_FORMAT_PCM ||
1076         lpDesc->lpFormat->nChannels == 0 ||
1077         lpDesc->lpFormat->nSamplesPerSec < DSBFREQUENCY_MIN ||
1078         lpDesc->lpFormat->nSamplesPerSec > DSBFREQUENCY_MAX ||
1079         (lpDesc->lpFormat->wBitsPerSample!=8 && lpDesc->lpFormat->wBitsPerSample!=16)) {
1080         WARN("Bad format: tag=%04X nChannels=%d nSamplesPerSec=%ld !\n",
1081              lpDesc->lpFormat->wFormatTag, lpDesc->lpFormat->nChannels,
1082              lpDesc->lpFormat->nSamplesPerSec);
1083         return WAVERR_BADFORMAT;
1084     }
1085
1086     if (dwFlags & WAVE_FORMAT_QUERY) {
1087         TRACE("Query format: tag=%04X nChannels=%d nSamplesPerSec=%ld !\n",
1088              lpDesc->lpFormat->wFormatTag, lpDesc->lpFormat->nChannels,
1089              lpDesc->lpFormat->nSamplesPerSec);
1090         return MMSYSERR_NOERROR;
1091     }
1092
1093     wwo = &WOutDev[wDevID];
1094
1095     /* direct sound not supported, ignore the flag */
1096     dwFlags &= ~WAVE_DIRECTSOUND;
1097
1098     wwo->wFlags = HIWORD(dwFlags & CALLBACK_TYPEMASK);
1099
1100     memcpy(&wwo->waveDesc, lpDesc,           sizeof(WAVEOPENDESC));
1101     memcpy(&wwo->format,   lpDesc->lpFormat, sizeof(PCMWAVEFORMAT));
1102
1103     if (wwo->format.wBitsPerSample == 0) {
1104         WARN("Resetting zeroed wBitsPerSample\n");
1105         wwo->format.wBitsPerSample = 8 *
1106             (wwo->format.wf.nAvgBytesPerSec /
1107              wwo->format.wf.nSamplesPerSec) /
1108             wwo->format.wf.nChannels;
1109     }
1110
1111     if (wwo->format.wBitsPerSample == 8)
1112         out_bits = ESD_BITS8;
1113     else if (wwo->format.wBitsPerSample == 16)
1114         out_bits = ESD_BITS16;
1115
1116     wwo->bytes_per_frame = (wwo->format.wBitsPerSample * wwo->format.wf.nChannels) / 8;
1117
1118     if (wwo->format.wf.nChannels == 1)
1119         out_channels = ESD_MONO;
1120     else if (wwo->format.wf.nChannels == 2)
1121         out_channels = ESD_STEREO;
1122
1123     out_format = out_bits | out_channels | out_mode | out_func;
1124     out_rate = (int) wwo->format.wf.nSamplesPerSec;
1125         TRACE("esd output format = 0x%08x, rate = %d\n", out_format, out_rate);
1126
1127     wwo->esd_fd = esd_play_stream(out_format, out_rate, esd_host, "wineesd");
1128
1129     /* clear these so we don't have any confusion ;-) */
1130     wwo->sound_buffer = 0;
1131     wwo->buffer_size = 0;
1132
1133     if(wwo->esd_fd < 0) return MMSYSERR_ALLOCATED;
1134
1135     wwo->dwBufferSize = ESD_BUF_SIZE;
1136     TRACE("Buffer size is now (%ld)\n",wwo->dwBufferSize);
1137
1138     wwo->dwPlayedTotal = 0;
1139     wwo->dwWrittenTotal = 0;
1140
1141     wwo->dwSleepTime = (1024 * 1000 * BUFFER_REFILL_THRESHOLD) / wwo->format.wf.nAvgBytesPerSec;
1142
1143     /* Initialize volume to full level */
1144     wwo->volume_left = 100;
1145     wwo->volume_right = 100;
1146
1147     ESD_InitRingMessage(&wwo->msgRing);
1148
1149     /* create player thread */
1150     if (!(dwFlags & WAVE_DIRECTSOUND)) {
1151         wwo->hStartUpEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
1152         wwo->hThread = CreateThread(NULL, 0, wodPlayer, (LPVOID)(DWORD)wDevID, 0, &(wwo->dwThreadID));
1153         WaitForSingleObject(wwo->hStartUpEvent, INFINITE);
1154         CloseHandle(wwo->hStartUpEvent);
1155     } else {
1156         wwo->hThread = INVALID_HANDLE_VALUE;
1157         wwo->dwThreadID = 0;
1158     }
1159     wwo->hStartUpEvent = INVALID_HANDLE_VALUE;
1160
1161     TRACE("esd=0x%lx, dwBufferSize=%ld\n",
1162           (long)wwo->esd_fd, wwo->dwBufferSize);
1163
1164     TRACE("wBitsPerSample=%u, nAvgBytesPerSec=%lu, nSamplesPerSec=%lu, nChannels=%u nBlockAlign=%u!\n",
1165           wwo->format.wBitsPerSample, wwo->format.wf.nAvgBytesPerSec,
1166           wwo->format.wf.nSamplesPerSec, wwo->format.wf.nChannels,
1167           wwo->format.wf.nBlockAlign);
1168
1169     return wodNotifyClient(wwo, WOM_OPEN, 0L, 0L);
1170 }
1171
1172 /**************************************************************************
1173  *                              wodClose                        [internal]
1174  */
1175 static DWORD wodClose(WORD wDevID)
1176 {
1177     DWORD               ret = MMSYSERR_NOERROR;
1178     WINE_WAVEOUT*       wwo;
1179
1180     TRACE("(%u);\n", wDevID);
1181
1182     if (wDevID >= MAX_WAVEOUTDRV || WOutDev[wDevID].esd_fd == -1) {
1183         WARN("bad device ID !\n");
1184         return MMSYSERR_BADDEVICEID;
1185     }
1186
1187     wwo = &WOutDev[wDevID];
1188     if (wwo->lpQueuePtr) {
1189         WARN("buffers still playing !\n");
1190         ret = WAVERR_STILLPLAYING;
1191     } else {
1192         TRACE("imhere[3-close]\n");
1193         if (wwo->hThread != INVALID_HANDLE_VALUE) {
1194             ESD_AddRingMessage(&wwo->msgRing, WINE_WM_CLOSING, 0, TRUE);
1195         }
1196
1197         ESD_DestroyRingMessage(&wwo->msgRing);
1198
1199         ESD_CloseWaveOutDevice(wwo);    /* close the stream and clean things up */
1200
1201         ret = wodNotifyClient(wwo, WOM_CLOSE, 0L, 0L);
1202     }
1203     return ret;
1204 }
1205
1206 /**************************************************************************
1207  *                              wodWrite                        [internal]
1208  *
1209  */
1210 static DWORD wodWrite(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
1211 {
1212     TRACE("(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
1213
1214     /* first, do the sanity checks... */
1215     if (wDevID >= MAX_WAVEOUTDRV || WOutDev[wDevID].esd_fd == -1) {
1216         WARN("bad dev ID !\n");
1217         return MMSYSERR_BADDEVICEID;
1218     }
1219
1220     if (lpWaveHdr->lpData == NULL || !(lpWaveHdr->dwFlags & WHDR_PREPARED))
1221     {
1222         TRACE("unprepared\n");
1223         return WAVERR_UNPREPARED;
1224     }
1225
1226     if (lpWaveHdr->dwFlags & WHDR_INQUEUE)
1227     {
1228         TRACE("still playing\n");
1229         return WAVERR_STILLPLAYING;
1230     }
1231
1232     lpWaveHdr->dwFlags &= ~WHDR_DONE;
1233     lpWaveHdr->dwFlags |= WHDR_INQUEUE;
1234     lpWaveHdr->lpNext = 0;
1235
1236     TRACE("adding ring message\n");
1237     ESD_AddRingMessage(&WOutDev[wDevID].msgRing, WINE_WM_HEADER, (DWORD)lpWaveHdr, FALSE);
1238
1239     return MMSYSERR_NOERROR;
1240 }
1241
1242 /**************************************************************************
1243  *                              wodPrepare                      [internal]
1244  */
1245 static DWORD wodPrepare(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
1246 {
1247     TRACE("(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
1248
1249     if (wDevID >= MAX_WAVEOUTDRV) {
1250         WARN("bad device ID !\n");
1251         return MMSYSERR_BADDEVICEID;
1252     }
1253
1254     if (lpWaveHdr->dwFlags & WHDR_INQUEUE)
1255         return WAVERR_STILLPLAYING;
1256
1257     lpWaveHdr->dwFlags |= WHDR_PREPARED;
1258     lpWaveHdr->dwFlags &= ~WHDR_DONE;
1259     return MMSYSERR_NOERROR;
1260 }
1261
1262 /**************************************************************************
1263  *                              wodUnprepare                    [internal]
1264  */
1265 static DWORD wodUnprepare(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
1266 {
1267     TRACE("(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
1268
1269     if (wDevID >= MAX_WAVEOUTDRV) {
1270         WARN("bad device ID !\n");
1271         return MMSYSERR_BADDEVICEID;
1272     }
1273
1274     if (lpWaveHdr->dwFlags & WHDR_INQUEUE)
1275         return WAVERR_STILLPLAYING;
1276
1277     lpWaveHdr->dwFlags &= ~WHDR_PREPARED;
1278     lpWaveHdr->dwFlags |= WHDR_DONE;
1279
1280     return MMSYSERR_NOERROR;
1281 }
1282
1283 /**************************************************************************
1284  *                      wodPause                                [internal]
1285  */
1286 static DWORD wodPause(WORD wDevID)
1287 {
1288     TRACE("(%u);!\n", wDevID);
1289
1290     if (wDevID >= MAX_WAVEOUTDRV || WOutDev[wDevID].esd_fd == -1) {
1291         WARN("bad device ID !\n");
1292         return MMSYSERR_BADDEVICEID;
1293     }
1294
1295     TRACE("imhere[3-PAUSING]\n");
1296     ESD_AddRingMessage(&WOutDev[wDevID].msgRing, WINE_WM_PAUSING, 0, TRUE);
1297
1298     return MMSYSERR_NOERROR;
1299 }
1300
1301 /**************************************************************************
1302  *                      wodRestart                              [internal]
1303  */
1304 static DWORD wodRestart(WORD wDevID)
1305 {
1306     TRACE("(%u);\n", wDevID);
1307
1308     if (wDevID >= MAX_WAVEOUTDRV || WOutDev[wDevID].esd_fd == -1) {
1309         WARN("bad device ID !\n");
1310         return MMSYSERR_BADDEVICEID;
1311     }
1312
1313     if (WOutDev[wDevID].state == WINE_WS_PAUSED) {
1314         TRACE("imhere[3-RESTARTING]\n");
1315         ESD_AddRingMessage(&WOutDev[wDevID].msgRing, WINE_WM_RESTARTING, 0, TRUE);
1316     }
1317
1318     /* FIXME: is NotifyClient with WOM_DONE right ? (Comet Busters 1.3.3 needs this notification) */
1319     /* FIXME: Myst crashes with this ... hmm -MM
1320        return wodNotifyClient(wwo, WOM_DONE, 0L, 0L);
1321     */
1322
1323     return MMSYSERR_NOERROR;
1324 }
1325
1326 /**************************************************************************
1327  *                      wodReset                                [internal]
1328  */
1329 static DWORD wodReset(WORD wDevID)
1330 {
1331     TRACE("(%u);\n", wDevID);
1332
1333     if (wDevID >= MAX_WAVEOUTDRV || WOutDev[wDevID].esd_fd == -1) {
1334         WARN("bad device ID !\n");
1335         return MMSYSERR_BADDEVICEID;
1336     }
1337
1338     TRACE("imhere[3-RESET]\n");
1339     ESD_AddRingMessage(&WOutDev[wDevID].msgRing, WINE_WM_RESETTING, 0, TRUE);
1340
1341     return MMSYSERR_NOERROR;
1342 }
1343
1344 /**************************************************************************
1345  *                              wodGetPosition                  [internal]
1346  */
1347 static DWORD wodGetPosition(WORD wDevID, LPMMTIME lpTime, DWORD uSize)
1348 {
1349     double              time;
1350     DWORD               val;
1351     WINE_WAVEOUT*       wwo;
1352
1353     TRACE("(%u, %p, %lu);\n", wDevID, lpTime, uSize);
1354
1355     if (wDevID >= MAX_WAVEOUTDRV || WOutDev[wDevID].esd_fd == -1) {
1356         WARN("bad device ID !\n");
1357         return MMSYSERR_BADDEVICEID;
1358     }
1359
1360     if (lpTime == NULL) return MMSYSERR_INVALPARAM;
1361
1362     wwo = &WOutDev[wDevID];
1363     ESD_AddRingMessage(&wwo->msgRing, WINE_WM_UPDATE, 0, TRUE);
1364     val = wwo->dwPlayedTotal;
1365
1366     TRACE("wType=%04X wBitsPerSample=%u nSamplesPerSec=%lu nChannels=%u nAvgBytesPerSec=%lu\n",
1367           lpTime->wType, wwo->format.wBitsPerSample,
1368           wwo->format.wf.nSamplesPerSec, wwo->format.wf.nChannels,
1369           wwo->format.wf.nAvgBytesPerSec);
1370     TRACE("dwPlayedTotal=%lu\n", val);
1371
1372     switch (lpTime->wType) {
1373     case TIME_BYTES:
1374         lpTime->u.cb = val;
1375         TRACE("TIME_BYTES=%lu\n", lpTime->u.cb);
1376         break;
1377     case TIME_SAMPLES:
1378         lpTime->u.sample = val * 8 / wwo->format.wBitsPerSample /wwo->format.wf.nChannels;
1379         TRACE("TIME_SAMPLES=%lu\n", lpTime->u.sample);
1380         break;
1381     case TIME_SMPTE:
1382         time = (double)val / (double)wwo->format.wf.nAvgBytesPerSec;
1383         lpTime->u.smpte.hour = time / (60 * 60);
1384         time -= lpTime->u.smpte.hour * (60 * 60);
1385         lpTime->u.smpte.min = time / 60;
1386         time -= lpTime->u.smpte.min * 60;
1387         lpTime->u.smpte.sec = time;
1388         time -= lpTime->u.smpte.sec;
1389         lpTime->u.smpte.frame = ceil(time * 30);
1390         lpTime->u.smpte.fps = 30;
1391         TRACE("TIME_SMPTE=%02u:%02u:%02u:%02u\n",
1392               lpTime->u.smpte.hour, lpTime->u.smpte.min,
1393               lpTime->u.smpte.sec, lpTime->u.smpte.frame);
1394         break;
1395     default:
1396         FIXME("Format %d not supported ! use TIME_MS !\n", lpTime->wType);
1397         lpTime->wType = TIME_MS;
1398     case TIME_MS:
1399         lpTime->u.ms = val * 1000.0 / wwo->format.wf.nAvgBytesPerSec;
1400         TRACE("TIME_MS=%lu\n", lpTime->u.ms);
1401         break;
1402     }
1403     return MMSYSERR_NOERROR;
1404 }
1405
1406 /**************************************************************************
1407  *                              wodBreakLoop                    [internal]
1408  */
1409 static DWORD wodBreakLoop(WORD wDevID)
1410 {
1411     TRACE("(%u);\n", wDevID);
1412
1413     if (wDevID >= MAX_WAVEOUTDRV || WOutDev[wDevID].esd_fd == -1) {
1414         WARN("bad device ID !\n");
1415         return MMSYSERR_BADDEVICEID;
1416     }
1417     ESD_AddRingMessage(&WOutDev[wDevID].msgRing, WINE_WM_BREAKLOOP, 0, TRUE);
1418     return MMSYSERR_NOERROR;
1419 }
1420
1421 /**************************************************************************
1422  *                              wodGetVolume                    [internal]
1423  */
1424 static DWORD wodGetVolume(WORD wDevID, LPDWORD lpdwVol)
1425 {
1426     DWORD left, right;
1427
1428     left = WOutDev[wDevID].volume_left;
1429     right = WOutDev[wDevID].volume_right;
1430
1431     TRACE("(%u, %p);\n", wDevID, lpdwVol);
1432
1433     *lpdwVol = ((left * 0xFFFFl) / 100) + (((right * 0xFFFFl) / 100) <<
1434                 16);
1435
1436     return MMSYSERR_NOERROR;
1437 }
1438
1439 /**************************************************************************
1440  *                              wodSetVolume                    [internal]
1441  */
1442 static DWORD wodSetVolume(WORD wDevID, DWORD dwParam)
1443 {
1444     DWORD left, right;
1445
1446     left  = (LOWORD(dwParam) * 100) / 0xFFFFl;
1447     right = (HIWORD(dwParam) * 100) / 0xFFFFl;
1448
1449     TRACE("(%u, %08lX);\n", wDevID, dwParam);
1450
1451     WOutDev[wDevID].volume_left = left;
1452     WOutDev[wDevID].volume_right = right;
1453
1454     return MMSYSERR_NOERROR;
1455 }
1456
1457 /**************************************************************************
1458  *                              wodGetNumDevs                   [internal]
1459  */
1460 static  DWORD   wodGetNumDevs(void)
1461 {
1462     return MAX_WAVEOUTDRV;
1463 }
1464
1465 /**************************************************************************
1466  *                              wodDevInterfaceSize             [internal]
1467  */
1468 static DWORD wodDevInterfaceSize(UINT wDevID, LPDWORD dwParam1)
1469 {
1470     TRACE("(%u, %p)\n", wDevID, dwParam1);
1471  
1472     *dwParam1 = MultiByteToWideChar(CP_ACP, 0, WOutDev[wDevID].interface_name, -1,
1473                                     NULL, 0 ) * sizeof(WCHAR);
1474     return MMSYSERR_NOERROR;
1475 }
1476  
1477 /**************************************************************************
1478  *                              wodDevInterface                 [internal]
1479  */
1480 static DWORD wodDevInterface(UINT wDevID, PWCHAR dwParam1, DWORD dwParam2)
1481 {
1482     if (dwParam2 >= MultiByteToWideChar(CP_ACP, 0, WOutDev[wDevID].interface_name, -1,
1483                                         NULL, 0 ) * sizeof(WCHAR))
1484     {
1485         MultiByteToWideChar(CP_ACP, 0, WOutDev[wDevID].interface_name, -1,
1486                             dwParam1, dwParam2 / sizeof(WCHAR));
1487         return MMSYSERR_NOERROR;
1488     }
1489     return MMSYSERR_INVALPARAM;
1490 }
1491  
1492 /**************************************************************************
1493  *                              wodMessage (WINEESD.@)
1494  */
1495 DWORD WINAPI ESD_wodMessage(UINT wDevID, UINT wMsg, DWORD dwUser,
1496                             DWORD dwParam1, DWORD dwParam2)
1497 {
1498     TRACE("(%u, %04X, %08lX, %08lX, %08lX);\n",
1499           wDevID, wMsg, dwUser, dwParam1, dwParam2);
1500
1501     switch (wMsg) {
1502     case DRVM_INIT:
1503     case DRVM_EXIT:
1504     case DRVM_ENABLE:
1505     case DRVM_DISABLE:
1506         /* FIXME: Pretend this is supported */
1507         return 0;
1508     case WODM_OPEN:             return wodOpen          (wDevID, (LPWAVEOPENDESC)dwParam1,      dwParam2);
1509     case WODM_CLOSE:            return wodClose         (wDevID);
1510     case WODM_WRITE:            return wodWrite         (wDevID, (LPWAVEHDR)dwParam1,           dwParam2);
1511     case WODM_PAUSE:            return wodPause         (wDevID);
1512     case WODM_GETPOS:           return wodGetPosition   (wDevID, (LPMMTIME)dwParam1,            dwParam2);
1513     case WODM_BREAKLOOP:        return wodBreakLoop     (wDevID);
1514     case WODM_PREPARE:          return wodPrepare       (wDevID, (LPWAVEHDR)dwParam1,           dwParam2);
1515     case WODM_UNPREPARE:        return wodUnprepare     (wDevID, (LPWAVEHDR)dwParam1,           dwParam2);
1516     case WODM_GETDEVCAPS:       return wodGetDevCaps    (wDevID, (LPWAVEOUTCAPSW)dwParam1,      dwParam2);
1517     case WODM_GETNUMDEVS:       return wodGetNumDevs    ();
1518     case WODM_GETPITCH:         return MMSYSERR_NOTSUPPORTED;
1519     case WODM_SETPITCH:         return MMSYSERR_NOTSUPPORTED;
1520     case WODM_GETPLAYBACKRATE:  return MMSYSERR_NOTSUPPORTED;
1521     case WODM_SETPLAYBACKRATE:  return MMSYSERR_NOTSUPPORTED;
1522     case WODM_GETVOLUME:        return wodGetVolume     (wDevID, (LPDWORD)dwParam1);
1523     case WODM_SETVOLUME:        return wodSetVolume     (wDevID, dwParam1);
1524     case WODM_RESTART:          return wodRestart       (wDevID);
1525     case WODM_RESET:            return wodReset         (wDevID);
1526
1527     case DRV_QUERYDEVICEINTERFACESIZE: return wodDevInterfaceSize       (wDevID, (LPDWORD)dwParam1);
1528     case DRV_QUERYDEVICEINTERFACE:     return wodDevInterface           (wDevID, (PWCHAR)dwParam1, dwParam2);
1529     case DRV_QUERYDSOUNDIFACE:  return wodDsCreate      (wDevID, (PIDSDRIVER*)dwParam1);
1530     case DRV_QUERYDSOUNDDESC:   return wodDsDesc        (wDevID, (PDSDRIVERDESC)dwParam1);
1531     default:
1532         FIXME("unknown message %d!\n", wMsg);
1533     }
1534     return MMSYSERR_NOTSUPPORTED;
1535 }
1536
1537 /*======================================================================*
1538  *                  Low level WAVE IN implementation                    *
1539  *======================================================================*/
1540
1541 /**************************************************************************
1542  *                              widGetNumDevs                   [internal]
1543  */
1544 static  DWORD   widGetNumDevs(void)
1545 {
1546     TRACE("%d \n",MAX_WAVEINDRV);
1547     return MAX_WAVEINDRV;
1548 }
1549
1550 /**************************************************************************
1551  *                              widDevInterfaceSize             [internal]
1552  */
1553 static DWORD widDevInterfaceSize(UINT wDevID, LPDWORD dwParam1)
1554 {
1555     TRACE("(%u, %p)\n", wDevID, dwParam1);
1556  
1557  
1558     *dwParam1 = MultiByteToWideChar(CP_ACP, 0, WInDev[wDevID].interface_name, -1,
1559                                     NULL, 0 ) * sizeof(WCHAR);
1560     return MMSYSERR_NOERROR;
1561 }
1562
1563 /**************************************************************************
1564  *                              widDevInterface                 [internal]
1565  */
1566 static DWORD widDevInterface(UINT wDevID, PWCHAR dwParam1, DWORD dwParam2)
1567 {
1568     if (dwParam2 >= MultiByteToWideChar(CP_ACP, 0, WInDev[wDevID].interface_name, -1,
1569                                         NULL, 0 ) * sizeof(WCHAR))
1570     {
1571         MultiByteToWideChar(CP_ACP, 0, WInDev[wDevID].interface_name, -1,
1572                             dwParam1, dwParam2 / sizeof(WCHAR));
1573         return MMSYSERR_NOERROR;
1574     }
1575     return MMSYSERR_INVALPARAM;
1576 }
1577
1578 /**************************************************************************
1579  *                      widNotifyClient                 [internal]
1580  */
1581 static DWORD widNotifyClient(WINE_WAVEIN* wwi, WORD wMsg, DWORD dwParam1, DWORD dwParam2)
1582 {
1583     TRACE("wMsg = 0x%04x dwParm1 = %04lX dwParam2 = %04lX\n", wMsg, dwParam1, dwParam2);
1584
1585     switch (wMsg) {
1586     case WIM_OPEN:
1587     case WIM_CLOSE:
1588     case WIM_DATA:
1589         if (wwi->wFlags != DCB_NULL &&
1590             !DriverCallback(wwi->waveDesc.dwCallback, wwi->wFlags,
1591                             (HDRVR)wwi->waveDesc.hWave, wMsg,
1592                             wwi->waveDesc.dwInstance, dwParam1, dwParam2)) {
1593             WARN("can't notify client !\n");
1594             return MMSYSERR_ERROR;
1595         }
1596         break;
1597     default:
1598         FIXME("Unknown callback message %u\n", wMsg);
1599         return MMSYSERR_INVALPARAM;
1600     }
1601     return MMSYSERR_NOERROR;
1602 }
1603
1604 /**************************************************************************
1605  *                      widGetDevCaps                           [internal]
1606  */
1607 static DWORD widGetDevCaps(WORD wDevID, LPWAVEINCAPSW lpCaps, DWORD dwSize)
1608 {
1609     TRACE("(%u, %p, %lu);\n", wDevID, lpCaps, dwSize);
1610
1611     if (lpCaps == NULL) return MMSYSERR_NOTENABLED;
1612
1613     if (wDevID >= MAX_WAVEINDRV) {
1614         TRACE("MAX_WAVINDRV reached !\n");
1615         return MMSYSERR_BADDEVICEID;
1616     }
1617
1618     memcpy(lpCaps, &WInDev[wDevID].caps, min(dwSize, sizeof(*lpCaps)));
1619     return MMSYSERR_NOERROR;
1620 }
1621
1622 /**************************************************************************
1623  *                              widRecorder                     [internal]
1624  */
1625 static  DWORD   CALLBACK        widRecorder(LPVOID pmt)
1626 {
1627     WORD                uDevID = (DWORD)pmt;
1628     WINE_WAVEIN*        wwi = (WINE_WAVEIN*)&WInDev[uDevID];
1629     WAVEHDR*            lpWaveHdr;
1630     DWORD               dwSleepTime;
1631     DWORD               bytesRead;
1632     enum win_wm_message msg;
1633     DWORD               param;
1634     HANDLE              ev;
1635
1636     SetEvent(wwi->hStartUpEvent);
1637
1638     /* make sleep time to be # of ms to record one packet */
1639     dwSleepTime = (1024 * 1000) / wwi->format.wf.nAvgBytesPerSec;
1640     TRACE("sleeptime=%ld ms\n", dwSleepTime);
1641
1642     for(;;) {
1643         TRACE("wwi->lpQueuePtr=(%p), wwi->state=(%d)\n",wwi->lpQueuePtr,wwi->state);
1644
1645         /* read all data is esd input buffer. */
1646         if ((wwi->lpQueuePtr != NULL) && (wwi->state == WINE_WS_PLAYING))
1647         {
1648             lpWaveHdr = wwi->lpQueuePtr;
1649  
1650             TRACE("read as much as we can\n");
1651             while(wwi->lpQueuePtr)
1652             {
1653                 TRACE("attempt to read %ld bytes\n",lpWaveHdr->dwBufferLength - lpWaveHdr->dwBytesRecorded);
1654                 bytesRead = read(wwi->esd_fd,
1655                               lpWaveHdr->lpData + lpWaveHdr->dwBytesRecorded,
1656                               lpWaveHdr->dwBufferLength - lpWaveHdr->dwBytesRecorded);
1657                 TRACE("bytesRead=%ld\n",bytesRead);
1658                 if (bytesRead == -1 && errno == EAGAIN)
1659                         bytesRead = 0;
1660                 if (bytesRead==0) break; /* So we can stop recording smoothly */
1661                 if (bytesRead < 0)
1662                         bytesRead = 0;
1663  
1664                 lpWaveHdr->dwBytesRecorded      += bytesRead;
1665                 wwi->dwRecordedTotal            += bytesRead;
1666
1667                 /* buffer full. notify client */
1668                 if (lpWaveHdr->dwBytesRecorded >= lpWaveHdr->dwBufferLength)
1669                 {
1670                     /* must copy the value of next waveHdr, because we have no idea of what
1671                      * will be done with the content of lpWaveHdr in callback
1672                      */
1673                     LPWAVEHDR   lpNext = lpWaveHdr->lpNext;
1674
1675                     TRACE("waveHdr full.\n");
1676  
1677                     lpWaveHdr->dwFlags &= ~WHDR_INQUEUE;
1678                     lpWaveHdr->dwFlags |=  WHDR_DONE;
1679  
1680                     widNotifyClient(wwi, WIM_DATA, (DWORD)lpWaveHdr, 0);
1681                     lpWaveHdr = wwi->lpQueuePtr = lpNext;
1682                 }
1683             }
1684         }
1685
1686         /* wait for dwSleepTime or an event in thread's queue */
1687         WaitForSingleObject(wwi->msgRing.msg_event, dwSleepTime);
1688
1689         while (ESD_RetrieveRingMessage(&wwi->msgRing, &msg, &param, &ev))
1690         {
1691             TRACE("msg=%s param=0x%lx\n",wodPlayerCmdString[msg - WM_USER - 1], param);
1692             switch(msg) {
1693             case WINE_WM_PAUSING:
1694                 wwi->state = WINE_WS_PAUSED;
1695
1696                 /* Put code here to "pause" esd recording
1697                  */
1698
1699                 SetEvent(ev);
1700                 break;
1701             case WINE_WM_STARTING:
1702                 wwi->state = WINE_WS_PLAYING;
1703
1704                 /* Put code here to "start" esd recording
1705                  */
1706
1707                 SetEvent(ev);
1708                 break;
1709             case WINE_WM_HEADER:
1710                 lpWaveHdr = (LPWAVEHDR)param;
1711                 /* insert buffer at end of queue */
1712                 {
1713                     LPWAVEHDR* wh;
1714                     int num_headers = 0;
1715                     for (wh = &(wwi->lpQueuePtr); *wh; wh = &((*wh)->lpNext))
1716                     {
1717                         num_headers++;
1718
1719                     }
1720                     *wh=lpWaveHdr;
1721                 }
1722                 break;
1723             case WINE_WM_STOPPING:
1724                 if (wwi->state != WINE_WS_STOPPED)
1725                 {
1726
1727                     /* Put code here to "stop" esd recording
1728                      */
1729
1730                     /* return current buffer to app */
1731                     lpWaveHdr = wwi->lpQueuePtr;
1732                     if (lpWaveHdr)
1733                     {
1734                         LPWAVEHDR lpNext = lpWaveHdr->lpNext;
1735                         TRACE("stop %p %p\n", lpWaveHdr, lpWaveHdr->lpNext);
1736                         lpWaveHdr->dwFlags &= ~WHDR_INQUEUE;
1737                         lpWaveHdr->dwFlags |= WHDR_DONE;
1738                         widNotifyClient(wwi, WIM_DATA, (DWORD)lpWaveHdr, 0);
1739                         wwi->lpQueuePtr = lpNext;
1740                     }
1741                 }
1742                 wwi->state = WINE_WS_STOPPED;
1743                 SetEvent(ev);
1744                 break;
1745             case WINE_WM_RESETTING:
1746                 wwi->state = WINE_WS_STOPPED;
1747                 wwi->dwRecordedTotal = 0;
1748
1749                 /* return all buffers to the app */
1750                 for (lpWaveHdr = wwi->lpQueuePtr; lpWaveHdr; lpWaveHdr = lpWaveHdr->lpNext) {
1751                     TRACE("reset %p %p\n", lpWaveHdr, lpWaveHdr->lpNext);
1752                     lpWaveHdr->dwFlags &= ~WHDR_INQUEUE;
1753                     lpWaveHdr->dwFlags |= WHDR_DONE;
1754
1755                     widNotifyClient(wwi, WIM_DATA, (DWORD)lpWaveHdr, 0);
1756                 }
1757                 wwi->lpQueuePtr = NULL; 
1758                 SetEvent(ev);
1759                 break;
1760             case WINE_WM_CLOSING:
1761                 wwi->hThread = 0;
1762                 wwi->state = WINE_WS_CLOSED;
1763                 SetEvent(ev);
1764                 ExitThread(0);
1765                 /* shouldn't go here */
1766             default:
1767                 FIXME("unknown message %d\n", msg);
1768                 break;
1769             }
1770         }
1771     }
1772     ExitThread(0);
1773     /* just for not generating compilation warnings... should never be executed */
1774     return 0;
1775 }
1776
1777 /**************************************************************************
1778  *                              widOpen                         [internal]
1779  */
1780 static DWORD widOpen(WORD wDevID, LPWAVEOPENDESC lpDesc, DWORD dwFlags)
1781 {
1782     WINE_WAVEIN*        wwi;
1783     /* input esound... */
1784     int                 in_bits = ESD_BITS16, in_channels = ESD_STEREO, in_rate;
1785 #ifdef WID_USE_ESDMON
1786     int                 in_mode = ESD_STREAM, in_func = ESD_PLAY;
1787 #else
1788     int                 in_mode = ESD_STREAM, in_func = ESD_RECORD;
1789 #endif
1790     esd_format_t        in_format;
1791     int                 mode;
1792
1793     TRACE("(%u, %p %08lX);\n",wDevID, lpDesc, dwFlags);
1794     if (lpDesc == NULL) {
1795         WARN("Invalid Parametr (lpDesc == NULL)!\n");
1796         return MMSYSERR_INVALPARAM;
1797     }
1798
1799     if (wDevID >= MAX_WAVEINDRV) {
1800         TRACE ("MAX_WAVEINDRV reached !\n");
1801         return MMSYSERR_BADDEVICEID;
1802     }
1803
1804     /* if this device is already open tell the app that it is allocated */
1805     if(WInDev[wDevID].esd_fd != -1)
1806     {
1807         TRACE("device already allocated\n");
1808         return MMSYSERR_ALLOCATED;
1809     }
1810
1811     /* only PCM format is support so far... */
1812     if (lpDesc->lpFormat->wFormatTag != WAVE_FORMAT_PCM ||
1813         lpDesc->lpFormat->nChannels == 0 ||
1814         lpDesc->lpFormat->nSamplesPerSec < DSBFREQUENCY_MIN ||
1815         lpDesc->lpFormat->nSamplesPerSec > DSBFREQUENCY_MAX ||
1816         (lpDesc->lpFormat->wBitsPerSample!=8 && lpDesc->lpFormat->wBitsPerSample!=16)) {
1817         WARN("Bad format: tag=%04X nChannels=%d nSamplesPerSec=%ld !\n",
1818              lpDesc->lpFormat->wFormatTag, lpDesc->lpFormat->nChannels,
1819              lpDesc->lpFormat->nSamplesPerSec);
1820         return WAVERR_BADFORMAT;
1821     }
1822
1823     if (dwFlags & WAVE_FORMAT_QUERY) {
1824         TRACE("Query format: tag=%04X nChannels=%d nSamplesPerSec=%ld !\n",
1825              lpDesc->lpFormat->wFormatTag, lpDesc->lpFormat->nChannels,
1826              lpDesc->lpFormat->nSamplesPerSec);
1827         return MMSYSERR_NOERROR;
1828     }
1829
1830     wwi = &WInDev[wDevID];
1831
1832     /* direct sound not supported, ignore the flag */
1833     dwFlags &= ~WAVE_DIRECTSOUND;
1834
1835     wwi->wFlags = HIWORD(dwFlags & CALLBACK_TYPEMASK);
1836  
1837     memcpy(&wwi->waveDesc, lpDesc,           sizeof(WAVEOPENDESC));
1838     memcpy(&wwi->format,   lpDesc->lpFormat, sizeof(PCMWAVEFORMAT));
1839
1840     if (wwi->format.wBitsPerSample == 0) {
1841         WARN("Resetting zerod wBitsPerSample\n");
1842         wwi->format.wBitsPerSample = 8 *
1843             (wwi->format.wf.nAvgBytesPerSec /
1844              wwi->format.wf.nSamplesPerSec) /
1845             wwi->format.wf.nChannels;
1846     }
1847
1848     if (wwi->format.wBitsPerSample == 8)
1849         in_bits = ESD_BITS8;
1850     else if (wwi->format.wBitsPerSample == 16)
1851         in_bits = ESD_BITS16;
1852
1853     wwi->bytes_per_frame = (wwi->format.wBitsPerSample * wwi->format.wf.nChannels) / 8;
1854
1855     if (wwi->format.wf.nChannels == 1)
1856         in_channels = ESD_MONO;
1857     else if (wwi->format.wf.nChannels == 2)
1858         in_channels = ESD_STEREO;
1859
1860     in_format = in_bits | in_channels | in_mode | in_func;
1861     in_rate = (int) wwi->format.wf.nSamplesPerSec;
1862         TRACE("esd input format = 0x%08x, rate = %d\n", in_format, in_rate);
1863
1864 #ifdef WID_USE_ESDMON
1865     wwi->esd_fd = esd_monitor_stream(in_format, in_rate, esd_host, "wineesd");
1866 #else
1867     wwi->esd_fd = esd_record_stream(in_format, in_rate, esd_host, "wineesd");
1868 #endif
1869     TRACE("(wwi->esd_fd=%d)\n",wwi->esd_fd);
1870     wwi->state = WINE_WS_STOPPED;
1871
1872     if (wwi->lpQueuePtr) {
1873         WARN("Should have an empty queue (%p)\n", wwi->lpQueuePtr);
1874         wwi->lpQueuePtr = NULL;
1875     }
1876
1877     if(wwi->esd_fd < 0) return MMSYSERR_ALLOCATED;
1878
1879     /* Set the esd socket O_NONBLOCK, so we can stop recording smoothly */
1880     mode = fcntl(wwi->esd_fd, F_GETFL);
1881     mode |= O_NONBLOCK;
1882     fcntl(wwi->esd_fd, F_SETFL, mode);
1883
1884     wwi->dwRecordedTotal = 0;
1885     wwi->wFlags = HIWORD(dwFlags & CALLBACK_TYPEMASK);
1886
1887     ESD_InitRingMessage(&wwi->msgRing);
1888
1889     /* create recorder thread */
1890     if (!(dwFlags & WAVE_DIRECTSOUND)) {
1891         wwi->hStartUpEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
1892         wwi->hThread = CreateThread(NULL, 0, widRecorder, (LPVOID)(DWORD)wDevID, 0, &(wwi->dwThreadID));
1893         WaitForSingleObject(wwi->hStartUpEvent, INFINITE);
1894         CloseHandle(wwi->hStartUpEvent);
1895     } else {
1896         wwi->hThread = INVALID_HANDLE_VALUE;
1897         wwi->dwThreadID = 0;
1898     }
1899     wwi->hStartUpEvent = INVALID_HANDLE_VALUE;
1900
1901     TRACE("wBitsPerSample=%u, nAvgBytesPerSec=%lu, nSamplesPerSec=%lu, nChannels=%u nBlockAlign=%u!\n",
1902           wwi->format.wBitsPerSample, wwi->format.wf.nAvgBytesPerSec,
1903           wwi->format.wf.nSamplesPerSec, wwi->format.wf.nChannels,
1904           wwi->format.wf.nBlockAlign);
1905     return widNotifyClient(wwi, WIM_OPEN, 0L, 0L);
1906 }
1907
1908 /**************************************************************************
1909  *                              widClose                        [internal]
1910  */
1911 static DWORD widClose(WORD wDevID)
1912 {
1913     WINE_WAVEIN*        wwi;
1914
1915     TRACE("(%u);\n", wDevID);
1916     if (wDevID >= MAX_WAVEINDRV || WInDev[wDevID].state == WINE_WS_CLOSED) {
1917         WARN("can't close !\n");
1918         return MMSYSERR_INVALHANDLE;
1919     }
1920
1921     wwi = &WInDev[wDevID];
1922
1923     if (wwi->lpQueuePtr != NULL) {
1924         WARN("still buffers open !\n");
1925         return WAVERR_STILLPLAYING;
1926     }
1927
1928     ESD_AddRingMessage(&wwi->msgRing, WINE_WM_CLOSING, 0, TRUE);
1929     ESD_CloseWaveInDevice(wwi);
1930     wwi->state = WINE_WS_CLOSED;
1931     ESD_DestroyRingMessage(&wwi->msgRing);
1932     return widNotifyClient(wwi, WIM_CLOSE, 0L, 0L);
1933 }
1934
1935 /**************************************************************************
1936  *                              widAddBuffer            [internal]
1937  */
1938 static DWORD widAddBuffer(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
1939 {
1940     TRACE("(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
1941
1942     if (wDevID >= MAX_WAVEINDRV || WInDev[wDevID].state == WINE_WS_CLOSED) {
1943         WARN("can't do it !\n");
1944         return MMSYSERR_INVALHANDLE;
1945     }
1946     if (!(lpWaveHdr->dwFlags & WHDR_PREPARED)) {
1947         TRACE("never been prepared !\n");
1948         return WAVERR_UNPREPARED;
1949     }
1950     if (lpWaveHdr->dwFlags & WHDR_INQUEUE) {
1951         TRACE("header already in use !\n");
1952         return WAVERR_STILLPLAYING;
1953     }
1954
1955     lpWaveHdr->dwFlags |= WHDR_INQUEUE;
1956     lpWaveHdr->dwFlags &= ~WHDR_DONE;
1957     lpWaveHdr->dwBytesRecorded = 0;
1958     lpWaveHdr->lpNext = NULL;
1959
1960     ESD_AddRingMessage(&WInDev[wDevID].msgRing, WINE_WM_HEADER, (DWORD)lpWaveHdr, FALSE);
1961     return MMSYSERR_NOERROR;
1962 }
1963
1964 /**************************************************************************
1965  *                              widPrepare                      [internal]
1966  */
1967 static DWORD widPrepare(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
1968 {
1969     TRACE("(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
1970
1971     if (wDevID >= MAX_WAVEINDRV) return MMSYSERR_INVALHANDLE;
1972
1973     if (lpWaveHdr->dwFlags & WHDR_INQUEUE)
1974         return WAVERR_STILLPLAYING;
1975
1976     lpWaveHdr->dwFlags |= WHDR_PREPARED;
1977     lpWaveHdr->dwFlags &= ~WHDR_DONE;
1978     lpWaveHdr->dwBytesRecorded = 0;
1979
1980     return MMSYSERR_NOERROR;
1981 }
1982
1983 /**************************************************************************
1984  *                              widUnprepare                    [internal]
1985  */
1986 static DWORD widUnprepare(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
1987 {
1988     TRACE("(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
1989     if (wDevID >= MAX_WAVEINDRV) {
1990         WARN("bad device ID !\n");
1991         return MMSYSERR_INVALHANDLE;
1992     }
1993
1994     if (lpWaveHdr->dwFlags & WHDR_INQUEUE) {
1995         TRACE("Still playing...\n");
1996         return WAVERR_STILLPLAYING;
1997     }
1998
1999     lpWaveHdr->dwFlags &= ~WHDR_PREPARED;
2000     lpWaveHdr->dwFlags |= WHDR_DONE;
2001
2002     return MMSYSERR_NOERROR;
2003 }
2004
2005 /**************************************************************************
2006  *                      widStart                                [internal]
2007  */
2008 static DWORD widStart(WORD wDevID)
2009 {
2010     TRACE("(%u);\n", wDevID);
2011     if (wDevID >= MAX_WAVEINDRV || WInDev[wDevID].state == WINE_WS_CLOSED) {
2012         WARN("can't start recording !\n");
2013         return MMSYSERR_INVALHANDLE;
2014     }
2015
2016     ESD_AddRingMessage(&WInDev[wDevID].msgRing, WINE_WM_STARTING, 0, TRUE);
2017     return MMSYSERR_NOERROR;
2018 }
2019
2020 /**************************************************************************
2021  *                      widStop                                 [internal]
2022  */
2023 static DWORD widStop(WORD wDevID)
2024 {
2025     TRACE("(%u);\n", wDevID);
2026     if (wDevID >= MAX_WAVEINDRV || WInDev[wDevID].state == WINE_WS_CLOSED) {
2027         WARN("can't stop !\n");
2028         return MMSYSERR_INVALHANDLE;
2029     }
2030
2031     ESD_AddRingMessage(&WInDev[wDevID].msgRing, WINE_WM_STOPPING, 0, TRUE);
2032
2033     return MMSYSERR_NOERROR;
2034 }
2035
2036 /**************************************************************************
2037  *                      widReset                                [internal]
2038  */
2039 static DWORD widReset(WORD wDevID)
2040 {
2041     TRACE("(%u);\n", wDevID);
2042     if (wDevID >= MAX_WAVEINDRV || WInDev[wDevID].state == WINE_WS_CLOSED) {
2043         WARN("can't reset !\n");
2044         return MMSYSERR_INVALHANDLE;
2045     }
2046     ESD_AddRingMessage(&WInDev[wDevID].msgRing, WINE_WM_RESETTING, 0, TRUE);
2047     return MMSYSERR_NOERROR;
2048 }
2049
2050 /**************************************************************************
2051  *                              widMessage (WINEESD.6)
2052  */
2053 DWORD WINAPI ESD_widMessage(UINT wDevID, UINT wMsg, DWORD dwUser,
2054                             DWORD dwParam1, DWORD dwParam2)
2055 {
2056     TRACE("(%u, %04X, %08lX, %08lX, %08lX);\n",
2057           wDevID, wMsg, dwUser, dwParam1, dwParam2);
2058     switch (wMsg) {
2059     case DRVM_INIT:
2060     case DRVM_EXIT:
2061     case DRVM_ENABLE:
2062     case DRVM_DISABLE:
2063         /* FIXME: Pretend this is supported */
2064         return 0;
2065     case WIDM_OPEN:             return widOpen          (wDevID, (LPWAVEOPENDESC)dwParam1,      dwParam2);
2066     case WIDM_CLOSE:            return widClose         (wDevID);
2067     case WIDM_ADDBUFFER:        return widAddBuffer     (wDevID, (LPWAVEHDR)dwParam1, dwParam2);
2068     case WIDM_PREPARE:          return widPrepare       (wDevID, (LPWAVEHDR)dwParam1, dwParam2);
2069     case WIDM_UNPREPARE:        return widUnprepare     (wDevID, (LPWAVEHDR)dwParam1, dwParam2);
2070     case WIDM_GETDEVCAPS:       return widGetDevCaps    (wDevID, (LPWAVEINCAPSW)dwParam1,       dwParam2);
2071     case WIDM_GETNUMDEVS:       return widGetNumDevs    ();
2072     case WIDM_RESET:            return widReset         (wDevID);
2073     case WIDM_START:            return widStart         (wDevID);
2074     case WIDM_STOP:             return widStop          (wDevID);
2075     case DRV_QUERYDEVICEINTERFACESIZE: return widDevInterfaceSize       (wDevID, (LPDWORD)dwParam1);
2076     case DRV_QUERYDEVICEINTERFACE:     return widDevInterface           (wDevID, (PWCHAR)dwParam1, dwParam2);
2077     default:
2078         FIXME("unknown message %d!\n", wMsg);
2079     }
2080     return MMSYSERR_NOTSUPPORTED;
2081 }
2082
2083 /*======================================================================*
2084  *                  Low level DSOUND implementation                     *
2085  *======================================================================*/
2086 static DWORD wodDsCreate(UINT wDevID, PIDSDRIVER* drv)
2087 {
2088     /* we can't perform memory mapping as we don't have a file stream
2089         interface with esd like we do with oss */
2090     MESSAGE("This sound card's driver does not support direct access\n");
2091     MESSAGE("The (slower) DirectSound HEL mode will be used instead.\n");
2092     return MMSYSERR_NOTSUPPORTED;
2093 }
2094
2095 static DWORD wodDsDesc(UINT wDevID, PDSDRIVERDESC desc)
2096 {
2097     memset(desc, 0, sizeof(*desc));
2098     strcpy(desc->szDesc, "Wine EsounD DirectSound Driver");
2099     strcpy(desc->szDrvname, "wineesd.drv");
2100     return MMSYSERR_NOERROR;
2101 }
2102
2103 #else /* !HAVE_ESD */
2104
2105 /**************************************************************************
2106  *                              wodMessage (WINEESD.@)
2107  */
2108 DWORD WINAPI ESD_wodMessage(WORD wDevID, WORD wMsg, DWORD dwUser,
2109                             DWORD dwParam1, DWORD dwParam2)
2110 {
2111     FIXME("(%u, %04X, %08lX, %08lX, %08lX):stub\n", wDevID, wMsg, dwUser, dwParam1, dwParam2);
2112     return MMSYSERR_NOTENABLED;
2113 }
2114
2115 /**************************************************************************
2116  *                              widMessage (WINEESD.6)
2117  */
2118 DWORD WINAPI ESD_widMessage(UINT wDevID, UINT wMsg, DWORD dwUser,
2119                             DWORD dwParam1, DWORD dwParam2)
2120 {
2121     FIXME("(%u, %04X, %08lX, %08lX, %08lX):stub\n", wDevID, wMsg, dwUser, dwParam1, dwParam2);
2122     return MMSYSERR_NOTENABLED;
2123 }
2124
2125 #endif /* HAVE_ESD */