0.8.0-alt1
[qemu] / qemu / audio / coreaudio.c
1 /*
2  * QEMU OS X CoreAudio audio driver
3  *
4  * Copyright (c) 2005 Mike Kronenberg
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  */
24
25 #include <CoreAudio/CoreAudio.h>
26 #include <string.h>             /* strerror */
27 #include <pthread.h>            /* pthread_X */
28
29 #include "vl.h"
30
31 #define AUDIO_CAP "coreaudio"
32 #include "audio_int.h"
33
34 struct {
35     int buffer_frames;
36     int nbuffers;
37     int isAtexit;
38 } conf = {
39     .buffer_frames = 512,
40     .nbuffers = 4,
41     .isAtexit = 0
42 };
43
44 typedef struct coreaudioVoiceOut {
45     HWVoiceOut hw;
46     pthread_mutex_t mutex;
47     int isAtexit;
48     AudioDeviceID outputDeviceID;
49     UInt32 audioDevicePropertyBufferFrameSize;
50     AudioStreamBasicDescription outputStreamBasicDescription;
51     int live;
52     int decr;
53     int rpos;
54 } coreaudioVoiceOut;
55
56 static void coreaudio_logstatus (OSStatus status)
57 {
58     char *str = "BUG";
59
60     switch(status) {
61     case kAudioHardwareNoError:
62         str = "kAudioHardwareNoError";
63         break;
64
65     case kAudioHardwareNotRunningError:
66         str = "kAudioHardwareNotRunningError";
67         break;
68
69     case kAudioHardwareUnspecifiedError:
70         str = "kAudioHardwareUnspecifiedError";
71         break;
72
73     case kAudioHardwareUnknownPropertyError:
74         str = "kAudioHardwareUnknownPropertyError";
75         break;
76
77     case kAudioHardwareBadPropertySizeError:
78         str = "kAudioHardwareBadPropertySizeError";
79         break;
80
81     case kAudioHardwareIllegalOperationError:
82         str = "kAudioHardwareIllegalOperationError";
83         break;
84
85     case kAudioHardwareBadDeviceError:
86         str = "kAudioHardwareBadDeviceError";
87         break;
88
89     case kAudioHardwareBadStreamError:
90         str = "kAudioHardwareBadStreamError";
91         break;
92
93     case kAudioHardwareUnsupportedOperationError:
94         str = "kAudioHardwareUnsupportedOperationError";
95         break;
96
97     case kAudioDeviceUnsupportedFormatError:
98         str = "kAudioDeviceUnsupportedFormatError";
99         break;
100
101     case kAudioDevicePermissionsError:
102         str = "kAudioDevicePermissionsError";
103         break;
104
105     default:
106         AUD_log (AUDIO_CAP, "Reason: status code %ld\n", status);
107         return;
108     }
109
110     AUD_log (AUDIO_CAP, "Reason: %s\n", str);
111 }
112
113 static void GCC_FMT_ATTR (2, 3) coreaudio_logerr (
114     OSStatus status,
115     const char *fmt,
116     ...
117     )
118 {
119     va_list ap;
120
121     va_start (ap, fmt);
122     AUD_log (AUDIO_CAP, fmt, ap);
123     va_end (ap);
124
125     coreaudio_logstatus (status);
126 }
127
128 static void GCC_FMT_ATTR (3, 4) coreaudio_logerr2 (
129     OSStatus status,
130     const char *typ,
131     const char *fmt,
132     ...
133     )
134 {
135     va_list ap;
136
137     AUD_log (AUDIO_CAP, "Could not initialize %s\n", typ);
138
139     va_start (ap, fmt);
140     AUD_vlog (AUDIO_CAP, fmt, ap);
141     va_end (ap);
142
143     coreaudio_logstatus (status);
144 }
145
146 static inline UInt32 isPlaying (AudioDeviceID outputDeviceID)
147 {
148     OSStatus status;
149     UInt32 result = 0;
150     UInt32 propertySize = sizeof(outputDeviceID);
151     status = AudioDeviceGetProperty(
152         outputDeviceID, 0, 0,
153         kAudioDevicePropertyDeviceIsRunning, &propertySize, &result);
154     if (status != kAudioHardwareNoError) {
155         coreaudio_logerr(status,
156                          "Could not determine whether Device is playing\n");
157     }
158     return result;
159 }
160
161 static void coreaudio_atexit (void)
162 {
163     conf.isAtexit = 1;
164 }
165
166 static int coreaudio_lock (coreaudioVoiceOut *core, const char *fn_name)
167 {
168     int err;
169
170     err = pthread_mutex_lock (&core->mutex);
171     if (err) {
172         dolog ("Could not lock voice for %s\nReason: %s\n",
173                fn_name, strerror (err));
174         return -1;
175     }
176     return 0;
177 }
178
179 static int coreaudio_unlock (coreaudioVoiceOut *core, const char *fn_name)
180 {
181     int err;
182
183     err = pthread_mutex_unlock (&core->mutex);
184     if (err) {
185         dolog ("Could not unlock voice for %s\nReason: %s\n",
186                fn_name, strerror (err));
187         return -1;
188     }
189     return 0;
190 }
191
192 static int coreaudio_run_out (HWVoiceOut *hw)
193 {
194     int live, decr;
195     coreaudioVoiceOut *core = (coreaudioVoiceOut *) hw;
196
197     if (coreaudio_lock (core, "coreaudio_run_out")) {
198         return 0;
199     }
200
201     live = audio_pcm_hw_get_live_out (hw);
202
203     if (core->decr > live) {
204         ldebug ("core->decr %d live %d core->live %d\n",
205                 core->decr,
206                 live,
207                 core->live);
208     }
209
210     decr = audio_MIN (core->decr, live);
211     core->decr -= decr;
212
213     core->live = live - decr;
214     hw->rpos = core->rpos;
215
216     coreaudio_unlock (core, "coreaudio_run_out");
217     return decr;
218 }
219
220 /* callback to feed audiooutput buffer */
221 static OSStatus audioDeviceIOProc(
222     AudioDeviceID inDevice,
223     const AudioTimeStamp* inNow,
224     const AudioBufferList* inInputData,
225     const AudioTimeStamp* inInputTime,
226     AudioBufferList* outOutputData,
227     const AudioTimeStamp* inOutputTime,
228     void* hwptr)
229 {
230     UInt32 frame, frameCount;
231     float *out = outOutputData->mBuffers[0].mData;
232     HWVoiceOut *hw = hwptr;
233     coreaudioVoiceOut *core = (coreaudioVoiceOut *) hwptr;
234     int rpos, live;
235     st_sample_t *src;
236 #ifndef FLOAT_MIXENG
237 #ifdef RECIPROCAL
238     const float scale = 1.f / UINT_MAX;
239 #else
240     const float scale = UINT_MAX;
241 #endif
242 #endif
243
244     if (coreaudio_lock (core, "audioDeviceIOProc")) {
245         inInputTime = 0;
246         return 0;
247     }
248
249     frameCount = core->audioDevicePropertyBufferFrameSize;
250     live = core->live;
251
252     /* if there are not enough samples, set signal and return */
253     if (live < frameCount) {
254         inInputTime = 0;
255         coreaudio_unlock (core, "audioDeviceIOProc(empty)");
256         return 0;
257     }
258
259     rpos = core->rpos;
260     src = hw->mix_buf + rpos;
261
262     /* fill buffer */
263     for (frame = 0; frame < frameCount; frame++) {
264 #ifdef FLOAT_MIXENG
265         *out++ = src[frame].l; /* left channel */
266         *out++ = src[frame].r; /* right channel */
267 #else
268 #ifdef RECIPROCAL
269         *out++ = src[frame].l * scale; /* left channel */
270         *out++ = src[frame].r * scale; /* right channel */
271 #else
272         *out++ = src[frame].l / scale; /* left channel */
273         *out++ = src[frame].r / scale; /* right channel */
274 #endif
275 #endif
276     }
277
278     /* cleanup */
279     mixeng_clear (src, frameCount);
280     rpos = (rpos + frameCount) % hw->samples;
281     core->decr += frameCount;
282     core->rpos = rpos;
283
284     coreaudio_unlock (core, "audioDeviceIOProc");
285     return 0;
286 }
287
288 static int coreaudio_write (SWVoiceOut *sw, void *buf, int len)
289 {
290     return audio_pcm_sw_write (sw, buf, len);
291 }
292
293 static int coreaudio_init_out (HWVoiceOut *hw, audsettings_t *as)
294 {
295     OSStatus status;
296     coreaudioVoiceOut *core = (coreaudioVoiceOut *) hw;
297     UInt32 propertySize;
298     int err;
299     int bits = 8;
300     int endianess = 0;
301     const char *typ = "playback";
302     AudioValueRange frameRange;
303
304     /* create mutex */
305     err = pthread_mutex_init(&core->mutex, NULL);
306     if (err) {
307         dolog("Could not create mutex\nReason: %s\n", strerror (err));
308         return -1;
309     }
310
311     if (as->fmt == AUD_FMT_S16 || as->fmt == AUD_FMT_U16) {
312         bits = 16;
313         endianess = 1;
314     }
315
316     audio_pcm_init_info (
317         &hw->info,
318         as,
319         /* Following is irrelevant actually since we do not use
320            mixengs clipping routines */
321         audio_need_to_swap_endian (endianess)
322         );
323
324     /* open default output device */
325     propertySize = sizeof(core->outputDeviceID);
326     status = AudioHardwareGetProperty(
327         kAudioHardwarePropertyDefaultOutputDevice,
328         &propertySize,
329         &core->outputDeviceID);
330     if (status != kAudioHardwareNoError) {
331         coreaudio_logerr2 (status, typ,
332                            "Could not get default output Device\n");
333         return -1;
334     }
335     if (core->outputDeviceID == kAudioDeviceUnknown) {
336         dolog ("Could not initialize %s - Unknown Audiodevice\n", typ);
337         return -1;
338     }
339
340     /* get minimum and maximum buffer frame sizes */
341     propertySize = sizeof(frameRange);
342     status = AudioDeviceGetProperty(
343         core->outputDeviceID,
344         0,
345         0,
346         kAudioDevicePropertyBufferFrameSizeRange,
347         &propertySize,
348         &frameRange);
349     if (status != kAudioHardwareNoError) {
350         coreaudio_logerr2 (status, typ,
351                            "Could not get device buffer frame range\n");
352         return -1;
353     }
354
355     if (frameRange.mMinimum > conf.buffer_frames) {
356         core->audioDevicePropertyBufferFrameSize = (UInt32) frameRange.mMinimum;
357         dolog ("warning: Upsizing Buffer Frames to %f\n", frameRange.mMinimum);
358     }
359     else if (frameRange.mMaximum < conf.buffer_frames) {
360         core->audioDevicePropertyBufferFrameSize = (UInt32) frameRange.mMaximum;
361         dolog ("warning: Downsizing Buffer Frames to %f\n", frameRange.mMaximum);
362     }
363     else {
364         core->audioDevicePropertyBufferFrameSize = conf.buffer_frames;
365     }
366
367     /* set Buffer Frame Size */
368     propertySize = sizeof(core->audioDevicePropertyBufferFrameSize);
369     status = AudioDeviceSetProperty(
370         core->outputDeviceID,
371         NULL,
372         0,
373         false,
374         kAudioDevicePropertyBufferFrameSize,
375         propertySize,
376         &core->audioDevicePropertyBufferFrameSize);
377     if (status != kAudioHardwareNoError) {
378         coreaudio_logerr2 (status, typ,
379                            "Could not set device buffer frame size %ld\n",
380                            core->audioDevicePropertyBufferFrameSize);
381         return -1;
382     }
383
384     /* get Buffer Frame Size */
385     propertySize = sizeof(core->audioDevicePropertyBufferFrameSize);
386     status = AudioDeviceGetProperty(
387         core->outputDeviceID,
388         0,
389         false,
390         kAudioDevicePropertyBufferFrameSize,
391         &propertySize,
392         &core->audioDevicePropertyBufferFrameSize);
393     if (status != kAudioHardwareNoError) {
394         coreaudio_logerr2 (status, typ,
395                            "Could not get device buffer frame size\n");
396         return -1;
397     }
398     hw->samples = conf.nbuffers * core->audioDevicePropertyBufferFrameSize;
399
400     /* get StreamFormat */
401     propertySize = sizeof(core->outputStreamBasicDescription);
402     status = AudioDeviceGetProperty(
403         core->outputDeviceID,
404         0,
405         false,
406         kAudioDevicePropertyStreamFormat,
407         &propertySize,
408         &core->outputStreamBasicDescription);
409     if (status != kAudioHardwareNoError) {
410         coreaudio_logerr2 (status, typ,
411                            "Could not get Device Stream properties\n");
412         core->outputDeviceID = kAudioDeviceUnknown;
413         return -1;
414     }
415
416     /* set Samplerate */
417     core->outputStreamBasicDescription.mSampleRate = (Float64) as->freq;
418     propertySize = sizeof(core->outputStreamBasicDescription);
419     status = AudioDeviceSetProperty(
420         core->outputDeviceID,
421         0,
422         0,
423         0,
424         kAudioDevicePropertyStreamFormat,
425         propertySize,
426         &core->outputStreamBasicDescription);
427     if (status != kAudioHardwareNoError) {
428         coreaudio_logerr2 (status, typ, "Could not set samplerate %d\n",
429                            as->freq);
430         core->outputDeviceID = kAudioDeviceUnknown;
431         return -1;
432     }
433
434     /* set Callback */
435     status = AudioDeviceAddIOProc(core->outputDeviceID, audioDeviceIOProc, hw);
436     if (status != kAudioHardwareNoError) {
437         coreaudio_logerr2 (status, typ, "Could not set IOProc\n");
438         core->outputDeviceID = kAudioDeviceUnknown;
439         return -1;
440     }
441
442     /* start Playback */
443     if (!isPlaying(core->outputDeviceID)) {
444         status = AudioDeviceStart(core->outputDeviceID, audioDeviceIOProc);
445         if (status != kAudioHardwareNoError) {
446             coreaudio_logerr2 (status, typ, "Could not start playback\n");
447             AudioDeviceRemoveIOProc(core->outputDeviceID, audioDeviceIOProc);
448             core->outputDeviceID = kAudioDeviceUnknown;
449             return -1;
450         }
451     }
452
453     return 0;
454 }
455
456 static void coreaudio_fini_out (HWVoiceOut *hw)
457 {
458     OSStatus status;
459     int err;
460     coreaudioVoiceOut *core = (coreaudioVoiceOut *) hw;
461
462     if (!conf.isAtexit) {
463         /* stop playback */
464         if (isPlaying(core->outputDeviceID)) {
465             status = AudioDeviceStop(core->outputDeviceID, audioDeviceIOProc);
466             if (status != kAudioHardwareNoError) {
467                 coreaudio_logerr (status, "Could not stop playback\n");
468             }
469         }
470
471         /* remove callback */
472         status = AudioDeviceRemoveIOProc(core->outputDeviceID,
473                                          audioDeviceIOProc);
474         if (status != kAudioHardwareNoError) {
475             coreaudio_logerr (status, "Could not remove IOProc\n");
476         }
477     }
478     core->outputDeviceID = kAudioDeviceUnknown;
479
480     /* destroy mutex */
481     err = pthread_mutex_destroy(&core->mutex);
482     if (err) {
483         dolog("Could not destroy mutex\nReason: %s\n", strerror (err));
484     }
485 }
486
487 static int coreaudio_ctl_out (HWVoiceOut *hw, int cmd, ...)
488 {
489     OSStatus status;
490     coreaudioVoiceOut *core = (coreaudioVoiceOut *) hw;
491
492     switch (cmd) {
493     case VOICE_ENABLE:
494         /* start playback */
495         if (!isPlaying(core->outputDeviceID)) {
496             status = AudioDeviceStart(core->outputDeviceID, audioDeviceIOProc);
497             if (status != kAudioHardwareNoError) {
498                 coreaudio_logerr (status, "Could not resume playback\n");
499             }
500         }
501         break;
502
503     case VOICE_DISABLE:
504         /* stop playback */
505         if (!conf.isAtexit) {
506             if (isPlaying(core->outputDeviceID)) {
507                 status = AudioDeviceStop(core->outputDeviceID, audioDeviceIOProc);
508                 if (status != kAudioHardwareNoError) {
509                     coreaudio_logerr (status, "Could not pause playback\n");
510                 }
511             }
512         }
513         break;
514     }
515     return 0;
516 }
517
518 static void *coreaudio_audio_init (void)
519 {
520     atexit(coreaudio_atexit);
521     return &coreaudio_audio_init;
522 }
523
524 static void coreaudio_audio_fini (void *opaque)
525 {
526     (void) opaque;
527 }
528
529 static struct audio_option coreaudio_options[] = {
530     {"BUFFER_SIZE", AUD_OPT_INT, &conf.buffer_frames,
531      "Size of the buffer in frames", NULL, 0},
532     {"BUFFER_COUNT", AUD_OPT_INT, &conf.nbuffers,
533      "Number of buffers", NULL, 0},
534     {NULL, 0, NULL, NULL, NULL, 0}
535 };
536
537 static struct audio_pcm_ops coreaudio_pcm_ops = {
538     coreaudio_init_out,
539     coreaudio_fini_out,
540     coreaudio_run_out,
541     coreaudio_write,
542     coreaudio_ctl_out,
543
544     NULL,
545     NULL,
546     NULL,
547     NULL,
548     NULL
549 };
550
551 struct audio_driver coreaudio_audio_driver = {
552     INIT_FIELD (name           = ) "coreaudio",
553     INIT_FIELD (descr          = )
554     "CoreAudio http://developer.apple.com/audio/coreaudio.html",
555     INIT_FIELD (options        = ) coreaudio_options,
556     INIT_FIELD (init           = ) coreaudio_audio_init,
557     INIT_FIELD (fini           = ) coreaudio_audio_fini,
558     INIT_FIELD (pcm_ops        = ) &coreaudio_pcm_ops,
559     INIT_FIELD (can_be_default = ) 1,
560     INIT_FIELD (max_voices_out = ) 1,
561     INIT_FIELD (max_voices_in  = ) 0,
562     INIT_FIELD (voice_size_out = ) sizeof (coreaudioVoiceOut),
563     INIT_FIELD (voice_size_in  = ) 0
564 };