riscv: sifive_u: Update model and compatible strings in device tree
[qemu/ar7.git] / audio / coreaudio.c
blobd1be58b40aa82f17317504f989761c8afdb38e7b
1 /*
2 * QEMU OS X CoreAudio audio driver
4 * Copyright (c) 2005 Mike Kronenberg
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:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
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.
25 #include "qemu/osdep.h"
26 #include <CoreAudio/CoreAudio.h>
27 #include <pthread.h> /* pthread_X */
29 #include "qemu/module.h"
30 #include "audio.h"
32 #define AUDIO_CAP "coreaudio"
33 #include "audio_int.h"
35 #ifndef MAC_OS_X_VERSION_10_6
36 #define MAC_OS_X_VERSION_10_6 1060
37 #endif
39 typedef struct coreaudioVoiceOut {
40 HWVoiceOut hw;
41 pthread_mutex_t mutex;
42 AudioDeviceID outputDeviceID;
43 UInt32 audioDevicePropertyBufferFrameSize;
44 AudioStreamBasicDescription outputStreamBasicDescription;
45 AudioDeviceIOProcID ioprocid;
46 size_t live;
47 size_t decr;
48 size_t rpos;
49 } coreaudioVoiceOut;
51 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
52 /* The APIs used here only become available from 10.6 */
54 static OSStatus coreaudio_get_voice(AudioDeviceID *id)
56 UInt32 size = sizeof(*id);
57 AudioObjectPropertyAddress addr = {
58 kAudioHardwarePropertyDefaultOutputDevice,
59 kAudioObjectPropertyScopeGlobal,
60 kAudioObjectPropertyElementMaster
63 return AudioObjectGetPropertyData(kAudioObjectSystemObject,
64 &addr,
66 NULL,
67 &size,
68 id);
71 static OSStatus coreaudio_get_framesizerange(AudioDeviceID id,
72 AudioValueRange *framerange)
74 UInt32 size = sizeof(*framerange);
75 AudioObjectPropertyAddress addr = {
76 kAudioDevicePropertyBufferFrameSizeRange,
77 kAudioDevicePropertyScopeOutput,
78 kAudioObjectPropertyElementMaster
81 return AudioObjectGetPropertyData(id,
82 &addr,
84 NULL,
85 &size,
86 framerange);
89 static OSStatus coreaudio_get_framesize(AudioDeviceID id, UInt32 *framesize)
91 UInt32 size = sizeof(*framesize);
92 AudioObjectPropertyAddress addr = {
93 kAudioDevicePropertyBufferFrameSize,
94 kAudioDevicePropertyScopeOutput,
95 kAudioObjectPropertyElementMaster
98 return AudioObjectGetPropertyData(id,
99 &addr,
101 NULL,
102 &size,
103 framesize);
106 static OSStatus coreaudio_set_framesize(AudioDeviceID id, UInt32 *framesize)
108 UInt32 size = sizeof(*framesize);
109 AudioObjectPropertyAddress addr = {
110 kAudioDevicePropertyBufferFrameSize,
111 kAudioDevicePropertyScopeOutput,
112 kAudioObjectPropertyElementMaster
115 return AudioObjectSetPropertyData(id,
116 &addr,
118 NULL,
119 size,
120 framesize);
123 static OSStatus coreaudio_get_streamformat(AudioDeviceID id,
124 AudioStreamBasicDescription *d)
126 UInt32 size = sizeof(*d);
127 AudioObjectPropertyAddress addr = {
128 kAudioDevicePropertyStreamFormat,
129 kAudioDevicePropertyScopeOutput,
130 kAudioObjectPropertyElementMaster
133 return AudioObjectGetPropertyData(id,
134 &addr,
136 NULL,
137 &size,
141 static OSStatus coreaudio_set_streamformat(AudioDeviceID id,
142 AudioStreamBasicDescription *d)
144 UInt32 size = sizeof(*d);
145 AudioObjectPropertyAddress addr = {
146 kAudioDevicePropertyStreamFormat,
147 kAudioDevicePropertyScopeOutput,
148 kAudioObjectPropertyElementMaster
151 return AudioObjectSetPropertyData(id,
152 &addr,
154 NULL,
155 size,
159 static OSStatus coreaudio_get_isrunning(AudioDeviceID id, UInt32 *result)
161 UInt32 size = sizeof(*result);
162 AudioObjectPropertyAddress addr = {
163 kAudioDevicePropertyDeviceIsRunning,
164 kAudioDevicePropertyScopeOutput,
165 kAudioObjectPropertyElementMaster
168 return AudioObjectGetPropertyData(id,
169 &addr,
171 NULL,
172 &size,
173 result);
175 #else
176 /* Legacy versions of functions using deprecated APIs */
178 static OSStatus coreaudio_get_voice(AudioDeviceID *id)
180 UInt32 size = sizeof(*id);
182 return AudioHardwareGetProperty(
183 kAudioHardwarePropertyDefaultOutputDevice,
184 &size,
185 id);
188 static OSStatus coreaudio_get_framesizerange(AudioDeviceID id,
189 AudioValueRange *framerange)
191 UInt32 size = sizeof(*framerange);
193 return AudioDeviceGetProperty(
197 kAudioDevicePropertyBufferFrameSizeRange,
198 &size,
199 framerange);
202 static OSStatus coreaudio_get_framesize(AudioDeviceID id, UInt32 *framesize)
204 UInt32 size = sizeof(*framesize);
206 return AudioDeviceGetProperty(
209 false,
210 kAudioDevicePropertyBufferFrameSize,
211 &size,
212 framesize);
215 static OSStatus coreaudio_set_framesize(AudioDeviceID id, UInt32 *framesize)
217 UInt32 size = sizeof(*framesize);
219 return AudioDeviceSetProperty(
221 NULL,
223 false,
224 kAudioDevicePropertyBufferFrameSize,
225 size,
226 framesize);
229 static OSStatus coreaudio_get_streamformat(AudioDeviceID id,
230 AudioStreamBasicDescription *d)
232 UInt32 size = sizeof(*d);
234 return AudioDeviceGetProperty(
237 false,
238 kAudioDevicePropertyStreamFormat,
239 &size,
243 static OSStatus coreaudio_set_streamformat(AudioDeviceID id,
244 AudioStreamBasicDescription *d)
246 UInt32 size = sizeof(*d);
248 return AudioDeviceSetProperty(
253 kAudioDevicePropertyStreamFormat,
254 size,
258 static OSStatus coreaudio_get_isrunning(AudioDeviceID id, UInt32 *result)
260 UInt32 size = sizeof(*result);
262 return AudioDeviceGetProperty(
266 kAudioDevicePropertyDeviceIsRunning,
267 &size,
268 result);
270 #endif
272 static void coreaudio_logstatus (OSStatus status)
274 const char *str = "BUG";
276 switch(status) {
277 case kAudioHardwareNoError:
278 str = "kAudioHardwareNoError";
279 break;
281 case kAudioHardwareNotRunningError:
282 str = "kAudioHardwareNotRunningError";
283 break;
285 case kAudioHardwareUnspecifiedError:
286 str = "kAudioHardwareUnspecifiedError";
287 break;
289 case kAudioHardwareUnknownPropertyError:
290 str = "kAudioHardwareUnknownPropertyError";
291 break;
293 case kAudioHardwareBadPropertySizeError:
294 str = "kAudioHardwareBadPropertySizeError";
295 break;
297 case kAudioHardwareIllegalOperationError:
298 str = "kAudioHardwareIllegalOperationError";
299 break;
301 case kAudioHardwareBadDeviceError:
302 str = "kAudioHardwareBadDeviceError";
303 break;
305 case kAudioHardwareBadStreamError:
306 str = "kAudioHardwareBadStreamError";
307 break;
309 case kAudioHardwareUnsupportedOperationError:
310 str = "kAudioHardwareUnsupportedOperationError";
311 break;
313 case kAudioDeviceUnsupportedFormatError:
314 str = "kAudioDeviceUnsupportedFormatError";
315 break;
317 case kAudioDevicePermissionsError:
318 str = "kAudioDevicePermissionsError";
319 break;
321 default:
322 AUD_log (AUDIO_CAP, "Reason: status code %" PRId32 "\n", (int32_t)status);
323 return;
326 AUD_log (AUDIO_CAP, "Reason: %s\n", str);
329 static void GCC_FMT_ATTR (2, 3) coreaudio_logerr (
330 OSStatus status,
331 const char *fmt,
335 va_list ap;
337 va_start (ap, fmt);
338 AUD_log (AUDIO_CAP, fmt, ap);
339 va_end (ap);
341 coreaudio_logstatus (status);
344 static void GCC_FMT_ATTR (3, 4) coreaudio_logerr2 (
345 OSStatus status,
346 const char *typ,
347 const char *fmt,
351 va_list ap;
353 AUD_log (AUDIO_CAP, "Could not initialize %s\n", typ);
355 va_start (ap, fmt);
356 AUD_vlog (AUDIO_CAP, fmt, ap);
357 va_end (ap);
359 coreaudio_logstatus (status);
362 static inline UInt32 isPlaying (AudioDeviceID outputDeviceID)
364 OSStatus status;
365 UInt32 result = 0;
366 status = coreaudio_get_isrunning(outputDeviceID, &result);
367 if (status != kAudioHardwareNoError) {
368 coreaudio_logerr(status,
369 "Could not determine whether Device is playing\n");
371 return result;
374 static int coreaudio_lock (coreaudioVoiceOut *core, const char *fn_name)
376 int err;
378 err = pthread_mutex_lock (&core->mutex);
379 if (err) {
380 dolog ("Could not lock voice for %s\nReason: %s\n",
381 fn_name, strerror (err));
382 return -1;
384 return 0;
387 static int coreaudio_unlock (coreaudioVoiceOut *core, const char *fn_name)
389 int err;
391 err = pthread_mutex_unlock (&core->mutex);
392 if (err) {
393 dolog ("Could not unlock voice for %s\nReason: %s\n",
394 fn_name, strerror (err));
395 return -1;
397 return 0;
400 static size_t coreaudio_run_out(HWVoiceOut *hw, size_t live)
402 size_t decr;
403 coreaudioVoiceOut *core = (coreaudioVoiceOut *) hw;
405 if (coreaudio_lock (core, "coreaudio_run_out")) {
406 return 0;
409 if (core->decr > live) {
410 ldebug ("core->decr %d live %d core->live %d\n",
411 core->decr,
412 live,
413 core->live);
416 decr = MIN (core->decr, live);
417 core->decr -= decr;
419 core->live = live - decr;
420 hw->rpos = core->rpos;
422 coreaudio_unlock (core, "coreaudio_run_out");
423 return decr;
426 /* callback to feed audiooutput buffer */
427 static OSStatus audioDeviceIOProc(
428 AudioDeviceID inDevice,
429 const AudioTimeStamp* inNow,
430 const AudioBufferList* inInputData,
431 const AudioTimeStamp* inInputTime,
432 AudioBufferList* outOutputData,
433 const AudioTimeStamp* inOutputTime,
434 void* hwptr)
436 UInt32 frame, frameCount;
437 float *out = outOutputData->mBuffers[0].mData;
438 HWVoiceOut *hw = hwptr;
439 coreaudioVoiceOut *core = (coreaudioVoiceOut *) hwptr;
440 int rpos, live;
441 struct st_sample *src;
442 #ifndef FLOAT_MIXENG
443 #ifdef RECIPROCAL
444 const float scale = 1.f / UINT_MAX;
445 #else
446 const float scale = UINT_MAX;
447 #endif
448 #endif
450 if (coreaudio_lock (core, "audioDeviceIOProc")) {
451 inInputTime = 0;
452 return 0;
455 frameCount = core->audioDevicePropertyBufferFrameSize;
456 live = core->live;
458 /* if there are not enough samples, set signal and return */
459 if (live < frameCount) {
460 inInputTime = 0;
461 coreaudio_unlock (core, "audioDeviceIOProc(empty)");
462 return 0;
465 rpos = core->rpos;
466 src = hw->mix_buf + rpos;
468 /* fill buffer */
469 for (frame = 0; frame < frameCount; frame++) {
470 #ifdef FLOAT_MIXENG
471 *out++ = src[frame].l; /* left channel */
472 *out++ = src[frame].r; /* right channel */
473 #else
474 #ifdef RECIPROCAL
475 *out++ = src[frame].l * scale; /* left channel */
476 *out++ = src[frame].r * scale; /* right channel */
477 #else
478 *out++ = src[frame].l / scale; /* left channel */
479 *out++ = src[frame].r / scale; /* right channel */
480 #endif
481 #endif
484 rpos = (rpos + frameCount) % hw->samples;
485 core->decr += frameCount;
486 core->rpos = rpos;
488 coreaudio_unlock (core, "audioDeviceIOProc");
489 return 0;
492 static int coreaudio_init_out(HWVoiceOut *hw, struct audsettings *as,
493 void *drv_opaque)
495 OSStatus status;
496 coreaudioVoiceOut *core = (coreaudioVoiceOut *) hw;
497 int err;
498 const char *typ = "playback";
499 AudioValueRange frameRange;
500 Audiodev *dev = drv_opaque;
501 AudiodevCoreaudioPerDirectionOptions *cpdo = dev->u.coreaudio.out;
502 int frames;
504 /* create mutex */
505 err = pthread_mutex_init(&core->mutex, NULL);
506 if (err) {
507 dolog("Could not create mutex\nReason: %s\n", strerror (err));
508 return -1;
511 audio_pcm_init_info (&hw->info, as);
513 status = coreaudio_get_voice(&core->outputDeviceID);
514 if (status != kAudioHardwareNoError) {
515 coreaudio_logerr2 (status, typ,
516 "Could not get default output Device\n");
517 return -1;
519 if (core->outputDeviceID == kAudioDeviceUnknown) {
520 dolog ("Could not initialize %s - Unknown Audiodevice\n", typ);
521 return -1;
524 /* get minimum and maximum buffer frame sizes */
525 status = coreaudio_get_framesizerange(core->outputDeviceID,
526 &frameRange);
527 if (status != kAudioHardwareNoError) {
528 coreaudio_logerr2 (status, typ,
529 "Could not get device buffer frame range\n");
530 return -1;
533 frames = audio_buffer_frames(
534 qapi_AudiodevCoreaudioPerDirectionOptions_base(cpdo), as, 11610);
535 if (frameRange.mMinimum > frames) {
536 core->audioDevicePropertyBufferFrameSize = (UInt32) frameRange.mMinimum;
537 dolog ("warning: Upsizing Buffer Frames to %f\n", frameRange.mMinimum);
538 } else if (frameRange.mMaximum < frames) {
539 core->audioDevicePropertyBufferFrameSize = (UInt32) frameRange.mMaximum;
540 dolog ("warning: Downsizing Buffer Frames to %f\n", frameRange.mMaximum);
542 else {
543 core->audioDevicePropertyBufferFrameSize = frames;
546 /* set Buffer Frame Size */
547 status = coreaudio_set_framesize(core->outputDeviceID,
548 &core->audioDevicePropertyBufferFrameSize);
549 if (status != kAudioHardwareNoError) {
550 coreaudio_logerr2 (status, typ,
551 "Could not set device buffer frame size %" PRIu32 "\n",
552 (uint32_t)core->audioDevicePropertyBufferFrameSize);
553 return -1;
556 /* get Buffer Frame Size */
557 status = coreaudio_get_framesize(core->outputDeviceID,
558 &core->audioDevicePropertyBufferFrameSize);
559 if (status != kAudioHardwareNoError) {
560 coreaudio_logerr2 (status, typ,
561 "Could not get device buffer frame size\n");
562 return -1;
564 hw->samples = (cpdo->has_buffer_count ? cpdo->buffer_count : 4) *
565 core->audioDevicePropertyBufferFrameSize;
567 /* get StreamFormat */
568 status = coreaudio_get_streamformat(core->outputDeviceID,
569 &core->outputStreamBasicDescription);
570 if (status != kAudioHardwareNoError) {
571 coreaudio_logerr2 (status, typ,
572 "Could not get Device Stream properties\n");
573 core->outputDeviceID = kAudioDeviceUnknown;
574 return -1;
577 /* set Samplerate */
578 core->outputStreamBasicDescription.mSampleRate = (Float64) as->freq;
579 status = coreaudio_set_streamformat(core->outputDeviceID,
580 &core->outputStreamBasicDescription);
581 if (status != kAudioHardwareNoError) {
582 coreaudio_logerr2 (status, typ, "Could not set samplerate %d\n",
583 as->freq);
584 core->outputDeviceID = kAudioDeviceUnknown;
585 return -1;
588 /* set Callback */
589 core->ioprocid = NULL;
590 status = AudioDeviceCreateIOProcID(core->outputDeviceID,
591 audioDeviceIOProc,
593 &core->ioprocid);
594 if (status != kAudioHardwareNoError || core->ioprocid == NULL) {
595 coreaudio_logerr2 (status, typ, "Could not set IOProc\n");
596 core->outputDeviceID = kAudioDeviceUnknown;
597 return -1;
600 /* start Playback */
601 if (!isPlaying(core->outputDeviceID)) {
602 status = AudioDeviceStart(core->outputDeviceID, core->ioprocid);
603 if (status != kAudioHardwareNoError) {
604 coreaudio_logerr2 (status, typ, "Could not start playback\n");
605 AudioDeviceDestroyIOProcID(core->outputDeviceID, core->ioprocid);
606 core->outputDeviceID = kAudioDeviceUnknown;
607 return -1;
611 return 0;
614 static void coreaudio_fini_out (HWVoiceOut *hw)
616 OSStatus status;
617 int err;
618 coreaudioVoiceOut *core = (coreaudioVoiceOut *) hw;
620 if (!audio_is_cleaning_up()) {
621 /* stop playback */
622 if (isPlaying(core->outputDeviceID)) {
623 status = AudioDeviceStop(core->outputDeviceID, core->ioprocid);
624 if (status != kAudioHardwareNoError) {
625 coreaudio_logerr (status, "Could not stop playback\n");
629 /* remove callback */
630 status = AudioDeviceDestroyIOProcID(core->outputDeviceID,
631 core->ioprocid);
632 if (status != kAudioHardwareNoError) {
633 coreaudio_logerr (status, "Could not remove IOProc\n");
636 core->outputDeviceID = kAudioDeviceUnknown;
638 /* destroy mutex */
639 err = pthread_mutex_destroy(&core->mutex);
640 if (err) {
641 dolog("Could not destroy mutex\nReason: %s\n", strerror (err));
645 static int coreaudio_ctl_out (HWVoiceOut *hw, int cmd, ...)
647 OSStatus status;
648 coreaudioVoiceOut *core = (coreaudioVoiceOut *) hw;
650 switch (cmd) {
651 case VOICE_ENABLE:
652 /* start playback */
653 if (!isPlaying(core->outputDeviceID)) {
654 status = AudioDeviceStart(core->outputDeviceID, core->ioprocid);
655 if (status != kAudioHardwareNoError) {
656 coreaudio_logerr (status, "Could not resume playback\n");
659 break;
661 case VOICE_DISABLE:
662 /* stop playback */
663 if (!audio_is_cleaning_up()) {
664 if (isPlaying(core->outputDeviceID)) {
665 status = AudioDeviceStop(core->outputDeviceID,
666 core->ioprocid);
667 if (status != kAudioHardwareNoError) {
668 coreaudio_logerr (status, "Could not pause playback\n");
672 break;
674 return 0;
677 static void *coreaudio_audio_init(Audiodev *dev)
679 return dev;
682 static void coreaudio_audio_fini (void *opaque)
686 static struct audio_pcm_ops coreaudio_pcm_ops = {
687 .init_out = coreaudio_init_out,
688 .fini_out = coreaudio_fini_out,
689 .run_out = coreaudio_run_out,
690 .ctl_out = coreaudio_ctl_out
693 static struct audio_driver coreaudio_audio_driver = {
694 .name = "coreaudio",
695 .descr = "CoreAudio http://developer.apple.com/audio/coreaudio.html",
696 .init = coreaudio_audio_init,
697 .fini = coreaudio_audio_fini,
698 .pcm_ops = &coreaudio_pcm_ops,
699 .can_be_default = 1,
700 .max_voices_out = 1,
701 .max_voices_in = 0,
702 .voice_size_out = sizeof (coreaudioVoiceOut),
703 .voice_size_in = 0
706 static void register_audio_coreaudio(void)
708 audio_driver_register(&coreaudio_audio_driver);
710 type_init(register_audio_coreaudio);