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