winecoreaudio: Added WAVEFORMATEXTENSIBLE support, for PCM only.
[wine] / dlls / winecoreaudio.drv / audio.c
1 /*
2  * Wine Driver for CoreAudio based on Jack Driver
3  *
4  * Copyright 1994 Martin Ayotte
5  * Copyright 1999 Eric Pouech (async playing in waveOut/waveIn)
6  * Copyright 2000 Eric Pouech (loops in waveOut)
7  * Copyright 2002 Chris Morgan (jack version of this file)
8  * Copyright 2005, 2006 Emmanuel Maillard
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
25 #include "config.h"
26
27 #include <stdlib.h>
28 #include <stdarg.h>
29 #include <stdio.h>
30 #include <string.h>
31 #ifdef HAVE_UNISTD_H
32 # include <unistd.h>
33 #endif
34 #include <fcntl.h>
35 #include <assert.h>
36
37 #include "windef.h"
38 #include "winbase.h"
39 #include "winnls.h"
40 #include "wingdi.h"
41 #include "winerror.h"
42 #include "mmddk.h"
43 #include "mmreg.h"
44 #include "dsound.h"
45 #include "dsdriver.h"
46 #include "ks.h"
47 #include "ksguid.h"
48 #include "ksmedia.h"
49 #include "coreaudio.h"
50 #include "wine/unicode.h"
51 #include "wine/library.h"
52 #include "wine/debug.h"
53
54 WINE_DEFAULT_DEBUG_CHANNEL(wave);
55
56
57 #if defined(HAVE_COREAUDIO_COREAUDIO_H) && defined(HAVE_AUDIOUNIT_AUDIOUNIT_H)
58 #include <CoreAudio/CoreAudio.h>
59 #include <CoreFoundation/CoreFoundation.h>
60 #include <libkern/OSAtomic.h>
61
62 /*
63     Due to AudioUnit headers conflict define some needed types.
64 */
65
66 typedef void *AudioUnit;
67
68 /* From AudioUnit/AUComponents.h */
69 enum
70 {
71     kAudioUnitRenderAction_OutputIsSilence  = (1 << 4),
72         /* provides hint on return from Render(): if set the buffer contains all zeroes */
73 };
74 typedef UInt32 AudioUnitRenderActionFlags;
75
76 typedef long ComponentResult;
77 extern ComponentResult
78 AudioUnitRender(                    AudioUnit                       ci,
79                                     AudioUnitRenderActionFlags *    ioActionFlags,
80                                     const AudioTimeStamp *          inTimeStamp,
81                                     UInt32                          inOutputBusNumber,
82                                     UInt32                          inNumberFrames,
83                                     AudioBufferList *               ioData)         AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER;
84
85 /* only allow 10 output devices through this driver, this ought to be adequate */
86 #define MAX_WAVEOUTDRV  (1)
87 #define MAX_WAVEINDRV   (1)
88
89 /* state diagram for waveOut writing:
90 *
91 * +---------+-------------+---------------+---------------------------------+
92 * |  state  |  function   |     event     |            new state             |
93 * +---------+-------------+---------------+---------------------------------+
94 * |         | open()       |               | PLAYING                         |
95 * | PAUSED  | write()      |               | PAUSED                          |
96 * | PLAYING | write()      | HEADER        | PLAYING                         |
97 * | (other) | write()      | <error>       |                                 |
98 * | (any)   | pause()      | PAUSING       | PAUSED                          |
99 * | PAUSED  | restart()    | RESTARTING    | PLAYING                         |
100 * | (any)   | reset()      | RESETTING     | PLAYING                         |
101 * | (any)   | close()      | CLOSING       | CLOSED                          |
102 * +---------+-------------+---------------+---------------------------------+
103 */
104
105 /* states of the playing device */
106 #define WINE_WS_PLAYING   0 /* for waveOut: lpPlayPtr == NULL -> stopped */
107 #define WINE_WS_PAUSED    1
108 #define WINE_WS_STOPPED   2 /* Not used for waveOut */
109 #define WINE_WS_CLOSED    3
110 #define WINE_WS_OPENING   4
111 #define WINE_WS_CLOSING   5
112
113 typedef struct tagCoreAudio_Device {
114     char                        dev_name[32];
115     char                        mixer_name[32];
116     unsigned                    open_count;
117     char*                       interface_name;
118     
119     WAVEOUTCAPSW                out_caps;
120     WAVEINCAPSW                 in_caps;
121     DWORD                       in_caps_support;
122     int                         sample_rate;
123     int                         stereo;
124     int                         format;
125     unsigned                    audio_fragment;
126     BOOL                        full_duplex;
127     BOOL                        bTriggerSupport;
128     BOOL                        bOutputEnabled;
129     BOOL                        bInputEnabled;
130     DSDRIVERDESC                ds_desc;
131     DSDRIVERCAPS                ds_caps;
132     DSCDRIVERCAPS               dsc_caps;
133     GUID                        ds_guid;
134     GUID                        dsc_guid;
135     
136     AudioDeviceID outputDeviceID;
137     AudioDeviceID inputDeviceID;
138     AudioStreamBasicDescription streamDescription;
139 } CoreAudio_Device;
140
141 /* for now use the default device */
142 static CoreAudio_Device CoreAudio_DefaultDevice;
143
144 typedef struct {
145     volatile int                state;      /* one of the WINE_WS_ manifest constants */
146     CoreAudio_Device            *cadev;
147     WAVEOPENDESC                waveDesc;
148     WORD                        wFlags;
149     PCMWAVEFORMAT               format;
150     DWORD                       woID;
151     AudioUnit                   audioUnit;
152     AudioStreamBasicDescription streamDescription;
153     
154     WAVEOUTCAPSW                caps;
155     char                        interface_name[32];
156     LPWAVEHDR                   lpQueuePtr;             /* start of queued WAVEHDRs (waiting to be notified) */
157     LPWAVEHDR                   lpPlayPtr;              /* start of not yet fully played buffers */
158     DWORD                       dwPartialOffset;        /* Offset of not yet written bytes in lpPlayPtr */
159     
160     LPWAVEHDR                   lpLoopPtr;              /* pointer of first buffer in loop, if any */
161     DWORD                       dwLoops;                /* private copy of loop counter */
162     
163     DWORD                       dwPlayedTotal;          /* number of bytes actually played since opening */
164     DWORD                       dwWrittenTotal;         /* number of bytes written to OSS buffer since opening */
165         
166     DWORD                       tickCountMS; /* time in MS of last AudioUnit callback */
167
168     OSSpinLock                  lock;         /* synchronization stuff */
169
170     BOOL trace_on;
171     BOOL warn_on;
172     BOOL err_on;
173 } WINE_WAVEOUT;
174
175 typedef struct {
176     /* This device's device number */
177     DWORD           wiID;
178
179     /* Access to the following fields is synchronized across threads. */
180     volatile int    state;
181     LPWAVEHDR       lpQueuePtr;
182     DWORD           dwTotalRecorded;
183
184     /* Synchronization mechanism to protect above fields */
185     OSSpinLock      lock;
186
187     /* Capabilities description */
188     WAVEINCAPSW     caps;
189     char            interface_name[32];
190
191     /* Record the arguments used when opening the device. */
192     WAVEOPENDESC    waveDesc;
193     WORD            wFlags;
194     PCMWAVEFORMAT   format;
195
196     AudioUnit       audioUnit;
197     AudioBufferList*bufferList;
198     AudioBufferList*bufferListCopy;
199
200     /* Record state of debug channels at open.  Used to control fprintf's since
201      * we can't use Wine debug channel calls in non-Wine AudioUnit threads. */
202     BOOL            trace_on;
203     BOOL            warn_on;
204     BOOL            err_on;
205
206 /* These fields aren't used. */
207 #if 0
208     CoreAudio_Device *cadev;
209
210     AudioStreamBasicDescription streamDescription;
211 #endif
212 } WINE_WAVEIN;
213
214 static WINE_WAVEOUT WOutDev   [MAX_WAVEOUTDRV];
215 static WINE_WAVEIN  WInDev    [MAX_WAVEINDRV];
216
217 static HANDLE hThread = NULL; /* Track the thread we create so we can clean it up later */
218 static CFMessagePortRef Port_SendToMessageThread;
219
220 static void wodHelper_PlayPtrNext(WINE_WAVEOUT* wwo);
221 static void wodHelper_NotifyDoneForList(WINE_WAVEOUT* wwo, LPWAVEHDR lpWaveHdr);
222 static void wodHelper_NotifyCompletions(WINE_WAVEOUT* wwo, BOOL force);
223 static void widHelper_NotifyCompletions(WINE_WAVEIN* wwi);
224
225 extern int AudioUnit_CreateDefaultAudioUnit(void *wwo, AudioUnit *au);
226 extern int AudioUnit_CloseAudioUnit(AudioUnit au);
227 extern int AudioUnit_InitializeWithStreamDescription(AudioUnit au, AudioStreamBasicDescription *streamFormat);
228
229 extern OSStatus AudioOutputUnitStart(AudioUnit au);
230 extern OSStatus AudioOutputUnitStop(AudioUnit au);
231 extern OSStatus AudioUnitUninitialize(AudioUnit au);
232
233 extern int AudioUnit_SetVolume(AudioUnit au, float left, float right);
234 extern int AudioUnit_GetVolume(AudioUnit au, float *left, float *right);
235
236 extern int AudioUnit_GetInputDeviceSampleRate(void);
237
238 extern int AudioUnit_CreateInputUnit(void* wwi, AudioUnit* out_au,
239         WORD nChannels, DWORD nSamplesPerSec, WORD wBitsPerSample,
240         UInt32* outFrameCount);
241
242 OSStatus CoreAudio_woAudioUnitIOProc(void *inRefCon, 
243                                      AudioUnitRenderActionFlags *ioActionFlags, 
244                                      const AudioTimeStamp *inTimeStamp, 
245                                      UInt32 inBusNumber, 
246                                      UInt32 inNumberFrames, 
247                                      AudioBufferList *ioData);
248 OSStatus CoreAudio_wiAudioUnitIOProc(void *inRefCon,
249                                      AudioUnitRenderActionFlags *ioActionFlags,
250                                      const AudioTimeStamp *inTimeStamp,
251                                      UInt32 inBusNumber,
252                                      UInt32 inNumberFrames,
253                                      AudioBufferList *ioData);
254
255 /* These strings used only for tracing */
256
257 static const char * getMessage(UINT msg)
258 {
259     static char unknown[32];
260 #define MSG_TO_STR(x) case x: return #x
261     switch(msg) {
262         MSG_TO_STR(DRVM_INIT);
263         MSG_TO_STR(DRVM_EXIT);
264         MSG_TO_STR(DRVM_ENABLE);
265         MSG_TO_STR(DRVM_DISABLE);
266         MSG_TO_STR(WIDM_OPEN);
267         MSG_TO_STR(WIDM_CLOSE);
268         MSG_TO_STR(WIDM_ADDBUFFER);
269         MSG_TO_STR(WIDM_PREPARE);
270         MSG_TO_STR(WIDM_UNPREPARE);
271         MSG_TO_STR(WIDM_GETDEVCAPS);
272         MSG_TO_STR(WIDM_GETNUMDEVS);
273         MSG_TO_STR(WIDM_GETPOS);
274         MSG_TO_STR(WIDM_RESET);
275         MSG_TO_STR(WIDM_START);
276         MSG_TO_STR(WIDM_STOP);
277         MSG_TO_STR(WODM_OPEN);
278         MSG_TO_STR(WODM_CLOSE);
279         MSG_TO_STR(WODM_WRITE);
280         MSG_TO_STR(WODM_PAUSE);
281         MSG_TO_STR(WODM_GETPOS);
282         MSG_TO_STR(WODM_BREAKLOOP);
283         MSG_TO_STR(WODM_PREPARE);
284         MSG_TO_STR(WODM_UNPREPARE);
285         MSG_TO_STR(WODM_GETDEVCAPS);
286         MSG_TO_STR(WODM_GETNUMDEVS);
287         MSG_TO_STR(WODM_GETPITCH);
288         MSG_TO_STR(WODM_SETPITCH);
289         MSG_TO_STR(WODM_GETPLAYBACKRATE);
290         MSG_TO_STR(WODM_SETPLAYBACKRATE);
291         MSG_TO_STR(WODM_GETVOLUME);
292         MSG_TO_STR(WODM_SETVOLUME);
293         MSG_TO_STR(WODM_RESTART);
294         MSG_TO_STR(WODM_RESET);
295         MSG_TO_STR(DRV_QUERYDEVICEINTERFACESIZE);
296         MSG_TO_STR(DRV_QUERYDEVICEINTERFACE);
297         MSG_TO_STR(DRV_QUERYDSOUNDIFACE);
298         MSG_TO_STR(DRV_QUERYDSOUNDDESC);
299     }
300 #undef MSG_TO_STR
301     sprintf(unknown, "UNKNOWN(0x%04x)", msg);
302     return unknown;
303 }
304
305 #define kStopLoopMessage 0
306 #define kWaveOutNotifyCompletionsMessage 1
307 #define kWaveInNotifyCompletionsMessage 2
308
309 /* Mach Message Handling */
310 static CFDataRef wodMessageHandler(CFMessagePortRef port_ReceiveInMessageThread, SInt32 msgid, CFDataRef data, void *info)
311 {
312     UInt32 *buffer = NULL;
313
314     switch (msgid)
315     {
316         case kWaveOutNotifyCompletionsMessage:
317             buffer = (UInt32 *) CFDataGetBytePtr(data);
318             wodHelper_NotifyCompletions(&WOutDev[buffer[0]], FALSE);
319             break;
320         case kWaveInNotifyCompletionsMessage:
321             buffer = (UInt32 *) CFDataGetBytePtr(data);
322             widHelper_NotifyCompletions(&WInDev[buffer[0]]);
323             break;
324         default:
325             CFRunLoopStop(CFRunLoopGetCurrent());
326             break;
327     }
328     
329     return NULL;
330 }
331
332 static DWORD WINAPI messageThread(LPVOID p)
333 {
334     CFMessagePortRef port_ReceiveInMessageThread = (CFMessagePortRef) p;
335     CFRunLoopSourceRef source;
336     
337     source = CFMessagePortCreateRunLoopSource(kCFAllocatorDefault, port_ReceiveInMessageThread, (CFIndex)0);
338     CFRunLoopAddSource(CFRunLoopGetCurrent(), source, kCFRunLoopDefaultMode);
339
340     CFRunLoopRun();
341
342     CFRunLoopSourceInvalidate(source);
343     CFRelease(source);
344     CFRelease(port_ReceiveInMessageThread);
345
346     return 0;
347 }
348
349 /**************************************************************************
350 *                       wodSendNotifyCompletionsMessage                 [internal]
351 *   Call from AudioUnit IO thread can't use Wine debug channels.
352 */
353 static void wodSendNotifyCompletionsMessage(WINE_WAVEOUT* wwo)
354 {
355     CFDataRef data;
356     UInt32 buffer;
357
358     if (!Port_SendToMessageThread)
359         return;
360
361     buffer = (UInt32) wwo->woID;
362
363     data = CFDataCreate(kCFAllocatorDefault, (UInt8 *)&buffer, sizeof(buffer));
364     if (!data)
365         return;
366
367     CFMessagePortSendRequest(Port_SendToMessageThread, kWaveOutNotifyCompletionsMessage, data, 0.0, 0.0, NULL, NULL);
368     CFRelease(data);
369 }
370
371 /**************************************************************************
372 *                       wodSendNotifyInputCompletionsMessage     [internal]
373 *   Call from AudioUnit IO thread can't use Wine debug channels.
374 */
375 static void wodSendNotifyInputCompletionsMessage(WINE_WAVEIN* wwi)
376 {
377     CFDataRef data;
378     UInt32 buffer;
379
380     if (!Port_SendToMessageThread)
381         return;
382
383     buffer = (UInt32) wwi->wiID;
384
385     data = CFDataCreate(kCFAllocatorDefault, (UInt8 *)&buffer, sizeof(buffer));
386     if (!data)
387         return;
388
389     CFMessagePortSendRequest(Port_SendToMessageThread, kWaveInNotifyCompletionsMessage, data, 0.0, 0.0, NULL, NULL);
390     CFRelease(data);
391 }
392
393 static DWORD bytes_to_mmtime(LPMMTIME lpTime, DWORD position,
394                              PCMWAVEFORMAT* format)
395 {
396     TRACE("wType=%04X wBitsPerSample=%u nSamplesPerSec=%u nChannels=%u nAvgBytesPerSec=%u\n",
397           lpTime->wType, format->wBitsPerSample, format->wf.nSamplesPerSec,
398           format->wf.nChannels, format->wf.nAvgBytesPerSec);
399     TRACE("Position in bytes=%u\n", position);
400
401     switch (lpTime->wType) {
402     case TIME_SAMPLES:
403         lpTime->u.sample = position / (format->wBitsPerSample / 8 * format->wf.nChannels);
404         TRACE("TIME_SAMPLES=%u\n", lpTime->u.sample);
405         break;
406     case TIME_MS:
407         lpTime->u.ms = 1000.0 * position / (format->wBitsPerSample / 8 * format->wf.nChannels * format->wf.nSamplesPerSec);
408         TRACE("TIME_MS=%u\n", lpTime->u.ms);
409         break;
410     case TIME_SMPTE:
411         lpTime->u.smpte.fps = 30;
412         position = position / (format->wBitsPerSample / 8 * format->wf.nChannels);
413         position += (format->wf.nSamplesPerSec / lpTime->u.smpte.fps) - 1; /* round up */
414         lpTime->u.smpte.sec = position / format->wf.nSamplesPerSec;
415         position -= lpTime->u.smpte.sec * format->wf.nSamplesPerSec;
416         lpTime->u.smpte.min = lpTime->u.smpte.sec / 60;
417         lpTime->u.smpte.sec -= 60 * lpTime->u.smpte.min;
418         lpTime->u.smpte.hour = lpTime->u.smpte.min / 60;
419         lpTime->u.smpte.min -= 60 * lpTime->u.smpte.hour;
420         lpTime->u.smpte.fps = 30;
421         lpTime->u.smpte.frame = position * lpTime->u.smpte.fps / format->wf.nSamplesPerSec;
422         TRACE("TIME_SMPTE=%02u:%02u:%02u:%02u\n",
423               lpTime->u.smpte.hour, lpTime->u.smpte.min,
424               lpTime->u.smpte.sec, lpTime->u.smpte.frame);
425         break;
426     default:
427         WARN("Format %d not supported, using TIME_BYTES !\n", lpTime->wType);
428         lpTime->wType = TIME_BYTES;
429         /* fall through */
430     case TIME_BYTES:
431         lpTime->u.cb = position;
432         TRACE("TIME_BYTES=%u\n", lpTime->u.cb);
433         break;
434     }
435     return MMSYSERR_NOERROR;
436 }
437
438 static BOOL supportedFormat(LPWAVEFORMATEX wf)
439 {
440     if (wf->nSamplesPerSec == 0)
441         return FALSE;
442
443     if (wf->wFormatTag == WAVE_FORMAT_PCM) {
444         if (wf->nChannels >= 1 && wf->nChannels <= 2) {
445             if (wf->wBitsPerSample==8||wf->wBitsPerSample==16)
446                 return TRUE;
447         }
448     } else if (wf->wFormatTag == WAVE_FORMAT_EXTENSIBLE) {
449         WAVEFORMATEXTENSIBLE * wfex = (WAVEFORMATEXTENSIBLE *)wf;
450
451         if (wf->cbSize == 22 && IsEqualGUID(&wfex->SubFormat, &KSDATAFORMAT_SUBTYPE_PCM)) {
452             if (wf->nChannels >=1 && wf->nChannels <= 2) {
453                 if (wf->wBitsPerSample==wfex->Samples.wValidBitsPerSample) {
454                     if (wf->wBitsPerSample==8||wf->wBitsPerSample==16)
455                         return TRUE;
456                 } else
457                     WARN("wBitsPerSample != wValidBitsPerSample not supported yet\n");
458             }
459         } else
460             WARN("only KSDATAFORMAT_SUBTYPE_PCM supported\n");
461     } else
462         WARN("only WAVE_FORMAT_PCM supported\n");
463
464     return FALSE;
465 }
466
467 void copyFormat(LPWAVEFORMATEX wf1, LPPCMWAVEFORMAT wf2)
468 {
469     memcpy(wf2, wf1, sizeof(PCMWAVEFORMAT));
470     /* Downgrade WAVE_FORMAT_EXTENSIBLE KSDATAFORMAT_SUBTYPE_PCM
471      * to smaller yet compatible WAVE_FORMAT_PCM structure */
472     if (wf2->wf.wFormatTag == WAVE_FORMAT_EXTENSIBLE)
473         wf2->wf.wFormatTag = WAVE_FORMAT_PCM;
474 }
475
476 /**************************************************************************
477 *                       CoreAudio_GetDevCaps            [internal]
478 */
479 BOOL CoreAudio_GetDevCaps (void)
480 {
481     OSStatus status;
482     UInt32 propertySize;
483     AudioDeviceID devId = CoreAudio_DefaultDevice.outputDeviceID;
484     
485     char name[MAXPNAMELEN];
486     
487     propertySize = MAXPNAMELEN;
488     status = AudioDeviceGetProperty(devId, 0 , FALSE, kAudioDevicePropertyDeviceName, &propertySize, name);
489     if (status) {
490         ERR("AudioHardwareGetProperty for kAudioDevicePropertyDeviceName return %c%c%c%c\n", (char) (status >> 24),
491                                                                                              (char) (status >> 16),
492                                                                                              (char) (status >> 8),
493                                                                                              (char) status);
494         return FALSE;
495     }
496     
497     memcpy(CoreAudio_DefaultDevice.ds_desc.szDesc, name, sizeof(name));
498     strcpy(CoreAudio_DefaultDevice.ds_desc.szDrvname, "winecoreaudio.drv");
499     MultiByteToWideChar(CP_UNIXCP, 0, name, sizeof(name),
500                         CoreAudio_DefaultDevice.out_caps.szPname, 
501                         sizeof(CoreAudio_DefaultDevice.out_caps.szPname) / sizeof(WCHAR));
502     memcpy(CoreAudio_DefaultDevice.dev_name, name, 32);
503     
504     propertySize = sizeof(CoreAudio_DefaultDevice.streamDescription);
505     status = AudioDeviceGetProperty(devId, 0, FALSE , kAudioDevicePropertyStreamFormat, &propertySize, &CoreAudio_DefaultDevice.streamDescription);
506     if (status != noErr) {
507         ERR("AudioHardwareGetProperty for kAudioDevicePropertyStreamFormat return %c%c%c%c\n", (char) (status >> 24),
508                                                                                                 (char) (status >> 16),
509                                                                                                 (char) (status >> 8),
510                                                                                                 (char) status);
511         return FALSE;
512     }
513     
514     TRACE("Device Stream Description mSampleRate : %f\n mFormatID : %c%c%c%c\n"
515             "mFormatFlags : %lX\n mBytesPerPacket : %lu\n mFramesPerPacket : %lu\n"
516             "mBytesPerFrame : %lu\n mChannelsPerFrame : %lu\n mBitsPerChannel : %lu\n",
517                                CoreAudio_DefaultDevice.streamDescription.mSampleRate,
518                                (char) (CoreAudio_DefaultDevice.streamDescription.mFormatID >> 24),
519                                (char) (CoreAudio_DefaultDevice.streamDescription.mFormatID >> 16),
520                                (char) (CoreAudio_DefaultDevice.streamDescription.mFormatID >> 8),
521                                (char) CoreAudio_DefaultDevice.streamDescription.mFormatID,
522                                CoreAudio_DefaultDevice.streamDescription.mFormatFlags,
523                                CoreAudio_DefaultDevice.streamDescription.mBytesPerPacket,
524                                CoreAudio_DefaultDevice.streamDescription.mFramesPerPacket,
525                                CoreAudio_DefaultDevice.streamDescription.mBytesPerFrame,
526                                CoreAudio_DefaultDevice.streamDescription.mChannelsPerFrame,
527                                CoreAudio_DefaultDevice.streamDescription.mBitsPerChannel);
528     
529     CoreAudio_DefaultDevice.out_caps.wMid = 0xcafe;
530     CoreAudio_DefaultDevice.out_caps.wPid = 0x0001;
531     
532     CoreAudio_DefaultDevice.out_caps.vDriverVersion = 0x0001;
533     CoreAudio_DefaultDevice.out_caps.dwFormats = 0x00000000;
534     CoreAudio_DefaultDevice.out_caps.wReserved1 = 0;
535     CoreAudio_DefaultDevice.out_caps.dwSupport = WAVECAPS_VOLUME;
536     CoreAudio_DefaultDevice.out_caps.dwSupport |= WAVECAPS_LRVOLUME;
537     
538     CoreAudio_DefaultDevice.out_caps.wChannels = 2;
539     CoreAudio_DefaultDevice.out_caps.dwFormats|= WAVE_FORMAT_4S16;
540     
541     return TRUE;
542 }
543
544 /******************************************************************
545 *               CoreAudio_WaveInit
546 *
547 * Initialize CoreAudio_DefaultDevice
548 */
549 LONG CoreAudio_WaveInit(void)
550 {
551     OSStatus status;
552     UInt32 propertySize;
553     int i;
554     CFStringRef  messageThreadPortName;
555     CFMessagePortRef port_ReceiveInMessageThread;
556     int inputSampleRate;
557
558     TRACE("()\n");
559     
560     /* number of sound cards */
561     AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices, &propertySize, NULL);
562     propertySize /= sizeof(AudioDeviceID);
563     TRACE("sound cards : %lu\n", propertySize);
564     
565     /* Get the output device */
566     propertySize = sizeof(CoreAudio_DefaultDevice.outputDeviceID);
567     status = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, &propertySize, &CoreAudio_DefaultDevice.outputDeviceID);
568     if (status) {
569         ERR("AudioHardwareGetProperty return %c%c%c%c for kAudioHardwarePropertyDefaultOutputDevice\n", (char) (status >> 24),
570                                                                                                 (char) (status >> 16),
571                                                                                                 (char) (status >> 8),
572                                                                                                 (char) status);
573         return DRV_FAILURE;
574     }
575     if (CoreAudio_DefaultDevice.outputDeviceID == kAudioDeviceUnknown) {
576         ERR("AudioHardwareGetProperty: CoreAudio_DefaultDevice.outputDeviceID == kAudioDeviceUnknown\n");
577         return DRV_FAILURE;
578     }
579     
580     if ( ! CoreAudio_GetDevCaps() )
581         return DRV_FAILURE;
582     
583     CoreAudio_DefaultDevice.interface_name=HeapAlloc(GetProcessHeap(),0,strlen(CoreAudio_DefaultDevice.dev_name)+1);
584     strcpy(CoreAudio_DefaultDevice.interface_name, CoreAudio_DefaultDevice.dev_name);
585     
586     for (i = 0; i < MAX_WAVEOUTDRV; ++i)
587     {
588         static const WCHAR wszWaveOutFormat[] =
589             {'C','o','r','e','A','u','d','i','o',' ','W','a','v','e','O','u','t',' ','%','d',0};
590
591         WOutDev[i].state = WINE_WS_CLOSED;
592         WOutDev[i].cadev = &CoreAudio_DefaultDevice; 
593         WOutDev[i].woID = i;
594         
595         memset(&WOutDev[i].caps, 0, sizeof(WOutDev[i].caps));
596         
597         WOutDev[i].caps.wMid = 0xcafe;  /* Manufac ID */
598         WOutDev[i].caps.wPid = 0x0001;  /* Product ID */
599         snprintfW(WOutDev[i].caps.szPname, sizeof(WOutDev[i].caps.szPname)/sizeof(WCHAR), wszWaveOutFormat, i);
600         snprintf(WOutDev[i].interface_name, sizeof(WOutDev[i].interface_name), "winecoreaudio: %d", i);
601         
602         WOutDev[i].caps.vDriverVersion = 0x0001;
603         WOutDev[i].caps.dwFormats = 0x00000000;
604         WOutDev[i].caps.dwSupport = WAVECAPS_VOLUME;
605         
606         WOutDev[i].caps.wChannels = 2;
607       /*  WOutDev[i].caps.dwSupport |= WAVECAPS_LRVOLUME; */ /* FIXME */
608         
609         WOutDev[i].caps.dwFormats |= WAVE_FORMAT_96M08;
610         WOutDev[i].caps.dwFormats |= WAVE_FORMAT_96S08;
611         WOutDev[i].caps.dwFormats |= WAVE_FORMAT_96M16;
612         WOutDev[i].caps.dwFormats |= WAVE_FORMAT_96S16;
613         WOutDev[i].caps.dwFormats |= WAVE_FORMAT_48M08;
614         WOutDev[i].caps.dwFormats |= WAVE_FORMAT_48S08;
615         WOutDev[i].caps.dwFormats |= WAVE_FORMAT_48M16;
616         WOutDev[i].caps.dwFormats |= WAVE_FORMAT_48S16;
617         WOutDev[i].caps.dwFormats |= WAVE_FORMAT_4M08;
618         WOutDev[i].caps.dwFormats |= WAVE_FORMAT_4S08; 
619         WOutDev[i].caps.dwFormats |= WAVE_FORMAT_4S16;
620         WOutDev[i].caps.dwFormats |= WAVE_FORMAT_4M16;
621         WOutDev[i].caps.dwFormats |= WAVE_FORMAT_2M08;
622         WOutDev[i].caps.dwFormats |= WAVE_FORMAT_2S08; 
623         WOutDev[i].caps.dwFormats |= WAVE_FORMAT_2M16;
624         WOutDev[i].caps.dwFormats |= WAVE_FORMAT_2S16;
625         WOutDev[i].caps.dwFormats |= WAVE_FORMAT_1M08;
626         WOutDev[i].caps.dwFormats |= WAVE_FORMAT_1S08;
627         WOutDev[i].caps.dwFormats |= WAVE_FORMAT_1M16;
628         WOutDev[i].caps.dwFormats |= WAVE_FORMAT_1S16;
629
630         WOutDev[i].lock = 0; /* initialize the mutex */
631     }
632
633     /* FIXME: implement sample rate conversion on input */
634     inputSampleRate = AudioUnit_GetInputDeviceSampleRate();
635
636     for (i = 0; i < MAX_WAVEINDRV; ++i)
637     {
638         static const WCHAR wszWaveInFormat[] =
639             {'C','o','r','e','A','u','d','i','o',' ','W','a','v','e','I','n',' ','%','d',0};
640
641         memset(&WInDev[i], 0, sizeof(WInDev[i]));
642         WInDev[i].wiID = i;
643
644         /* Establish preconditions for widOpen */
645         WInDev[i].state = WINE_WS_CLOSED;
646         WInDev[i].lock = 0; /* initialize the mutex */
647
648         /* Fill in capabilities.  widGetDevCaps can be called at any time. */
649         WInDev[i].caps.wMid = 0xcafe;   /* Manufac ID */
650         WInDev[i].caps.wPid = 0x0001;   /* Product ID */
651         WInDev[i].caps.vDriverVersion = 0x0001;
652
653         snprintfW(WInDev[i].caps.szPname, sizeof(WInDev[i].caps.szPname)/sizeof(WCHAR), wszWaveInFormat, i);
654         snprintf(WInDev[i].interface_name, sizeof(WInDev[i].interface_name), "winecoreaudio in: %d", i);
655
656         if (inputSampleRate == 96000)
657         {
658             WInDev[i].caps.dwFormats |= WAVE_FORMAT_96M08;
659             WInDev[i].caps.dwFormats |= WAVE_FORMAT_96S08;
660             WInDev[i].caps.dwFormats |= WAVE_FORMAT_96M16;
661             WInDev[i].caps.dwFormats |= WAVE_FORMAT_96S16;
662         }
663         if (inputSampleRate == 48000)
664         {
665             WInDev[i].caps.dwFormats |= WAVE_FORMAT_48M08;
666             WInDev[i].caps.dwFormats |= WAVE_FORMAT_48S08;
667             WInDev[i].caps.dwFormats |= WAVE_FORMAT_48M16;
668             WInDev[i].caps.dwFormats |= WAVE_FORMAT_48S16;
669         }
670         if (inputSampleRate == 44100)
671         {
672             WInDev[i].caps.dwFormats |= WAVE_FORMAT_4M08;
673             WInDev[i].caps.dwFormats |= WAVE_FORMAT_4S08;
674             WInDev[i].caps.dwFormats |= WAVE_FORMAT_4M16;
675             WInDev[i].caps.dwFormats |= WAVE_FORMAT_4S16;
676         }
677         if (inputSampleRate == 22050)
678         {
679             WInDev[i].caps.dwFormats |= WAVE_FORMAT_2M08;
680             WInDev[i].caps.dwFormats |= WAVE_FORMAT_2S08;
681             WInDev[i].caps.dwFormats |= WAVE_FORMAT_2M16;
682             WInDev[i].caps.dwFormats |= WAVE_FORMAT_2S16;
683         }
684         if (inputSampleRate == 11025)
685         {
686             WInDev[i].caps.dwFormats |= WAVE_FORMAT_1M08;
687             WInDev[i].caps.dwFormats |= WAVE_FORMAT_1S08;
688             WInDev[i].caps.dwFormats |= WAVE_FORMAT_1M16;
689             WInDev[i].caps.dwFormats |= WAVE_FORMAT_1S16;
690         }
691
692         WInDev[i].caps.wChannels = 2;
693     }
694
695     /* create mach messages handler */
696     srandomdev();
697     messageThreadPortName = CFStringCreateWithFormat(kCFAllocatorDefault, NULL,
698         CFSTR("WaveMessagePort.%d.%lu"), getpid(), (unsigned long)random());
699     if (!messageThreadPortName)
700     {
701         ERR("Can't create message thread port name\n");
702         return DRV_FAILURE;
703     }
704
705     port_ReceiveInMessageThread = CFMessagePortCreateLocal(kCFAllocatorDefault, messageThreadPortName,
706                                         &wodMessageHandler, NULL, NULL);
707     if (!port_ReceiveInMessageThread)
708     {
709         ERR("Can't create message thread local port\n");
710         CFRelease(messageThreadPortName);
711         return DRV_FAILURE;
712     }
713
714     Port_SendToMessageThread = CFMessagePortCreateRemote(kCFAllocatorDefault, messageThreadPortName);
715     CFRelease(messageThreadPortName);
716     if (!Port_SendToMessageThread)
717     {
718         ERR("Can't create port for sending to message thread\n");
719         CFRelease(port_ReceiveInMessageThread);
720         return DRV_FAILURE;
721     }
722
723     /* Cannot WAIT for any events because we are called from the loader (which has a lock on loading stuff) */
724     /* We might want to wait for this thread to be created -- but we cannot -- not here at least */
725     /* Instead track the thread so we can clean it up later */
726     if ( hThread )
727     {
728         ERR("Message thread already started -- expect problems\n");
729     }
730     hThread = CreateThread(NULL, 0, messageThread, (LPVOID)port_ReceiveInMessageThread, 0, NULL);
731     if ( !hThread )
732     {
733         ERR("Can't create message thread\n");
734         CFRelease(port_ReceiveInMessageThread);
735         CFRelease(Port_SendToMessageThread);
736         Port_SendToMessageThread = NULL;
737         return DRV_FAILURE;
738     }
739
740     /* The message thread is responsible for releasing port_ReceiveInMessageThread. */
741
742     return DRV_SUCCESS;
743 }
744
745 void CoreAudio_WaveRelease(void)
746 {
747     /* Stop CFRunLoop in messageThread */
748     TRACE("()\n");
749
750     if (!Port_SendToMessageThread)
751         return;
752
753     CFMessagePortSendRequest(Port_SendToMessageThread, kStopLoopMessage, NULL, 0.0, 0.0, NULL, NULL);
754     CFRelease(Port_SendToMessageThread);
755     Port_SendToMessageThread = NULL;
756
757     /* Wait for the thread to finish and clean it up */
758     /* This rids us of any quick start/shutdown driver crashes */
759     WaitForSingleObject(hThread, INFINITE);
760     CloseHandle(hThread);
761     hThread = NULL;
762 }
763
764 /*======================================================================*
765 *                  Low level WAVE OUT implementation                    *
766 *======================================================================*/
767
768 /**************************************************************************
769 *                       wodNotifyClient                 [internal]
770 */
771 static DWORD wodNotifyClient(WINE_WAVEOUT* wwo, WORD wMsg, DWORD dwParam1, DWORD dwParam2)
772 {
773     switch (wMsg) {
774         case WOM_OPEN:
775         case WOM_CLOSE:
776         case WOM_DONE:
777             if (wwo->wFlags != DCB_NULL &&
778                 !DriverCallback(wwo->waveDesc.dwCallback, wwo->wFlags,
779                                 (HDRVR)wwo->waveDesc.hWave, wMsg, wwo->waveDesc.dwInstance,
780                                 dwParam1, dwParam2))
781             {
782                 return MMSYSERR_ERROR;
783             }
784             break;
785         default:
786             return MMSYSERR_INVALPARAM;
787     }
788     return MMSYSERR_NOERROR;
789 }
790
791
792 /**************************************************************************
793 *                       wodGetDevCaps               [internal]
794 */
795 static DWORD wodGetDevCaps(WORD wDevID, LPWAVEOUTCAPSW lpCaps, DWORD dwSize)
796 {
797     TRACE("(%u, %p, %u);\n", wDevID, lpCaps, dwSize);
798     
799     if (lpCaps == NULL) return MMSYSERR_NOTENABLED;
800     
801     if (wDevID >= MAX_WAVEOUTDRV)
802     {
803         TRACE("MAX_WAVOUTDRV reached !\n");
804         return MMSYSERR_BADDEVICEID;
805     }
806     
807     TRACE("dwSupport=(0x%x), dwFormats=(0x%x)\n", WOutDev[wDevID].caps.dwSupport, WOutDev[wDevID].caps.dwFormats);
808     memcpy(lpCaps, &WOutDev[wDevID].caps, min(dwSize, sizeof(*lpCaps)));
809     return MMSYSERR_NOERROR;
810 }
811
812 /**************************************************************************
813 *                               wodOpen                         [internal]
814 */
815 static DWORD wodOpen(WORD wDevID, LPWAVEOPENDESC lpDesc, DWORD dwFlags)
816 {
817     WINE_WAVEOUT*       wwo;
818     DWORD               ret;
819     AudioStreamBasicDescription streamFormat;
820     AudioUnit           audioUnit = NULL;
821     BOOL                auInited  = FALSE;
822
823     TRACE("(%u, %p, %08x);\n", wDevID, lpDesc, dwFlags);
824     if (lpDesc == NULL)
825     {
826         WARN("Invalid Parameter !\n");
827         return MMSYSERR_INVALPARAM;
828     }
829     if (wDevID >= MAX_WAVEOUTDRV) {
830         TRACE("MAX_WAVOUTDRV reached !\n");
831         return MMSYSERR_BADDEVICEID;
832     }
833     
834     TRACE("Format: tag=%04X nChannels=%d nSamplesPerSec=%d wBitsPerSample=%d !\n",
835           lpDesc->lpFormat->wFormatTag, lpDesc->lpFormat->nChannels,
836           lpDesc->lpFormat->nSamplesPerSec, lpDesc->lpFormat->wBitsPerSample);
837     
838     if (!supportedFormat(lpDesc->lpFormat))
839     {
840         WARN("Bad format: tag=%04X nChannels=%d nSamplesPerSec=%d wBitsPerSample=%d !\n",
841              lpDesc->lpFormat->wFormatTag, lpDesc->lpFormat->nChannels,
842              lpDesc->lpFormat->nSamplesPerSec, lpDesc->lpFormat->wBitsPerSample);
843         return WAVERR_BADFORMAT;
844     }
845     
846     if (dwFlags & WAVE_FORMAT_QUERY)
847     {
848         TRACE("Query format: tag=%04X nChannels=%d nSamplesPerSec=%d !\n",
849               lpDesc->lpFormat->wFormatTag, lpDesc->lpFormat->nChannels,
850               lpDesc->lpFormat->nSamplesPerSec);
851         return MMSYSERR_NOERROR;
852     }
853
854     /* nBlockAlign and nAvgBytesPerSec are output variables for dsound */
855     if (lpDesc->lpFormat->nBlockAlign != lpDesc->lpFormat->nChannels*lpDesc->lpFormat->wBitsPerSample/8) {
856         lpDesc->lpFormat->nBlockAlign  = lpDesc->lpFormat->nChannels*lpDesc->lpFormat->wBitsPerSample/8;
857         WARN("Fixing nBlockAlign\n");
858     }
859     if (lpDesc->lpFormat->nAvgBytesPerSec!= lpDesc->lpFormat->nSamplesPerSec*lpDesc->lpFormat->nBlockAlign) {
860         lpDesc->lpFormat->nAvgBytesPerSec = lpDesc->lpFormat->nSamplesPerSec*lpDesc->lpFormat->nBlockAlign;
861         WARN("Fixing nAvgBytesPerSec\n");
862     }
863
864     /* We proceed in three phases:
865      * o Reserve the device for us, marking it as unavailable (not closed)
866      * o Create, configure, and start the Audio Unit.  To avoid deadlock,
867      *   this has to be done without holding wwo->lock.
868      * o If that was successful, finish setting up our device info and
869      *   mark the device as ready.
870      *   Otherwise, clean up and mark the device as available.
871      */
872     wwo = &WOutDev[wDevID];
873     if (!OSSpinLockTry(&wwo->lock))
874         return MMSYSERR_ALLOCATED;
875
876     if (wwo->state != WINE_WS_CLOSED)
877     {
878         OSSpinLockUnlock(&wwo->lock);
879         return MMSYSERR_ALLOCATED;
880     }
881
882     wwo->state = WINE_WS_OPENING;
883     wwo->audioUnit = NULL;
884     OSSpinLockUnlock(&wwo->lock);
885
886
887     if (!AudioUnit_CreateDefaultAudioUnit((void *) wwo, &audioUnit))
888     {
889         ERR("CoreAudio_CreateDefaultAudioUnit(%p) failed\n", wwo);
890         ret = MMSYSERR_ERROR;
891         goto error;
892     }
893
894     streamFormat.mFormatID = kAudioFormatLinearPCM;
895     streamFormat.mFormatFlags = kLinearPCMFormatFlagIsPacked;
896     /* FIXME check for 32bits float -> kLinearPCMFormatFlagIsFloat */
897     if (lpDesc->lpFormat->wBitsPerSample != 8)
898         streamFormat.mFormatFlags |= kLinearPCMFormatFlagIsSignedInteger;
899 # ifdef WORDS_BIGENDIAN
900     streamFormat.mFormatFlags |= kLinearPCMFormatFlagIsBigEndian; /* FIXME Wave format is little endian */
901 # endif
902
903     streamFormat.mSampleRate = lpDesc->lpFormat->nSamplesPerSec;
904     streamFormat.mChannelsPerFrame = lpDesc->lpFormat->nChannels;       
905     streamFormat.mFramesPerPacket = 1;  
906     streamFormat.mBitsPerChannel = lpDesc->lpFormat->wBitsPerSample;
907     streamFormat.mBytesPerFrame = streamFormat.mBitsPerChannel * streamFormat.mChannelsPerFrame / 8;    
908     streamFormat.mBytesPerPacket = streamFormat.mBytesPerFrame * streamFormat.mFramesPerPacket;         
909
910     ret = AudioUnit_InitializeWithStreamDescription(audioUnit, &streamFormat);
911     if (!ret) 
912     {
913         ret = WAVERR_BADFORMAT; /* FIXME return an error based on the OSStatus */
914         goto error;
915     }
916     auInited = TRUE;
917
918     /* Our render callback CoreAudio_woAudioUnitIOProc may be called before
919      * AudioOutputUnitStart returns.  Core Audio will grab its own internal
920      * lock before calling it and the callback grabs wwo->lock.  This would
921      * deadlock if we were holding wwo->lock.
922      * Also, the callback has to safely do nothing in that case, because
923      * wwo hasn't been completely filled out, yet. */
924     ret = AudioOutputUnitStart(audioUnit);
925     if (ret)
926     {
927         ERR("AudioOutputUnitStart failed: %08x\n", ret);
928         ret = MMSYSERR_ERROR; /* FIXME return an error based on the OSStatus */
929         goto error;
930     }
931
932
933     OSSpinLockLock(&wwo->lock);
934     assert(wwo->state == WINE_WS_OPENING);
935
936     wwo->audioUnit = audioUnit;
937     wwo->streamDescription = streamFormat;
938
939     wwo->state = WINE_WS_PLAYING;
940
941     wwo->wFlags = HIWORD(dwFlags & CALLBACK_TYPEMASK);
942
943     wwo->waveDesc = *lpDesc;
944     copyFormat(lpDesc->lpFormat, &wwo->format);
945     
946     wwo->dwPlayedTotal = 0;
947     wwo->dwWrittenTotal = 0;
948
949     wwo->trace_on = TRACE_ON(wave);
950     wwo->warn_on  = WARN_ON(wave);
951     wwo->err_on   = ERR_ON(wave);
952
953     OSSpinLockUnlock(&wwo->lock);
954     
955     ret = wodNotifyClient(wwo, WOM_OPEN, 0L, 0L);
956     
957     return ret;
958
959 error:
960     if (audioUnit)
961     {
962         if (auInited)
963             AudioUnitUninitialize(audioUnit);
964         AudioUnit_CloseAudioUnit(audioUnit);
965     }
966
967     OSSpinLockLock(&wwo->lock);
968     assert(wwo->state == WINE_WS_OPENING);
969     wwo->state = WINE_WS_CLOSED;
970     OSSpinLockUnlock(&wwo->lock);
971
972     return ret;
973 }
974
975 /**************************************************************************
976 *                               wodClose                        [internal]
977 */
978 static DWORD wodClose(WORD wDevID)
979 {
980     DWORD               ret = MMSYSERR_NOERROR;
981     WINE_WAVEOUT*       wwo;
982     
983     TRACE("(%u);\n", wDevID);
984     
985     if (wDevID >= MAX_WAVEOUTDRV)
986     {
987         WARN("bad device ID !\n");
988         return MMSYSERR_BADDEVICEID;
989     }
990     
991     wwo = &WOutDev[wDevID];
992     OSSpinLockLock(&wwo->lock);
993     if (wwo->lpQueuePtr)
994     {
995         WARN("buffers still playing !\n");
996         OSSpinLockUnlock(&wwo->lock);
997         ret = WAVERR_STILLPLAYING;
998     } else
999     {
1000         OSStatus err;
1001         AudioUnit audioUnit = wwo->audioUnit;
1002
1003         /* sanity check: this should not happen since the device must have been reset before */
1004         if (wwo->lpQueuePtr || wwo->lpPlayPtr) ERR("out of sync\n");
1005         
1006         wwo->state = WINE_WS_CLOSING; /* mark the device as closing */
1007         wwo->audioUnit = NULL;
1008         
1009         OSSpinLockUnlock(&wwo->lock);
1010
1011         err = AudioUnitUninitialize(audioUnit);
1012         if (err) {
1013             ERR("AudioUnitUninitialize return %c%c%c%c\n", (char) (err >> 24),
1014                                                             (char) (err >> 16),
1015                                                             (char) (err >> 8),
1016                                                             (char) err);
1017             return MMSYSERR_ERROR; /* FIXME return an error based on the OSStatus */
1018         }
1019         
1020         if ( !AudioUnit_CloseAudioUnit(audioUnit) )
1021         {
1022             ERR("Can't close AudioUnit\n");
1023             return MMSYSERR_ERROR; /* FIXME return an error based on the OSStatus */
1024         }  
1025         
1026         OSSpinLockLock(&wwo->lock);
1027         assert(wwo->state == WINE_WS_CLOSING);
1028         wwo->state = WINE_WS_CLOSED; /* mark the device as closed */
1029         OSSpinLockUnlock(&wwo->lock);
1030
1031         ret = wodNotifyClient(wwo, WOM_CLOSE, 0L, 0L);
1032     }
1033     
1034     return ret;
1035 }
1036
1037 /**************************************************************************
1038 *                               wodPrepare                      [internal]
1039 */
1040 static DWORD wodPrepare(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
1041 {
1042     TRACE("(%u, %p, %08x);\n", wDevID, lpWaveHdr, dwSize);
1043     
1044     if (wDevID >= MAX_WAVEOUTDRV) {
1045         WARN("bad device ID !\n");
1046         return MMSYSERR_BADDEVICEID;
1047     }
1048     
1049     if (lpWaveHdr->dwFlags & WHDR_INQUEUE)
1050         return WAVERR_STILLPLAYING;
1051     
1052     lpWaveHdr->dwFlags |= WHDR_PREPARED;
1053     lpWaveHdr->dwFlags &= ~WHDR_DONE;
1054
1055     return MMSYSERR_NOERROR;
1056 }
1057
1058 /**************************************************************************
1059 *                               wodUnprepare                    [internal]
1060 */
1061 static DWORD wodUnprepare(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
1062 {
1063     TRACE("(%u, %p, %08x);\n", wDevID, lpWaveHdr, dwSize);
1064     
1065     if (wDevID >= MAX_WAVEOUTDRV) {
1066         WARN("bad device ID !\n");
1067         return MMSYSERR_BADDEVICEID;
1068     }
1069     
1070     if (lpWaveHdr->dwFlags & WHDR_INQUEUE)
1071         return WAVERR_STILLPLAYING;
1072     
1073     lpWaveHdr->dwFlags &= ~WHDR_PREPARED;
1074     lpWaveHdr->dwFlags |= WHDR_DONE;
1075    
1076     return MMSYSERR_NOERROR;
1077 }
1078
1079
1080 /**************************************************************************
1081 *                               wodHelper_CheckForLoopBegin             [internal]
1082 *
1083 * Check if the new waveheader is the beginning of a loop, and set up
1084 * state if so.
1085 * This is called with the WAVEOUT lock held.
1086 * Call from AudioUnit IO thread can't use Wine debug channels.
1087 */
1088 static void wodHelper_CheckForLoopBegin(WINE_WAVEOUT* wwo)
1089 {
1090     LPWAVEHDR lpWaveHdr = wwo->lpPlayPtr;
1091
1092     if (lpWaveHdr->dwFlags & WHDR_BEGINLOOP)
1093     {
1094         if (wwo->lpLoopPtr)
1095         {
1096             if (wwo->warn_on)
1097                 fprintf(stderr, "warn:winecoreaudio:wodHelper_CheckForLoopBegin Already in a loop. Discarding loop on this header (%p)\n", lpWaveHdr);
1098         }
1099         else
1100         {
1101             if (wwo->trace_on)
1102                 fprintf(stderr, "trace:winecoreaudio:wodHelper_CheckForLoopBegin Starting loop (%dx) with %p\n", lpWaveHdr->dwLoops, lpWaveHdr);
1103
1104             wwo->lpLoopPtr = lpWaveHdr;
1105             /* Windows does not touch WAVEHDR.dwLoops,
1106                 * so we need to make an internal copy */
1107             wwo->dwLoops = lpWaveHdr->dwLoops;
1108         }
1109     }
1110 }
1111
1112
1113 /**************************************************************************
1114 *                               wodHelper_PlayPtrNext           [internal]
1115 *
1116 * Advance the play pointer to the next waveheader, looping if required.
1117 * This is called with the WAVEOUT lock held.
1118 * Call from AudioUnit IO thread can't use Wine debug channels.
1119 */
1120 static void wodHelper_PlayPtrNext(WINE_WAVEOUT* wwo)
1121 {
1122     BOOL didLoopBack = FALSE;
1123
1124     wwo->dwPartialOffset = 0;
1125     if ((wwo->lpPlayPtr->dwFlags & WHDR_ENDLOOP) && wwo->lpLoopPtr)
1126     {
1127         /* We're at the end of a loop, loop if required */
1128         if (wwo->dwLoops > 1)
1129         {
1130             wwo->dwLoops--;
1131             wwo->lpPlayPtr = wwo->lpLoopPtr;
1132             didLoopBack = TRUE;
1133         }
1134         else
1135         {
1136             wwo->lpLoopPtr = NULL;
1137         }
1138     }
1139     if (!didLoopBack)
1140     {
1141         /* We didn't loop back.  Advance to the next wave header */
1142         wwo->lpPlayPtr = wwo->lpPlayPtr->lpNext;
1143
1144         if (wwo->lpPlayPtr)
1145             wodHelper_CheckForLoopBegin(wwo);
1146     }
1147 }
1148
1149 /* Send the "done" notification for each WAVEHDR in a list.  The list must be
1150  * free-standing.  It should not be part of a device's queue.
1151  * This function must be called with the WAVEOUT lock *not* held.  Furthermore,
1152  * it does not lock it, itself.  That's because the callback to the application
1153  * may prompt the application to operate on the device, and we don't want to
1154  * deadlock.
1155  */
1156 static void wodHelper_NotifyDoneForList(WINE_WAVEOUT* wwo, LPWAVEHDR lpWaveHdr)
1157 {
1158     while (lpWaveHdr)
1159     {
1160         LPWAVEHDR lpNext = lpWaveHdr->lpNext;
1161
1162         lpWaveHdr->lpNext = NULL;
1163         lpWaveHdr->dwFlags &= ~WHDR_INQUEUE;
1164         lpWaveHdr->dwFlags |= WHDR_DONE;
1165         wodNotifyClient(wwo, WOM_DONE, (DWORD)lpWaveHdr, 0);
1166
1167         lpWaveHdr = lpNext;
1168     }
1169 }
1170
1171 /* if force is TRUE then notify the client that all the headers were completed
1172  */
1173 static void wodHelper_NotifyCompletions(WINE_WAVEOUT* wwo, BOOL force)
1174 {
1175     LPWAVEHDR lpFirstDoneWaveHdr = NULL;
1176
1177     OSSpinLockLock(&wwo->lock);
1178
1179     /* First, excise all of the done headers from the queue into
1180      * a free-standing list. */
1181     if (force)
1182     {
1183         lpFirstDoneWaveHdr = wwo->lpQueuePtr;
1184         wwo->lpQueuePtr = NULL;
1185     }
1186     else
1187     {
1188         LPWAVEHDR lpWaveHdr;
1189         LPWAVEHDR lpLastDoneWaveHdr = NULL;
1190
1191         /* Start from lpQueuePtr and keep notifying until:
1192             * - we hit an unwritten wavehdr
1193             * - we hit the beginning of a running loop
1194             * - we hit a wavehdr which hasn't finished playing
1195             */
1196         for (
1197             lpWaveHdr = wwo->lpQueuePtr;
1198             lpWaveHdr &&
1199                 lpWaveHdr != wwo->lpPlayPtr &&
1200                 lpWaveHdr != wwo->lpLoopPtr;
1201             lpWaveHdr = lpWaveHdr->lpNext
1202             )
1203         {
1204             if (!lpFirstDoneWaveHdr)
1205                 lpFirstDoneWaveHdr = lpWaveHdr;
1206             lpLastDoneWaveHdr = lpWaveHdr;
1207         }
1208
1209         if (lpLastDoneWaveHdr)
1210         {
1211             wwo->lpQueuePtr = lpLastDoneWaveHdr->lpNext;
1212             lpLastDoneWaveHdr->lpNext = NULL;
1213         }
1214     }
1215     
1216     OSSpinLockUnlock(&wwo->lock);
1217
1218     /* Now, send the "done" notification for each header in our list. */
1219     wodHelper_NotifyDoneForList(wwo, lpFirstDoneWaveHdr);
1220 }
1221
1222
1223 /**************************************************************************
1224 *                               wodWrite                        [internal]
1225
1226 */
1227 static DWORD wodWrite(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
1228 {
1229     LPWAVEHDR*wh;
1230     WINE_WAVEOUT *wwo;
1231     
1232     TRACE("(%u, %p, %08X);\n", wDevID, lpWaveHdr, dwSize);
1233     
1234     /* first, do the sanity checks... */
1235     if (wDevID >= MAX_WAVEOUTDRV)
1236     {
1237         WARN("bad dev ID !\n");
1238         return MMSYSERR_BADDEVICEID;
1239     }
1240     
1241     wwo = &WOutDev[wDevID];
1242     
1243     if (lpWaveHdr->lpData == NULL || !(lpWaveHdr->dwFlags & WHDR_PREPARED))
1244     {
1245         TRACE("unprepared\n");
1246         return WAVERR_UNPREPARED;
1247     }
1248     
1249     if (lpWaveHdr->dwFlags & WHDR_INQUEUE) 
1250     {
1251         TRACE("still playing\n");
1252         return WAVERR_STILLPLAYING;
1253     }
1254     
1255     lpWaveHdr->dwFlags &= ~WHDR_DONE;
1256     lpWaveHdr->dwFlags |= WHDR_INQUEUE;
1257     lpWaveHdr->lpNext = 0;
1258
1259     OSSpinLockLock(&wwo->lock);
1260     /* insert buffer at the end of queue */
1261     for (wh = &(wwo->lpQueuePtr); *wh; wh = &((*wh)->lpNext))
1262         /* Do nothing */;
1263     *wh = lpWaveHdr;
1264     
1265     if (!wwo->lpPlayPtr)
1266     {
1267         wwo->lpPlayPtr = lpWaveHdr;
1268
1269         wodHelper_CheckForLoopBegin(wwo);
1270
1271         wwo->dwPartialOffset = 0;
1272     }
1273     OSSpinLockUnlock(&wwo->lock);
1274
1275     return MMSYSERR_NOERROR;
1276 }
1277
1278 /**************************************************************************
1279 *                       wodPause                                [internal]
1280 */
1281 static DWORD wodPause(WORD wDevID)
1282 {
1283     OSStatus status;
1284
1285     TRACE("(%u);!\n", wDevID);
1286     
1287     if (wDevID >= MAX_WAVEOUTDRV)
1288     {
1289         WARN("bad device ID !\n");
1290         return MMSYSERR_BADDEVICEID;
1291     }
1292
1293     /* The order of the following operations is important since we can't hold
1294      * the mutex while we make an Audio Unit call.  Stop the Audio Unit before
1295      * setting the PAUSED state.  In wodRestart, the order is reversed.  This
1296      * guarantees that we can't get into a situation where the state is
1297      * PLAYING but the Audio Unit isn't running.  Although we can be in PAUSED
1298      * state with the Audio Unit still running, that's harmless because the
1299      * render callback will just produce silence.
1300      */
1301     status = AudioOutputUnitStop(WOutDev[wDevID].audioUnit);
1302     if (status) {
1303         WARN("AudioOutputUnitStop return %c%c%c%c\n",
1304              (char) (status >> 24), (char) (status >> 16), (char) (status >> 8), (char) status);
1305     }
1306
1307     OSSpinLockLock(&WOutDev[wDevID].lock);
1308     if (WOutDev[wDevID].state == WINE_WS_PLAYING)
1309         WOutDev[wDevID].state = WINE_WS_PAUSED;
1310     OSSpinLockUnlock(&WOutDev[wDevID].lock);
1311
1312     return MMSYSERR_NOERROR;
1313 }
1314
1315 /**************************************************************************
1316 *                       wodRestart                              [internal]
1317 */
1318 static DWORD wodRestart(WORD wDevID)
1319 {
1320     OSStatus status;
1321
1322     TRACE("(%u);\n", wDevID);
1323     
1324     if (wDevID >= MAX_WAVEOUTDRV )
1325     {
1326         WARN("bad device ID !\n");
1327         return MMSYSERR_BADDEVICEID;
1328     }
1329
1330     /* The order of the following operations is important since we can't hold
1331      * the mutex while we make an Audio Unit call.  Set the PLAYING
1332      * state before starting the Audio Unit.  In wodPause, the order is
1333      * reversed.  This guarantees that we can't get into a situation where
1334      * the state is PLAYING but the Audio Unit isn't running.
1335      * Although we can be in PAUSED state with the Audio Unit still running,
1336      * that's harmless because the render callback will just produce silence.
1337      */
1338     OSSpinLockLock(&WOutDev[wDevID].lock);
1339     if (WOutDev[wDevID].state == WINE_WS_PAUSED)
1340         WOutDev[wDevID].state = WINE_WS_PLAYING;
1341     OSSpinLockUnlock(&WOutDev[wDevID].lock);
1342
1343     status = AudioOutputUnitStart(WOutDev[wDevID].audioUnit);
1344     if (status) {
1345         ERR("AudioOutputUnitStart return %c%c%c%c\n",
1346             (char) (status >> 24), (char) (status >> 16), (char) (status >> 8), (char) status);
1347         return MMSYSERR_ERROR; /* FIXME return an error based on the OSStatus */
1348     }
1349
1350     return MMSYSERR_NOERROR;
1351 }
1352
1353 /**************************************************************************
1354 *                       wodReset                                [internal]
1355 */
1356 static DWORD wodReset(WORD wDevID)
1357 {
1358     WINE_WAVEOUT* wwo;
1359     OSStatus status;
1360     LPWAVEHDR lpSavedQueuePtr;
1361
1362     TRACE("(%u);\n", wDevID);
1363
1364     if (wDevID >= MAX_WAVEOUTDRV)
1365     {
1366         WARN("bad device ID !\n");
1367         return MMSYSERR_BADDEVICEID;
1368     }
1369
1370     wwo = &WOutDev[wDevID];
1371
1372     OSSpinLockLock(&wwo->lock);
1373
1374     if (wwo->state == WINE_WS_CLOSED || wwo->state == WINE_WS_CLOSING ||
1375         wwo->state == WINE_WS_OPENING)
1376     {
1377         OSSpinLockUnlock(&wwo->lock);
1378         WARN("resetting a closed device\n");
1379         return MMSYSERR_INVALHANDLE;
1380     }
1381
1382     lpSavedQueuePtr = wwo->lpQueuePtr;
1383     wwo->lpPlayPtr = wwo->lpQueuePtr = wwo->lpLoopPtr = NULL;
1384     wwo->state = WINE_WS_PLAYING;
1385     wwo->dwPlayedTotal = wwo->dwWrittenTotal = 0;
1386
1387     wwo->dwPartialOffset = 0;        /* Clear partial wavehdr */
1388
1389     OSSpinLockUnlock(&wwo->lock);
1390
1391     status = AudioOutputUnitStart(wwo->audioUnit);
1392
1393     if (status) {
1394         ERR( "AudioOutputUnitStart return %c%c%c%c\n",
1395              (char) (status >> 24), (char) (status >> 16), (char) (status >> 8), (char) status);
1396         return MMSYSERR_ERROR; /* FIXME return an error based on the OSStatus */
1397     }
1398
1399     /* Now, send the "done" notification for each header in our list. */
1400     /* Do this last so the reset operation is effectively complete before the
1401      * app does whatever it's going to do in response to these notifications. */
1402     wodHelper_NotifyDoneForList(wwo, lpSavedQueuePtr);
1403
1404     return MMSYSERR_NOERROR;
1405 }
1406
1407 /**************************************************************************
1408 *           wodBreakLoop                [internal]
1409 */
1410 static DWORD wodBreakLoop(WORD wDevID)
1411 {
1412     WINE_WAVEOUT* wwo;
1413
1414     TRACE("(%u);\n", wDevID);
1415
1416     if (wDevID >= MAX_WAVEOUTDRV)
1417     {
1418         WARN("bad device ID !\n");
1419         return MMSYSERR_BADDEVICEID;
1420     }
1421
1422     wwo = &WOutDev[wDevID];
1423
1424     OSSpinLockLock(&wwo->lock);
1425
1426     if (wwo->lpLoopPtr != NULL)
1427     {
1428         /* ensure exit at end of current loop */
1429         wwo->dwLoops = 1;
1430     }
1431
1432     OSSpinLockUnlock(&wwo->lock);
1433
1434     return MMSYSERR_NOERROR;
1435 }
1436
1437 /**************************************************************************
1438 *                               wodGetPosition                  [internal]
1439 */
1440 static DWORD wodGetPosition(WORD wDevID, LPMMTIME lpTime, DWORD uSize)
1441 {
1442     DWORD               val;
1443     WINE_WAVEOUT*       wwo;
1444
1445     TRACE("(%u, %p, %u);\n", wDevID, lpTime, uSize);
1446     
1447     if (wDevID >= MAX_WAVEOUTDRV)
1448     {
1449         WARN("bad device ID !\n");
1450         return MMSYSERR_BADDEVICEID;
1451     }
1452     
1453     /* if null pointer to time structure return error */
1454     if (lpTime == NULL) return MMSYSERR_INVALPARAM;
1455     
1456     wwo = &WOutDev[wDevID];
1457     
1458     OSSpinLockLock(&WOutDev[wDevID].lock);
1459     val = wwo->dwPlayedTotal;
1460     OSSpinLockUnlock(&WOutDev[wDevID].lock);
1461     
1462     return bytes_to_mmtime(lpTime, val, &wwo->format);
1463 }
1464
1465 /**************************************************************************
1466 *                               wodGetVolume                    [internal]
1467 */
1468 static DWORD wodGetVolume(WORD wDevID, LPDWORD lpdwVol)
1469 {
1470     float left;
1471     float right;
1472     
1473     if (wDevID >= MAX_WAVEOUTDRV)
1474     {
1475         WARN("bad device ID !\n");
1476         return MMSYSERR_BADDEVICEID;
1477     }    
1478     
1479     TRACE("(%u, %p);\n", wDevID, lpdwVol);
1480
1481     AudioUnit_GetVolume(WOutDev[wDevID].audioUnit, &left, &right); 
1482
1483     *lpdwVol = ((WORD) left * 0xFFFFl) + (((WORD) right * 0xFFFFl) << 16);
1484     
1485     return MMSYSERR_NOERROR;
1486 }
1487
1488 /**************************************************************************
1489 *                               wodSetVolume                    [internal]
1490 */
1491 static DWORD wodSetVolume(WORD wDevID, DWORD dwParam)
1492 {
1493     float left;
1494     float right;
1495     
1496     if (wDevID >= MAX_WAVEOUTDRV)
1497     {
1498         WARN("bad device ID !\n");
1499         return MMSYSERR_BADDEVICEID;
1500     }
1501
1502     left  = LOWORD(dwParam) / 65535.0f;
1503     right = HIWORD(dwParam) / 65535.0f;
1504     
1505     TRACE("(%u, %08x);\n", wDevID, dwParam);
1506
1507     AudioUnit_SetVolume(WOutDev[wDevID].audioUnit, left, right); 
1508
1509     return MMSYSERR_NOERROR;
1510 }
1511
1512 /**************************************************************************
1513 *                               wodGetNumDevs                   [internal]
1514 */
1515 static DWORD wodGetNumDevs(void)
1516 {
1517     TRACE("\n");
1518     return MAX_WAVEOUTDRV;
1519 }
1520
1521 /**************************************************************************
1522 *                              wodDevInterfaceSize             [internal]
1523 */
1524 static DWORD wodDevInterfaceSize(UINT wDevID, LPDWORD dwParam1)
1525 {
1526     TRACE("(%u, %p)\n", wDevID, dwParam1);
1527     
1528     *dwParam1 = MultiByteToWideChar(CP_UNIXCP, 0, WOutDev[wDevID].cadev->interface_name, -1,
1529                                     NULL, 0 ) * sizeof(WCHAR);
1530     return MMSYSERR_NOERROR;
1531 }
1532
1533 /**************************************************************************
1534 *                              wodDevInterface                 [internal]
1535 */
1536 static DWORD wodDevInterface(UINT wDevID, PWCHAR dwParam1, DWORD dwParam2)
1537 {
1538     TRACE("\n");
1539     if (dwParam2 >= MultiByteToWideChar(CP_UNIXCP, 0, WOutDev[wDevID].cadev->interface_name, -1,
1540                                         NULL, 0 ) * sizeof(WCHAR))
1541     {
1542         MultiByteToWideChar(CP_UNIXCP, 0, WOutDev[wDevID].cadev->interface_name, -1,
1543                             dwParam1, dwParam2 / sizeof(WCHAR));
1544         return MMSYSERR_NOERROR;
1545     }
1546     return MMSYSERR_INVALPARAM;
1547 }
1548
1549 /**************************************************************************
1550  *                              widDsCreate                     [internal]
1551  */
1552 static DWORD wodDsCreate(UINT wDevID, PIDSDRIVER* drv)
1553 {
1554     TRACE("(%d,%p)\n",wDevID,drv);
1555
1556     FIXME("DirectSound not implemented\n");
1557     FIXME("The (slower) DirectSound HEL mode will be used instead.\n");
1558     return MMSYSERR_NOTSUPPORTED;
1559 }
1560
1561 /**************************************************************************
1562 *                              wodDsDesc                 [internal]
1563 */
1564 static DWORD wodDsDesc(UINT wDevID, PDSDRIVERDESC desc)
1565 {
1566     /* The DirectSound HEL will automatically wrap a non-DirectSound-capable
1567      * driver in a DirectSound adaptor, thus allowing the driver to be used by
1568      * DirectSound clients.  However, it only does this if we respond
1569      * successfully to the DRV_QUERYDSOUNDDESC message.  It's enough to fill in
1570      * the driver and device names of the description output parameter. */
1571     *desc = WOutDev[wDevID].cadev->ds_desc;
1572     return MMSYSERR_NOERROR;
1573 }
1574
1575 /**************************************************************************
1576 *                               wodMessage (WINECOREAUDIO.7)
1577 */
1578 DWORD WINAPI CoreAudio_wodMessage(UINT wDevID, UINT wMsg, DWORD dwUser, 
1579                                   DWORD dwParam1, DWORD dwParam2)
1580 {
1581     TRACE("(%u, %s, %08x, %08x, %08x);\n",
1582           wDevID, getMessage(wMsg), dwUser, dwParam1, dwParam2);
1583     
1584     switch (wMsg) {
1585         case DRVM_INIT:
1586         case DRVM_EXIT:
1587         case DRVM_ENABLE:
1588         case DRVM_DISABLE:
1589             
1590             /* FIXME: Pretend this is supported */
1591             return 0;
1592         case WODM_OPEN:         return wodOpen(wDevID, (LPWAVEOPENDESC) dwParam1, dwParam2);          
1593         case WODM_CLOSE:        return wodClose(wDevID);
1594         case WODM_WRITE:        return wodWrite(wDevID, (LPWAVEHDR) dwParam1, dwParam2);
1595         case WODM_PAUSE:        return wodPause(wDevID);  
1596         case WODM_GETPOS:       return wodGetPosition(wDevID, (LPMMTIME) dwParam1, dwParam2);
1597         case WODM_BREAKLOOP:    return wodBreakLoop(wDevID);
1598         case WODM_PREPARE:      return wodPrepare(wDevID, (LPWAVEHDR)dwParam1, dwParam2);
1599         case WODM_UNPREPARE:    return wodUnprepare(wDevID, (LPWAVEHDR)dwParam1, dwParam2);
1600             
1601         case WODM_GETDEVCAPS:   return wodGetDevCaps(wDevID, (LPWAVEOUTCAPSW) dwParam1, dwParam2);
1602         case WODM_GETNUMDEVS:   return wodGetNumDevs();  
1603             
1604         case WODM_GETPITCH:         
1605         case WODM_SETPITCH:        
1606         case WODM_GETPLAYBACKRATE:      
1607         case WODM_SETPLAYBACKRATE:      return MMSYSERR_NOTSUPPORTED;
1608         case WODM_GETVOLUME:    return wodGetVolume(wDevID, (LPDWORD)dwParam1);
1609         case WODM_SETVOLUME:    return wodSetVolume(wDevID, dwParam1);
1610         case WODM_RESTART:      return wodRestart(wDevID);
1611         case WODM_RESET:        return wodReset(wDevID);
1612             
1613         case DRV_QUERYDEVICEINTERFACESIZE:  return wodDevInterfaceSize (wDevID, (LPDWORD)dwParam1);
1614         case DRV_QUERYDEVICEINTERFACE:      return wodDevInterface (wDevID, (PWCHAR)dwParam1, dwParam2);
1615         case DRV_QUERYDSOUNDIFACE:  return wodDsCreate  (wDevID, (PIDSDRIVER*)dwParam1);
1616         case DRV_QUERYDSOUNDDESC:   return wodDsDesc    (wDevID, (PDSDRIVERDESC)dwParam1);
1617             
1618         default:
1619             FIXME("unknown message %d!\n", wMsg);
1620     }
1621     
1622     return MMSYSERR_NOTSUPPORTED;
1623 }
1624
1625 /*======================================================================*
1626 *                  Low level DSOUND implementation                      *
1627 *======================================================================*/
1628
1629 typedef struct IDsDriverImpl IDsDriverImpl;
1630 typedef struct IDsDriverBufferImpl IDsDriverBufferImpl;
1631
1632 struct IDsDriverImpl
1633 {
1634     /* IUnknown fields */
1635     const IDsDriverVtbl *lpVtbl;
1636     DWORD               ref;
1637     /* IDsDriverImpl fields */
1638     UINT                wDevID;
1639     IDsDriverBufferImpl*primary;
1640 };
1641
1642 struct IDsDriverBufferImpl
1643 {
1644     /* IUnknown fields */
1645     const IDsDriverBufferVtbl *lpVtbl;
1646     DWORD ref;
1647     /* IDsDriverBufferImpl fields */
1648     IDsDriverImpl* drv;
1649     DWORD buflen;
1650 };
1651
1652
1653 /*
1654     CoreAudio IO threaded callback,
1655     we can't call Wine debug channels, critical section or anything using NtCurrentTeb here.
1656 */
1657 OSStatus CoreAudio_woAudioUnitIOProc(void *inRefCon, 
1658                                      AudioUnitRenderActionFlags *ioActionFlags, 
1659                                      const AudioTimeStamp *inTimeStamp, 
1660                                      UInt32 inBusNumber, 
1661                                      UInt32 inNumberFrames, 
1662                                      AudioBufferList *ioData)
1663 {
1664     UInt32 buffer;
1665     WINE_WAVEOUT *wwo = (WINE_WAVEOUT *) inRefCon;
1666     int needNotify = 0;
1667
1668     unsigned int dataNeeded = ioData->mBuffers[0].mDataByteSize;
1669     unsigned int dataProvided = 0;
1670
1671     OSSpinLockLock(&wwo->lock);
1672
1673     /* We might have been called before wwo has been completely filled out by
1674      * wodOpen, or while it's being closed in wodClose.  We have to do nothing
1675      * in that case.  The check of wwo->state below ensures that. */
1676     while (dataNeeded > 0 && wwo->state == WINE_WS_PLAYING && wwo->lpPlayPtr)
1677     {
1678         unsigned int available = wwo->lpPlayPtr->dwBufferLength - wwo->dwPartialOffset;
1679         unsigned int toCopy;
1680
1681         if (available >= dataNeeded)
1682             toCopy = dataNeeded;
1683         else
1684             toCopy = available;
1685
1686         if (toCopy > 0)
1687         {
1688             memcpy((char*)ioData->mBuffers[0].mData + dataProvided,
1689                 wwo->lpPlayPtr->lpData + wwo->dwPartialOffset, toCopy);
1690             wwo->dwPartialOffset += toCopy;
1691             wwo->dwPlayedTotal += toCopy;
1692             dataProvided += toCopy;
1693             dataNeeded -= toCopy;
1694             available -= toCopy;
1695         }
1696
1697         if (available == 0)
1698         {
1699             wodHelper_PlayPtrNext(wwo);
1700             needNotify = 1;
1701         }
1702     }
1703     ioData->mBuffers[0].mDataByteSize = dataProvided;
1704
1705     OSSpinLockUnlock(&wwo->lock);
1706
1707     /* We can't provide any more wave data.  Fill the rest with silence. */
1708     if (dataNeeded > 0)
1709     {
1710         if (!dataProvided)
1711             *ioActionFlags |= kAudioUnitRenderAction_OutputIsSilence;
1712         memset((char*)ioData->mBuffers[0].mData + dataProvided, 0, dataNeeded);
1713         dataProvided += dataNeeded;
1714         dataNeeded = 0;
1715     }
1716
1717     /* We only fill buffer 0.  Set any others that might be requested to 0. */
1718     for (buffer = 1; buffer < ioData->mNumberBuffers; buffer++)
1719     {
1720         memset(ioData->mBuffers[buffer].mData, 0, ioData->mBuffers[buffer].mDataByteSize);
1721     }
1722
1723     if (needNotify) wodSendNotifyCompletionsMessage(wwo);
1724     return noErr;
1725 }
1726
1727
1728 /*======================================================================*
1729  *                  Low level WAVE IN implementation                    *
1730  *======================================================================*/
1731
1732 /**************************************************************************
1733  *                      widNotifyClient                 [internal]
1734  */
1735 static DWORD widNotifyClient(WINE_WAVEIN* wwi, WORD wMsg, DWORD dwParam1, DWORD dwParam2)
1736 {
1737     TRACE("wMsg = 0x%04x dwParm1 = %04X dwParam2 = %04X\n", wMsg, dwParam1, dwParam2);
1738
1739     switch (wMsg)
1740     {
1741         case WIM_OPEN:
1742         case WIM_CLOSE:
1743         case WIM_DATA:
1744             if (wwi->wFlags != DCB_NULL &&
1745                 !DriverCallback(wwi->waveDesc.dwCallback, wwi->wFlags,
1746                                 (HDRVR)wwi->waveDesc.hWave, wMsg, wwi->waveDesc.dwInstance,
1747                                 dwParam1, dwParam2))
1748             {
1749                 WARN("can't notify client !\n");
1750                 return MMSYSERR_ERROR;
1751             }
1752             break;
1753         default:
1754             FIXME("Unknown callback message %u\n", wMsg);
1755             return MMSYSERR_INVALPARAM;
1756     }
1757     return MMSYSERR_NOERROR;
1758 }
1759
1760
1761 /**************************************************************************
1762  *                      widHelper_NotifyCompletions              [internal]
1763  */
1764 static void widHelper_NotifyCompletions(WINE_WAVEIN* wwi)
1765 {
1766     LPWAVEHDR       lpWaveHdr;
1767     LPWAVEHDR       lpFirstDoneWaveHdr = NULL;
1768     LPWAVEHDR       lpLastDoneWaveHdr = NULL;
1769
1770     OSSpinLockLock(&wwi->lock);
1771
1772     /* First, excise all of the done headers from the queue into
1773      * a free-standing list. */
1774
1775     /* Start from lpQueuePtr and keep notifying until:
1776         * - we hit an unfilled wavehdr
1777         * - we hit the end of the list
1778         */
1779     for (
1780         lpWaveHdr = wwi->lpQueuePtr;
1781         lpWaveHdr &&
1782             lpWaveHdr->dwBytesRecorded >= lpWaveHdr->dwBufferLength;
1783         lpWaveHdr = lpWaveHdr->lpNext
1784         )
1785     {
1786         if (!lpFirstDoneWaveHdr)
1787             lpFirstDoneWaveHdr = lpWaveHdr;
1788         lpLastDoneWaveHdr = lpWaveHdr;
1789     }
1790
1791     if (lpLastDoneWaveHdr)
1792     {
1793         wwi->lpQueuePtr = lpLastDoneWaveHdr->lpNext;
1794         lpLastDoneWaveHdr->lpNext = NULL;
1795     }
1796
1797     OSSpinLockUnlock(&wwi->lock);
1798
1799     /* Now, send the "done" notification for each header in our list. */
1800     lpWaveHdr = lpFirstDoneWaveHdr;
1801     while (lpWaveHdr)
1802     {
1803         LPWAVEHDR lpNext = lpWaveHdr->lpNext;
1804
1805         lpWaveHdr->lpNext = NULL;
1806         lpWaveHdr->dwFlags &= ~WHDR_INQUEUE;
1807         lpWaveHdr->dwFlags |= WHDR_DONE;
1808         widNotifyClient(wwi, WIM_DATA, (DWORD)lpWaveHdr, 0);
1809
1810         lpWaveHdr = lpNext;
1811     }
1812 }
1813
1814
1815 /**************************************************************************
1816  *                      widGetDevCaps                           [internal]
1817  */
1818 static DWORD widGetDevCaps(WORD wDevID, LPWAVEINCAPSW lpCaps, DWORD dwSize)
1819 {
1820     TRACE("(%u, %p, %u);\n", wDevID, lpCaps, dwSize);
1821
1822     if (lpCaps == NULL) return MMSYSERR_NOTENABLED;
1823
1824     if (wDevID >= MAX_WAVEINDRV)
1825     {
1826         TRACE("MAX_WAVEINDRV reached !\n");
1827         return MMSYSERR_BADDEVICEID;
1828     }
1829
1830     memcpy(lpCaps, &WInDev[wDevID].caps, min(dwSize, sizeof(*lpCaps)));
1831     return MMSYSERR_NOERROR;
1832 }
1833
1834
1835 /**************************************************************************
1836  *                    widHelper_DestroyAudioBufferList           [internal]
1837  * Convenience function to dispose of our audio buffers
1838  */
1839 static void widHelper_DestroyAudioBufferList(AudioBufferList* list)
1840 {
1841     if (list)
1842     {
1843         UInt32 i;
1844         for (i = 0; i < list->mNumberBuffers; i++)
1845         {
1846             if (list->mBuffers[i].mData)
1847                 HeapFree(GetProcessHeap(), 0, list->mBuffers[i].mData);
1848         }
1849         HeapFree(GetProcessHeap(), 0, list);
1850     }
1851 }
1852
1853
1854 #define AUDIOBUFFERLISTSIZE(numBuffers) (offsetof(AudioBufferList, mBuffers) + (numBuffers) * sizeof(AudioBuffer))
1855
1856 /**************************************************************************
1857  *                    widHelper_AllocateAudioBufferList          [internal]
1858  * Convenience function to allocate our audio buffers
1859  */
1860 static AudioBufferList* widHelper_AllocateAudioBufferList(UInt32 numChannels, UInt32 bitsPerChannel, UInt32 bufferFrames, BOOL interleaved)
1861 {
1862     UInt32                      numBuffers;
1863     UInt32                      channelsPerFrame;
1864     UInt32                      bytesPerFrame;
1865     UInt32                      bytesPerBuffer;
1866     AudioBufferList*            list;
1867     UInt32                      i;
1868
1869     if (interleaved)
1870     {
1871         /* For interleaved audio, we allocate one buffer for all channels. */
1872         numBuffers = 1;
1873         channelsPerFrame = numChannels;
1874     }
1875     else
1876     {
1877         numBuffers = numChannels;
1878         channelsPerFrame = 1;
1879     }
1880
1881     bytesPerFrame = bitsPerChannel * channelsPerFrame / 8;
1882     bytesPerBuffer = bytesPerFrame * bufferFrames;
1883
1884     list = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, AUDIOBUFFERLISTSIZE(numBuffers));
1885     if (list == NULL)
1886         return NULL;
1887
1888     list->mNumberBuffers = numBuffers;
1889     for (i = 0; i < numBuffers; ++i)
1890     {
1891         list->mBuffers[i].mNumberChannels = channelsPerFrame;
1892         list->mBuffers[i].mDataByteSize = bytesPerBuffer;
1893         list->mBuffers[i].mData = HeapAlloc(GetProcessHeap(), 0, bytesPerBuffer);
1894         if (list->mBuffers[i].mData == NULL)
1895         {
1896             widHelper_DestroyAudioBufferList(list);
1897             return NULL;
1898         }
1899     }
1900     return list;
1901 }
1902
1903
1904 /**************************************************************************
1905  *                              widOpen                         [internal]
1906  */
1907 static DWORD widOpen(WORD wDevID, LPWAVEOPENDESC lpDesc, DWORD dwFlags)
1908 {
1909     WINE_WAVEIN*    wwi;
1910     UInt32          frameCount;
1911
1912     TRACE("(%u, %p, %08X);\n", wDevID, lpDesc, dwFlags);
1913     if (lpDesc == NULL)
1914     {
1915         WARN("Invalid Parameter !\n");
1916         return MMSYSERR_INVALPARAM;
1917     }
1918     if (wDevID >= MAX_WAVEINDRV)
1919     {
1920         TRACE ("MAX_WAVEINDRV reached !\n");
1921         return MMSYSERR_BADDEVICEID;
1922     }
1923
1924     TRACE("Format: tag=%04X nChannels=%d nSamplesPerSec=%d wBitsPerSample=%d !\n",
1925           lpDesc->lpFormat->wFormatTag, lpDesc->lpFormat->nChannels,
1926           lpDesc->lpFormat->nSamplesPerSec, lpDesc->lpFormat->wBitsPerSample);
1927
1928     if (!supportedFormat(lpDesc->lpFormat) ||
1929         lpDesc->lpFormat->nSamplesPerSec != AudioUnit_GetInputDeviceSampleRate()
1930         )
1931     {
1932         WARN("Bad format: tag=%04X nChannels=%d nSamplesPerSec=%d wBitsPerSample=%d !\n",
1933              lpDesc->lpFormat->wFormatTag, lpDesc->lpFormat->nChannels,
1934              lpDesc->lpFormat->nSamplesPerSec, lpDesc->lpFormat->wBitsPerSample);
1935         return WAVERR_BADFORMAT;
1936     }
1937
1938     if (dwFlags & WAVE_FORMAT_QUERY)
1939     {
1940         TRACE("Query format: tag=%04X nChannels=%d nSamplesPerSec=%d !\n",
1941               lpDesc->lpFormat->wFormatTag, lpDesc->lpFormat->nChannels,
1942               lpDesc->lpFormat->nSamplesPerSec);
1943         return MMSYSERR_NOERROR;
1944     }
1945
1946     /* nBlockAlign and nAvgBytesPerSec are output variables for dsound */
1947     if (lpDesc->lpFormat->nBlockAlign != lpDesc->lpFormat->nChannels*lpDesc->lpFormat->wBitsPerSample/8) {
1948         lpDesc->lpFormat->nBlockAlign  = lpDesc->lpFormat->nChannels*lpDesc->lpFormat->wBitsPerSample/8;
1949         WARN("Fixing nBlockAlign\n");
1950     }
1951     if (lpDesc->lpFormat->nAvgBytesPerSec!= lpDesc->lpFormat->nSamplesPerSec*lpDesc->lpFormat->nBlockAlign) {
1952         lpDesc->lpFormat->nAvgBytesPerSec = lpDesc->lpFormat->nSamplesPerSec*lpDesc->lpFormat->nBlockAlign;
1953         WARN("Fixing nAvgBytesPerSec\n");
1954     }
1955
1956     wwi = &WInDev[wDevID];
1957     if (!OSSpinLockTry(&wwi->lock))
1958         return MMSYSERR_ALLOCATED;
1959
1960     if (wwi->state != WINE_WS_CLOSED)
1961     {
1962         OSSpinLockUnlock(&wwi->lock);
1963         return MMSYSERR_ALLOCATED;
1964     }
1965
1966     wwi->state = WINE_WS_STOPPED;
1967     wwi->wFlags = HIWORD(dwFlags & CALLBACK_TYPEMASK);
1968
1969     wwi->waveDesc = *lpDesc;
1970     copyFormat(lpDesc->lpFormat, &wwi->format);
1971
1972     wwi->dwTotalRecorded = 0;
1973
1974     wwi->trace_on = TRACE_ON(wave);
1975     wwi->warn_on  = WARN_ON(wave);
1976     wwi->err_on   = ERR_ON(wave);
1977
1978     if (!AudioUnit_CreateInputUnit(wwi, &wwi->audioUnit,
1979         wwi->format.wf.nChannels, wwi->format.wf.nSamplesPerSec,
1980         wwi->format.wBitsPerSample, &frameCount))
1981     {
1982         ERR("AudioUnit_CreateInputUnit failed\n");
1983         OSSpinLockUnlock(&wwi->lock);
1984         return MMSYSERR_ERROR;
1985     }
1986
1987     /* Allocate our audio buffers */
1988     wwi->bufferList = widHelper_AllocateAudioBufferList(wwi->format.wf.nChannels,
1989         wwi->format.wBitsPerSample, frameCount, TRUE);
1990     if (wwi->bufferList == NULL)
1991     {
1992         ERR("Failed to allocate buffer list\n");
1993         AudioUnitUninitialize(wwi->audioUnit);
1994         AudioUnit_CloseAudioUnit(wwi->audioUnit);
1995         OSSpinLockUnlock(&wwi->lock);
1996         return MMSYSERR_NOMEM;
1997     }
1998
1999     /* Keep a copy of the buffer list structure (but not the buffers themselves)
2000      * in case AudioUnitRender clobbers the original, as it won't to do. */
2001     wwi->bufferListCopy = HeapAlloc(GetProcessHeap(), 0, AUDIOBUFFERLISTSIZE(wwi->bufferList->mNumberBuffers));
2002     if (wwi->bufferListCopy == NULL)
2003     {
2004         ERR("Failed to allocate buffer list copy\n");
2005         widHelper_DestroyAudioBufferList(wwi->bufferList);
2006         AudioUnitUninitialize(wwi->audioUnit);
2007         AudioUnit_CloseAudioUnit(wwi->audioUnit);
2008         OSSpinLockUnlock(&wwi->lock);
2009         return MMSYSERR_NOMEM;
2010     }
2011     memcpy(wwi->bufferListCopy, wwi->bufferList, AUDIOBUFFERLISTSIZE(wwi->bufferList->mNumberBuffers));
2012
2013     OSSpinLockUnlock(&wwi->lock);
2014
2015     return widNotifyClient(wwi, WIM_OPEN, 0L, 0L);
2016 }
2017
2018
2019 /**************************************************************************
2020  *                              widClose                        [internal]
2021  */
2022 static DWORD widClose(WORD wDevID)
2023 {
2024     DWORD           ret = MMSYSERR_NOERROR;
2025     WINE_WAVEIN*    wwi;
2026     OSStatus        err;
2027
2028     TRACE("(%u);\n", wDevID);
2029
2030     if (wDevID >= MAX_WAVEINDRV)
2031     {
2032         WARN("bad device ID !\n");
2033         return MMSYSERR_BADDEVICEID;
2034     }
2035
2036     wwi = &WInDev[wDevID];
2037     OSSpinLockLock(&wwi->lock);
2038     if (wwi->state == WINE_WS_CLOSED || wwi->state == WINE_WS_CLOSING)
2039     {
2040         WARN("Device already closed.\n");
2041         ret = MMSYSERR_INVALHANDLE;
2042     }
2043     else if (wwi->lpQueuePtr)
2044     {
2045         WARN("Buffers in queue.\n");
2046         ret = WAVERR_STILLPLAYING;
2047     }
2048     else
2049     {
2050         wwi->state = WINE_WS_CLOSING;
2051     }
2052
2053     OSSpinLockUnlock(&wwi->lock);
2054
2055     if (ret != MMSYSERR_NOERROR)
2056         return ret;
2057
2058
2059     /* Clean up and close the audio unit.  This has to be done without
2060      * wwi->lock being held to avoid deadlock.  AudioUnitUninitialize will
2061      * grab an internal Core Audio lock while waiting for the device work
2062      * thread to exit.  Meanwhile the device work thread may be holding
2063      * that lock and trying to grab the wwi->lock in the callback. */
2064     err = AudioUnitUninitialize(wwi->audioUnit);
2065     if (err)
2066     {
2067         ERR("AudioUnitUninitialize return %c%c%c%c\n", (char) (err >> 24),
2068                                                        (char) (err >> 16),
2069                                                        (char) (err >> 8),
2070                                                        (char) err);
2071     }
2072
2073     if (!AudioUnit_CloseAudioUnit(wwi->audioUnit))
2074     {
2075         ERR("Can't close AudioUnit\n");
2076     }
2077
2078
2079     OSSpinLockLock(&wwi->lock);
2080     assert(wwi->state == WINE_WS_CLOSING);
2081
2082     /* Dellocate our audio buffers */
2083     widHelper_DestroyAudioBufferList(wwi->bufferList);
2084     wwi->bufferList = NULL;
2085     HeapFree(GetProcessHeap(), 0, wwi->bufferListCopy);
2086     wwi->bufferListCopy = NULL;
2087
2088     wwi->audioUnit = NULL;
2089     wwi->state = WINE_WS_CLOSED;
2090     OSSpinLockUnlock(&wwi->lock);
2091
2092     ret = widNotifyClient(wwi, WIM_CLOSE, 0L, 0L);
2093
2094     return ret;
2095 }
2096
2097
2098 /**************************************************************************
2099  *                              widAddBuffer            [internal]
2100  */
2101 static DWORD widAddBuffer(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
2102 {
2103     DWORD           ret = MMSYSERR_NOERROR;
2104     WINE_WAVEIN*    wwi;
2105
2106     TRACE("(%u, %p, %08X);\n", wDevID, lpWaveHdr, dwSize);
2107
2108     if (wDevID >= MAX_WAVEINDRV)
2109     {
2110         WARN("invalid device ID\n");
2111         return MMSYSERR_INVALHANDLE;
2112     }
2113     if (!(lpWaveHdr->dwFlags & WHDR_PREPARED))
2114     {
2115         TRACE("never been prepared !\n");
2116         return WAVERR_UNPREPARED;
2117     }
2118     if (lpWaveHdr->dwFlags & WHDR_INQUEUE)
2119     {
2120         TRACE("header already in use !\n");
2121         return WAVERR_STILLPLAYING;
2122     }
2123
2124     wwi = &WInDev[wDevID];
2125     OSSpinLockLock(&wwi->lock);
2126
2127     if (wwi->state == WINE_WS_CLOSED || wwi->state == WINE_WS_CLOSING)
2128     {
2129         WARN("Trying to add buffer to closed device.\n");
2130         ret = MMSYSERR_INVALHANDLE;
2131     }
2132     else
2133     {
2134         LPWAVEHDR* wh;
2135
2136         lpWaveHdr->dwFlags |= WHDR_INQUEUE;
2137         lpWaveHdr->dwFlags &= ~WHDR_DONE;
2138         lpWaveHdr->dwBytesRecorded = 0;
2139         lpWaveHdr->lpNext = NULL;
2140
2141         /* insert buffer at end of queue */
2142         for (wh = &(wwi->lpQueuePtr); *wh; wh = &((*wh)->lpNext))
2143             /* Do nothing */;
2144         *wh = lpWaveHdr;
2145     }
2146
2147     OSSpinLockUnlock(&wwi->lock);
2148
2149     return ret;
2150 }
2151
2152
2153 /**************************************************************************
2154  *                      widStart                                [internal]
2155  */
2156 static DWORD widStart(WORD wDevID)
2157 {
2158     DWORD           ret = MMSYSERR_NOERROR;
2159     WINE_WAVEIN*    wwi;
2160
2161     TRACE("(%u);\n", wDevID);
2162     if (wDevID >= MAX_WAVEINDRV)
2163     {
2164         WARN("invalid device ID\n");
2165         return MMSYSERR_INVALHANDLE;
2166     }
2167
2168     /* The order of the following operations is important since we can't hold
2169      * the mutex while we make an Audio Unit call.  Set the PLAYING state
2170      * before starting the Audio Unit.  In widStop, the order is reversed.
2171      * This guarantees that we can't get into a situation where the state is
2172      * PLAYING but the Audio Unit isn't running.  Although we can be in STOPPED
2173      * state with the Audio Unit still running, that's harmless because the
2174      * input callback will just throw away the sound data.
2175      */
2176     wwi = &WInDev[wDevID];
2177     OSSpinLockLock(&wwi->lock);
2178
2179     if (wwi->state == WINE_WS_CLOSED || wwi->state == WINE_WS_CLOSING)
2180     {
2181         WARN("Trying to start closed device.\n");
2182         ret = MMSYSERR_INVALHANDLE;
2183     }
2184     else
2185         wwi->state = WINE_WS_PLAYING;
2186
2187     OSSpinLockUnlock(&wwi->lock);
2188
2189     if (ret == MMSYSERR_NOERROR)
2190     {
2191         /* Start pulling for audio data */
2192         OSStatus err = AudioOutputUnitStart(wwi->audioUnit);
2193         if (err != noErr)
2194             ERR("Failed to start AU: %08lx\n", err);
2195
2196         TRACE("Recording started...\n");
2197     }
2198
2199     return ret;
2200 }
2201
2202
2203 /**************************************************************************
2204  *                      widStop                                 [internal]
2205  */
2206 static DWORD widStop(WORD wDevID)
2207 {
2208     DWORD           ret = MMSYSERR_NOERROR;
2209     WINE_WAVEIN*    wwi;
2210     WAVEHDR*        lpWaveHdr = NULL;
2211     OSStatus        err;
2212
2213     TRACE("(%u);\n", wDevID);
2214     if (wDevID >= MAX_WAVEINDRV)
2215     {
2216         WARN("invalid device ID\n");
2217         return MMSYSERR_INVALHANDLE;
2218     }
2219
2220     wwi = &WInDev[wDevID];
2221
2222     /* The order of the following operations is important since we can't hold
2223      * the mutex while we make an Audio Unit call.  Stop the Audio Unit before
2224      * setting the STOPPED state.  In widStart, the order is reversed.  This
2225      * guarantees that we can't get into a situation where the state is
2226      * PLAYING but the Audio Unit isn't running.  Although we can be in STOPPED
2227      * state with the Audio Unit still running, that's harmless because the
2228      * input callback will just throw away the sound data.
2229      */
2230     err = AudioOutputUnitStop(wwi->audioUnit);
2231     if (err != noErr)
2232         WARN("Failed to stop AU: %08lx\n", err);
2233
2234     TRACE("Recording stopped.\n");
2235
2236     OSSpinLockLock(&wwi->lock);
2237
2238     if (wwi->state == WINE_WS_CLOSED || wwi->state == WINE_WS_CLOSING)
2239     {
2240         WARN("Trying to stop closed device.\n");
2241         ret = MMSYSERR_INVALHANDLE;
2242     }
2243     else if (wwi->state != WINE_WS_STOPPED)
2244     {
2245         wwi->state = WINE_WS_STOPPED;
2246         /* If there's a buffer in progress, it's done.  Remove it from the
2247          * queue so that we can return it to the app, below. */
2248         if (wwi->lpQueuePtr)
2249         {
2250             lpWaveHdr = wwi->lpQueuePtr;
2251             wwi->lpQueuePtr = lpWaveHdr->lpNext;
2252         }
2253     }
2254
2255     OSSpinLockUnlock(&wwi->lock);
2256
2257     if (lpWaveHdr)
2258     {
2259         lpWaveHdr->lpNext = NULL;
2260         lpWaveHdr->dwFlags &= ~WHDR_INQUEUE;
2261         lpWaveHdr->dwFlags |= WHDR_DONE;
2262         widNotifyClient(wwi, WIM_DATA, (DWORD)lpWaveHdr, 0);
2263     }
2264
2265     return ret;
2266 }
2267
2268 /**************************************************************************
2269  *                      widGetPos                                 [internal]
2270  */
2271 static DWORD widGetPos(WORD wDevID, LPMMTIME lpTime, UINT size)
2272 {
2273     DWORD                   val;
2274     WINE_WAVEIN*    wwi;
2275
2276     TRACE("(%u);\n", wDevID);
2277     if (wDevID >= MAX_WAVEINDRV)
2278     {
2279         WARN("invalid device ID\n");
2280         return MMSYSERR_INVALHANDLE;
2281     }
2282
2283     wwi = &WInDev[wDevID];
2284
2285     OSSpinLockLock(&WInDev[wDevID].lock);
2286     val = wwi->dwTotalRecorded;
2287     OSSpinLockUnlock(&WInDev[wDevID].lock);
2288
2289     return bytes_to_mmtime(lpTime, val, &wwi->format);
2290 }
2291
2292 /**************************************************************************
2293  *                      widReset                                [internal]
2294  */
2295 static DWORD widReset(WORD wDevID)
2296 {
2297     DWORD           ret = MMSYSERR_NOERROR;
2298     WINE_WAVEIN*    wwi;
2299     WAVEHDR*        lpWaveHdr = NULL;
2300
2301     TRACE("(%u);\n", wDevID);
2302     if (wDevID >= MAX_WAVEINDRV)
2303     {
2304         WARN("invalid device ID\n");
2305         return MMSYSERR_INVALHANDLE;
2306     }
2307
2308     wwi = &WInDev[wDevID];
2309     OSSpinLockLock(&wwi->lock);
2310
2311     if (wwi->state == WINE_WS_CLOSED || wwi->state == WINE_WS_CLOSING)
2312     {
2313         WARN("Trying to reset a closed device.\n");
2314         ret = MMSYSERR_INVALHANDLE;
2315     }
2316     else
2317     {
2318         lpWaveHdr               = wwi->lpQueuePtr;
2319         wwi->lpQueuePtr         = NULL;
2320         wwi->state              = WINE_WS_STOPPED;
2321         wwi->dwTotalRecorded    = 0;
2322     }
2323
2324     OSSpinLockUnlock(&wwi->lock);
2325
2326     if (ret == MMSYSERR_NOERROR)
2327     {
2328         OSStatus err = AudioOutputUnitStop(wwi->audioUnit);
2329         if (err != noErr)
2330             WARN("Failed to stop AU: %08lx\n", err);
2331
2332         TRACE("Recording stopped.\n");
2333     }
2334
2335     while (lpWaveHdr)
2336     {
2337         WAVEHDR* lpNext = lpWaveHdr->lpNext;
2338
2339         lpWaveHdr->lpNext = NULL;
2340         lpWaveHdr->dwFlags &= ~WHDR_INQUEUE;
2341         lpWaveHdr->dwFlags |= WHDR_DONE;
2342         widNotifyClient(wwi, WIM_DATA, (DWORD)lpWaveHdr, 0);
2343
2344         lpWaveHdr = lpNext;
2345     }
2346
2347     return ret;
2348 }
2349
2350
2351 /**************************************************************************
2352  *                              widGetNumDevs                   [internal]
2353  */
2354 static DWORD widGetNumDevs(void)
2355 {
2356     return MAX_WAVEINDRV;
2357 }
2358
2359
2360 /**************************************************************************
2361  *                              widDevInterfaceSize             [internal]
2362  */
2363 static DWORD widDevInterfaceSize(UINT wDevID, LPDWORD dwParam1)
2364 {
2365     TRACE("(%u, %p)\n", wDevID, dwParam1);
2366
2367     *dwParam1 = MultiByteToWideChar(CP_UNIXCP, 0, WInDev[wDevID].interface_name, -1,
2368                                     NULL, 0 ) * sizeof(WCHAR);
2369     return MMSYSERR_NOERROR;
2370 }
2371
2372
2373 /**************************************************************************
2374  *                              widDevInterface                 [internal]
2375  */
2376 static DWORD widDevInterface(UINT wDevID, PWCHAR dwParam1, DWORD dwParam2)
2377 {
2378     if (dwParam2 >= MultiByteToWideChar(CP_UNIXCP, 0, WInDev[wDevID].interface_name, -1,
2379                                         NULL, 0 ) * sizeof(WCHAR))
2380     {
2381         MultiByteToWideChar(CP_UNIXCP, 0, WInDev[wDevID].interface_name, -1,
2382                             dwParam1, dwParam2 / sizeof(WCHAR));
2383         return MMSYSERR_NOERROR;
2384     }
2385     return MMSYSERR_INVALPARAM;
2386 }
2387
2388
2389 /**************************************************************************
2390  *                              widDsCreate                     [internal]
2391  */
2392 static DWORD widDsCreate(UINT wDevID, PIDSCDRIVER* drv)
2393 {
2394     TRACE("(%d,%p)\n",wDevID,drv);
2395
2396     FIXME("DirectSoundCapture not implemented\n");
2397     FIXME("The (slower) DirectSound HEL mode will be used instead.\n");
2398     return MMSYSERR_NOTSUPPORTED;
2399 }
2400
2401 /**************************************************************************
2402  *                              widDsDesc                       [internal]
2403  */
2404 static DWORD widDsDesc(UINT wDevID, PDSDRIVERDESC desc)
2405 {
2406     /* The DirectSound HEL will automatically wrap a non-DirectSound-capable
2407      * driver in a DirectSound adaptor, thus allowing the driver to be used by
2408      * DirectSound clients.  However, it only does this if we respond
2409      * successfully to the DRV_QUERYDSOUNDDESC message.  It's enough to fill in
2410      * the driver and device names of the description output parameter. */
2411     memset(desc, 0, sizeof(*desc));
2412     lstrcpynA(desc->szDrvname, "winecoreaudio.drv", sizeof(desc->szDrvname) - 1);
2413     lstrcpynA(desc->szDesc, WInDev[wDevID].interface_name, sizeof(desc->szDesc) - 1);
2414     return MMSYSERR_NOERROR;
2415 }
2416
2417
2418 /**************************************************************************
2419  *                              widMessage (WINECOREAUDIO.6)
2420  */
2421 DWORD WINAPI CoreAudio_widMessage(WORD wDevID, WORD wMsg, DWORD dwUser,
2422                             DWORD dwParam1, DWORD dwParam2)
2423 {
2424     TRACE("(%u, %04X, %08X, %08X, %08X);\n",
2425             wDevID, wMsg, dwUser, dwParam1, dwParam2);
2426
2427     switch (wMsg)
2428     {
2429         case DRVM_INIT:
2430         case DRVM_EXIT:
2431         case DRVM_ENABLE:
2432         case DRVM_DISABLE:
2433             /* FIXME: Pretend this is supported */
2434             return 0;
2435         case WIDM_OPEN:             return widOpen          (wDevID, (LPWAVEOPENDESC)dwParam1,  dwParam2);
2436         case WIDM_CLOSE:            return widClose         (wDevID);
2437         case WIDM_ADDBUFFER:        return widAddBuffer     (wDevID, (LPWAVEHDR)dwParam1,       dwParam2);
2438         case WIDM_PREPARE:          return MMSYSERR_NOTSUPPORTED;
2439         case WIDM_UNPREPARE:        return MMSYSERR_NOTSUPPORTED;
2440         case WIDM_GETDEVCAPS:       return widGetDevCaps    (wDevID, (LPWAVEINCAPSW)dwParam1,   dwParam2);
2441         case WIDM_GETNUMDEVS:       return widGetNumDevs    ();
2442         case WIDM_RESET:            return widReset         (wDevID);
2443         case WIDM_START:            return widStart         (wDevID);
2444         case WIDM_STOP:             return widStop          (wDevID);
2445         case WIDM_GETPOS:           return widGetPos        (wDevID, (LPMMTIME)dwParam1, (UINT)dwParam2  );
2446         case DRV_QUERYDEVICEINTERFACESIZE: return widDevInterfaceSize       (wDevID, (LPDWORD)dwParam1);
2447         case DRV_QUERYDEVICEINTERFACE:     return widDevInterface           (wDevID, (PWCHAR)dwParam1, dwParam2);
2448         case DRV_QUERYDSOUNDIFACE:  return widDsCreate   (wDevID, (PIDSCDRIVER*)dwParam1);
2449         case DRV_QUERYDSOUNDDESC:   return widDsDesc     (wDevID, (PDSDRIVERDESC)dwParam1);
2450         default:
2451             FIXME("unknown message %d!\n", wMsg);
2452     }
2453
2454     return MMSYSERR_NOTSUPPORTED;
2455 }
2456
2457
2458 OSStatus CoreAudio_wiAudioUnitIOProc(void *inRefCon,
2459                                      AudioUnitRenderActionFlags *ioActionFlags,
2460                                      const AudioTimeStamp *inTimeStamp,
2461                                      UInt32 inBusNumber,
2462                                      UInt32 inNumberFrames,
2463                                      AudioBufferList *ioData)
2464 {
2465     WINE_WAVEIN*    wwi = (WINE_WAVEIN*)inRefCon;
2466     OSStatus        err = noErr;
2467     BOOL            needNotify = FALSE;
2468     WAVEHDR*        lpStorePtr;
2469     unsigned int    dataToStore;
2470     unsigned int    dataStored = 0;
2471
2472
2473     if (wwi->trace_on)
2474         fprintf(stderr, "trace:wave:CoreAudio_wiAudioUnitIOProc (ioActionFlags = %08lx, "
2475             "inTimeStamp = { %f, %x%08x, %f, %x%08x, %08lx }, inBusNumber = %lu, inNumberFrames = %lu)\n",
2476             *ioActionFlags, inTimeStamp->mSampleTime, (DWORD)(inTimeStamp->mHostTime >>32),
2477             (DWORD)inTimeStamp->mHostTime, inTimeStamp->mRateScalar, (DWORD)(inTimeStamp->mWordClockTime >> 32),
2478             (DWORD)inTimeStamp->mWordClockTime, inTimeStamp->mFlags, inBusNumber, inNumberFrames);
2479
2480     /* Render into audio buffer */
2481     /* FIXME: implement sample rate conversion on input.  This will require
2482      * a different render strategy.  We'll need to buffer the sound data
2483      * received here and pass it off to an AUConverter in another thread. */
2484     err = AudioUnitRender(wwi->audioUnit, ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames, wwi->bufferList);
2485     if (err)
2486     {
2487         if (wwi->err_on)
2488             fprintf(stderr, "err:wave:CoreAudio_wiAudioUnitIOProc AudioUnitRender failed with error %li\n", err);
2489         return err;
2490     }
2491
2492     /* Copy from audio buffer to the wavehdrs */
2493     dataToStore = wwi->bufferList->mBuffers[0].mDataByteSize;
2494
2495     OSSpinLockLock(&wwi->lock);
2496
2497     lpStorePtr = wwi->lpQueuePtr;
2498
2499     /* We might have been called while the waveIn device is being closed in
2500      * widClose.  We have to do nothing in that case.  The check of wwi->state
2501      * below ensures that. */
2502     while (dataToStore > 0 && wwi->state == WINE_WS_PLAYING && lpStorePtr)
2503     {
2504         unsigned int room = lpStorePtr->dwBufferLength - lpStorePtr->dwBytesRecorded;
2505         unsigned int toCopy;
2506
2507         if (wwi->trace_on)
2508             fprintf(stderr, "trace:wave:CoreAudio_wiAudioUnitIOProc Looking to store %u bytes to wavehdr %p, which has room for %u\n",
2509                 dataToStore, lpStorePtr, room);
2510
2511         if (room >= dataToStore)
2512             toCopy = dataToStore;
2513         else
2514             toCopy = room;
2515
2516         if (toCopy > 0)
2517         {
2518             memcpy(lpStorePtr->lpData + lpStorePtr->dwBytesRecorded,
2519                 (char*)wwi->bufferList->mBuffers[0].mData + dataStored, toCopy);
2520             lpStorePtr->dwBytesRecorded += toCopy;
2521             wwi->dwTotalRecorded += toCopy;
2522             dataStored += toCopy;
2523             dataToStore -= toCopy;
2524             room -= toCopy;
2525         }
2526
2527         if (room == 0)
2528         {
2529             lpStorePtr = lpStorePtr->lpNext;
2530             needNotify = TRUE;
2531         }
2532     }
2533
2534     OSSpinLockUnlock(&wwi->lock);
2535
2536     /* Restore the audio buffer list structure from backup, in case
2537      * AudioUnitRender clobbered it.  (It modifies mDataByteSize and may even
2538      * give us a different mData buffer to avoid a copy.) */
2539     memcpy(wwi->bufferList, wwi->bufferListCopy, AUDIOBUFFERLISTSIZE(wwi->bufferList->mNumberBuffers));
2540
2541     if (needNotify) wodSendNotifyInputCompletionsMessage(wwi);
2542     return err;
2543 }
2544
2545 #else
2546
2547 /**************************************************************************
2548  *                              widMessage (WINECOREAUDIO.6)
2549  */
2550 DWORD WINAPI CoreAudio_widMessage(WORD wDevID, WORD wMsg, DWORD dwUser,
2551                             DWORD dwParam1, DWORD dwParam2)
2552 {
2553     FIXME("(%u, %04X, %08X, %08X, %08X): CoreAudio support not compiled into wine\n", wDevID, wMsg, dwUser, dwParam1, dwParam2);
2554     return MMSYSERR_NOTENABLED;
2555 }
2556
2557 /**************************************************************************
2558 *                               wodMessage (WINECOREAUDIO.7)
2559 */
2560 DWORD WINAPI CoreAudio_wodMessage(WORD wDevID, WORD wMsg, DWORD dwUser, 
2561                                   DWORD dwParam1, DWORD dwParam2)
2562 {
2563     FIXME("(%u, %04X, %08X, %08X, %08X): CoreAudio support not compiled into wine\n", wDevID, wMsg, dwUser, dwParam1, dwParam2);
2564     return MMSYSERR_NOTENABLED;
2565 }
2566
2567 #endif