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