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