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->