master
m 685 lines 22 KB
Raw
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 "qemu/osdep.h"
26 #include <CoreAudio/CoreAudio.h>
27 #include <pthread.h> /* pthread_X */
28
29 #include "qemu/main-loop.h"
30 #include "qemu/module.h"
31 #include "qemu/error-report.h"
32 #include "qemu/audio.h"
33 #include "qom/object.h"
34 #include "audio_int.h"
35
36 #define TYPE_AUDIO_COREAUDIO "audio-coreaudio"
37 OBJECT_DECLARE_SIMPLE_TYPE(AudioCoreaudio, AUDIO_COREAUDIO)
38
39 struct AudioCoreaudio {
40 AudioMixengBackend parent_obj;
41 };
42
43 typedef struct coreaudioVoiceOut {
44 HWVoiceOut hw;
45 pthread_mutex_t buf_mutex;
46 AudioDeviceID device_id;
47 int frame_size_setting;
48 uint32_t buffer_count;
49 UInt32 device_frame_size;
50 AudioDeviceIOProcID ioprocid;
51 bool enabled;
52 } CoreaudioVoiceOut;
53
54 static const AudioObjectPropertyAddress voice_out_addr = {
55 kAudioHardwarePropertyDefaultOutputDevice,
56 kAudioObjectPropertyScopeGlobal,
57 kAudioObjectPropertyElementMain
58 };
59
60 static OSStatus coreaudio_get_voice_out(AudioDeviceID *id)
61 {
62 UInt32 size = sizeof(*id);
63
64 return AudioObjectGetPropertyData(kAudioObjectSystemObject,
65 &voice_out_addr,
66 0,
67 NULL,
68 &size,
69 id);
70 }
71
72 static OSStatus coreaudio_get_out_framesizerange(AudioDeviceID id,
73 AudioValueRange *framerange)
74 {
75 UInt32 size = sizeof(*framerange);
76 AudioObjectPropertyAddress addr = {
77 kAudioDevicePropertyBufferFrameSizeRange,
78 kAudioDevicePropertyScopeOutput,
79 kAudioObjectPropertyElementMain
80 };
81
82 return AudioObjectGetPropertyData(id,
83 &addr,
84 0,
85 NULL,
86 &size,
87 framerange);
88 }
89
90 static OSStatus coreaudio_get_out_framesize(AudioDeviceID id, UInt32 *framesize)
91 {
92 UInt32 size = sizeof(*framesize);
93 AudioObjectPropertyAddress addr = {
94 kAudioDevicePropertyBufferFrameSize,
95 kAudioDevicePropertyScopeOutput,
96 kAudioObjectPropertyElementMain
97 };
98
99 return AudioObjectGetPropertyData(id,
100 &addr,
101 0,
102 NULL,
103 &size,
104 framesize);
105 }
106
107 static OSStatus coreaudio_set_out_framesize(AudioDeviceID id, UInt32 *framesize)
108 {
109 UInt32 size = sizeof(*framesize);
110 AudioObjectPropertyAddress addr = {
111 kAudioDevicePropertyBufferFrameSize,
112 kAudioDevicePropertyScopeOutput,
113 kAudioObjectPropertyElementMain
114 };
115
116 return AudioObjectSetPropertyData(id,
117 &addr,
118 0,
119 NULL,
120 size,
121 framesize);
122 }
123
124 static OSStatus coreaudio_set_out_streamformat(AudioDeviceID id,
125 AudioStreamBasicDescription *d)
126 {
127 UInt32 size = sizeof(*d);
128 AudioObjectPropertyAddress addr = {
129 kAudioDevicePropertyStreamFormat,
130 kAudioDevicePropertyScopeOutput,
131 kAudioObjectPropertyElementMain
132 };
133
134 return AudioObjectSetPropertyData(id,
135 &addr,
136 0,
137 NULL,
138 size,
139 d);
140 }
141
142 static OSStatus coreaudio_get_out_isrunning(AudioDeviceID id, UInt32 *result)
143 {
144 UInt32 size = sizeof(*result);
145 AudioObjectPropertyAddress addr = {
146 kAudioDevicePropertyDeviceIsRunning,
147 kAudioDevicePropertyScopeOutput,
148 kAudioObjectPropertyElementMain
149 };
150
151 return AudioObjectGetPropertyData(id,
152 &addr,
153 0,
154 NULL,
155 &size,
156 result);
157 }
158
159 static void coreaudio_logstatus(OSStatus status)
160 {
161 const char *str = "BUG";
162
163 switch (status) {
164 case kAudioHardwareNoError:
165 str = "kAudioHardwareNoError";
166 break;
167
168 case kAudioHardwareNotRunningError:
169 str = "kAudioHardwareNotRunningError";
170 break;
171
172 case kAudioHardwareUnspecifiedError:
173 str = "kAudioHardwareUnspecifiedError";
174 break;
175
176 case kAudioHardwareUnknownPropertyError:
177 str = "kAudioHardwareUnknownPropertyError";
178 break;
179
180 case kAudioHardwareBadPropertySizeError:
181 str = "kAudioHardwareBadPropertySizeError";
182 break;
183
184 case kAudioHardwareIllegalOperationError:
185 str = "kAudioHardwareIllegalOperationError";
186 break;
187
188 case kAudioHardwareBadDeviceError:
189 str = "kAudioHardwareBadDeviceError";
190 break;
191
192 case kAudioHardwareBadStreamError:
193 str = "kAudioHardwareBadStreamError";
194 break;
195
196 case kAudioHardwareUnsupportedOperationError:
197 str = "kAudioHardwareUnsupportedOperationError";
198 break;
199
200 case kAudioDeviceUnsupportedFormatError:
201 str = "kAudioDeviceUnsupportedFormatError";
202 break;
203
204 case kAudioDevicePermissionsError:
205 str = "kAudioDevicePermissionsError";
206 break;
207
208 default:
209 error_printf(" Reason: status code %" PRId32, (int32_t)status);
210 return;
211 }
212
213 error_printf(" Reason: %s", str);
214 }
215
216 static void G_GNUC_PRINTF(2, 3) coreaudio_logerr(OSStatus status,
217 const char *fmt, ...)
218 {
219 va_list ap;
220
221 error_printf("coreaudio: ");
222 va_start(ap, fmt);
223 error_vprintf(fmt, ap);
224 va_end(ap);
225 coreaudio_logstatus(status);
226 error_printf("\n");
227 }
228
229 static void G_GNUC_PRINTF(3, 4) coreaudio_logerr2(OSStatus status,
230 const char *typ,
231 const char *fmt, ...)
232 {
233 va_list ap;
234
235 error_printf("coreaudio: Could not initialize %s: ", typ);
236 va_start(ap, fmt);
237 error_vprintf(fmt, ap);
238 va_end(ap);
239 coreaudio_logstatus(status);
240 error_printf("\n");
241 }
242
243 #define coreaudio_playback_logerr(status, ...) \
244 coreaudio_logerr2(status, "playback", __VA_ARGS__)
245
246 static int coreaudio_voice_out_buf_lock(CoreaudioVoiceOut *core,
247 const char *fn_name)
248 {
249 int err;
250
251 err = pthread_mutex_lock(&core->buf_mutex);
252 if (err) {
253 error_report("coreaudio: Could not lock voice for %s: %s",
254 fn_name, strerror(err));
255 return -1;
256 }
257 return 0;
258 }
259
260 static int coreaudio_voice_out_buf_unlock(CoreaudioVoiceOut *core,
261 const char *fn_name)
262 {
263 int err;
264
265 err = pthread_mutex_unlock(&core->buf_mutex);
266 if (err) {
267 error_report("coreaudio: Could not unlock voice for %s: %s",
268 fn_name, strerror(err));
269 return -1;
270 }
271 return 0;
272 }
273
274 #define COREAUDIO_WRAPPER_FUNC(name, ret_type, args_decl, args) \
275 static ret_type glue(coreaudio_, name)args_decl \
276 { \
277 CoreaudioVoiceOut *core = (CoreaudioVoiceOut *)hw; \
278 ret_type ret; \
279 \
280 if (coreaudio_voice_out_buf_lock(core, "coreaudio_" #name)) { \
281 return 0; \
282 } \
283 \
284 ret = glue(audio_generic_, name)args; \
285 \
286 coreaudio_voice_out_buf_unlock(core, "coreaudio_" #name); \
287 return ret; \
288 }
289 COREAUDIO_WRAPPER_FUNC(buffer_get_free, size_t, (HWVoiceOut *hw), (hw))
290 COREAUDIO_WRAPPER_FUNC(get_buffer_out, void *, (HWVoiceOut *hw, size_t *size),
291 (hw, size))
292 COREAUDIO_WRAPPER_FUNC(put_buffer_out, size_t,
293 (HWVoiceOut *hw, void *buf, size_t size),
294 (hw, buf, size))
295 COREAUDIO_WRAPPER_FUNC(write, size_t, (HWVoiceOut *hw, void *buf, size_t size),
296 (hw, buf, size))
297 #undef COREAUDIO_WRAPPER_FUNC
298
299 /*
300 * callback to feed audiooutput buffer. called without BQL.
301 * allowed to lock "buf_mutex", but disallowed to have any other locks.
302 */
303 static OSStatus out_device_ioproc(
304 AudioDeviceID inDevice,
305 const AudioTimeStamp *inNow,
306 const AudioBufferList *inInputData,
307 const AudioTimeStamp *inInputTime,
308 AudioBufferList *outOutputData,
309 const AudioTimeStamp *inOutputTime,
310 void *hwptr)
311 {
312 UInt32 frame_size, pending_frames;
313 void *out = outOutputData->mBuffers[0].mData;
314 HWVoiceOut *hw = hwptr;
315 CoreaudioVoiceOut *core = hwptr;
316 size_t len;
317
318 if (coreaudio_voice_out_buf_lock(core, "out_device_ioproc")) {
319 inInputTime = 0;
320 return 0;
321 }
322
323 if (inDevice != core->device_id) {
324 coreaudio_voice_out_buf_unlock(core, "out_device_ioproc(old device)");
325 return 0;
326 }
327
328 frame_size = core->device_frame_size;
329 pending_frames = hw->pending_emul / hw->info.bytes_per_frame;
330
331 /* if there are not enough samples, set signal and return */
332 if (pending_frames < frame_size) {
333 inInputTime = 0;
334 coreaudio_voice_out_buf_unlock(core, "out_device_ioproc(empty)");
335 return 0;
336 }
337
338 len = frame_size * hw->info.bytes_per_frame;
339 while (len) {
340 size_t write_len, start;
341
342 start = audio_ring_posb(hw->pos_emul, hw->pending_emul, hw->size_emul);
343 assert(start < hw->size_emul);
344
345 write_len = MIN(MIN(hw->pending_emul, len),
346 hw->size_emul - start);
347
348 memcpy(out, hw->buf_emul + start, write_len);
349 hw->pending_emul -= write_len;
350 len -= write_len;
351 out += write_len;
352 }
353
354 coreaudio_voice_out_buf_unlock(core, "out_device_ioproc");
355 return 0;
356 }
357
358 static OSStatus init_out_device(CoreaudioVoiceOut *core)
359 {
360 AudioDeviceID device_id;
361 AudioDeviceIOProcID ioprocid;
362 AudioValueRange value_range;
363 OSStatus status;
364 UInt32 device_frame_size;
365
366 AudioStreamBasicDescription stream_basic_description = {
367 .mBitsPerChannel = audio_format_bits(core->hw.info.af),
368 .mBytesPerFrame = core->hw.info.bytes_per_frame,
369 .mBytesPerPacket = core->hw.info.bytes_per_frame,
370 .mChannelsPerFrame = core->hw.info.nchannels,
371 .mFormatFlags = kLinearPCMFormatFlagIsFloat,
372 .mFormatID = kAudioFormatLinearPCM,
373 .mFramesPerPacket = 1,
374 .mSampleRate = core->hw.info.freq
375 };
376
377 status = coreaudio_get_voice_out(&device_id);
378 if (status != kAudioHardwareNoError) {
379 coreaudio_playback_logerr(status,
380 "Could not get default output device");
381 return status;
382 }
383 if (device_id == kAudioDeviceUnknown) {
384 error_report("coreaudio: Could not initialize playback: "
385 "Unknown audio device");
386 return status;
387 }
388
389 /* get minimum and maximum buffer frame sizes */
390 status = coreaudio_get_out_framesizerange(device_id, &value_range);
391 if (status == kAudioHardwareBadObjectError) {
392 return 0;
393 }
394 if (status != kAudioHardwareNoError) {
395 coreaudio_playback_logerr(status,
396 "Could not get device buffer frame range");
397 return status;
398 }
399
400 if (value_range.mMinimum > core->frame_size_setting) {
401 device_frame_size = value_range.mMinimum;
402 warn_report("coreaudio: Upsizing buffer frames to %f",
403 value_range.mMinimum);
404 } else if (value_range.mMaximum < core->frame_size_setting) {
405 device_frame_size = value_range.mMaximum;
406 warn_report("coreaudio: Downsizing buffer frames to %f",
407 value_range.mMaximum);
408 } else {
409 device_frame_size = core->frame_size_setting;
410 }
411
412 /* set Buffer Frame Size */
413 status = coreaudio_set_out_framesize(device_id, &device_frame_size);
414 if (status == kAudioHardwareBadObjectError) {
415 return 0;
416 }
417 if (status != kAudioHardwareNoError) {
418 coreaudio_playback_logerr(status,
419 "Could not set device buffer frame size %" PRIu32,
420 (uint32_t)device_frame_size);
421 return status;
422 }
423
424 /* get Buffer Frame Size */
425 status = coreaudio_get_out_framesize(device_id, &device_frame_size);
426 if (status == kAudioHardwareBadObjectError) {
427 return 0;
428 }
429 if (status != kAudioHardwareNoError) {
430 coreaudio_playback_logerr(status,
431 "Could not get device buffer frame size");
432 return status;
433 }
434
435 /* set Samplerate */
436 status = coreaudio_set_out_streamformat(device_id,
437 &stream_basic_description);
438 if (status == kAudioHardwareBadObjectError) {
439 return 0;
440 }
441 if (status != kAudioHardwareNoError) {
442 coreaudio_playback_logerr(status,
443 "Could not set samplerate %lf",
444 stream_basic_description.mSampleRate);
445 return status;
446 }
447
448 /*
449 * set Callback.
450 *
451 * On macOS 11.3.1, Core Audio calls AudioDeviceIOProc after calling an
452 * internal function named HALB_Mutex::Lock(), which locks a mutex in
453 * HALB_IOThread::Entry(void*). HALB_Mutex::Lock() is also called in
454 * AudioObjectGetPropertyData, which is called by coreaudio driver.
455 * Therefore, the specified callback must be designed to avoid a deadlock
456 * with the callers of AudioObjectGetPropertyData.
457 */
458 ioprocid = NULL;
459 status = AudioDeviceCreateIOProcID(device_id,
460 out_device_ioproc,
461 &core->hw,
462 &ioprocid);
463 if (status == kAudioHardwareBadDeviceError) {
464 return 0;
465 }
466 if (status != kAudioHardwareNoError || ioprocid == NULL) {
467 coreaudio_playback_logerr(status, "Could not set IOProc");
468 return status;
469 }
470
471 core->device_id = device_id;
472 core->device_frame_size = device_frame_size;
473 core->hw.samples = core->buffer_count * core->device_frame_size;
474 audio_generic_initialize_buffer_out(&core->hw);
475 core->ioprocid = ioprocid;
476
477 return 0;
478 }
479
480 static void fini_out_device(CoreaudioVoiceOut *core)
481 {
482 OSStatus status;
483 UInt32 isrunning;
484
485 /* stop playback */
486 status = coreaudio_get_out_isrunning(core->device_id, &isrunning);
487 if (status != kAudioHardwareBadObjectError) {
488 if (status != kAudioHardwareNoError) {
489 coreaudio_logerr(status,
490 "Could not determine whether device is playing");
491 }
492
493 if (isrunning) {
494 status = AudioDeviceStop(core->device_id, core->ioprocid);
495 if (status != kAudioHardwareBadDeviceError && status != kAudioHardwareNoError) {
496 coreaudio_logerr(status, "Could not stop playback");
497 }
498 }
499 }
500
501 /* remove callback */
502 status = AudioDeviceDestroyIOProcID(core->device_id,
503 core->ioprocid);
504 if (status != kAudioHardwareBadDeviceError && status != kAudioHardwareNoError) {
505 coreaudio_logerr(status, "Could not remove IOProc");
506 }
507 core->device_id = kAudioDeviceUnknown;
508 }
509
510 static void update_out_device_playback_state(CoreaudioVoiceOut *core)
511 {
512 OSStatus status;
513 UInt32 isrunning;
514
515 status = coreaudio_get_out_isrunning(core->device_id, &isrunning);
516 if (status != kAudioHardwareNoError) {
517 if (status != kAudioHardwareBadObjectError) {
518 coreaudio_logerr(status,
519 "Could not determine whether device is playing");
520 }
521
522 return;
523 }
524
525 if (core->enabled) {
526 /* start playback */
527 if (!isrunning) {
528 status = AudioDeviceStart(core->device_id, core->ioprocid);
529 if (status != kAudioHardwareBadDeviceError && status != kAudioHardwareNoError) {
530 coreaudio_logerr(status, "Could not resume playback");
531 }
532 }
533 } else {
534 /* stop playback */
535 if (isrunning) {
536 status = AudioDeviceStop(core->device_id,
537 core->ioprocid);
538 if (status != kAudioHardwareBadDeviceError && status != kAudioHardwareNoError) {
539 coreaudio_logerr(status, "Could not pause playback");
540 }
541 }
542 }
543 }
544
545 /* called without BQL. */
546 static OSStatus handle_voice_out_change(
547 AudioObjectID in_object_id,
548 UInt32 in_number_addresses,
549 const AudioObjectPropertyAddress *in_addresses,
550 void *in_client_data)
551 {
552 CoreaudioVoiceOut *core = in_client_data;
553
554 bql_lock();
555
556 if (core->device_id) {
557 fini_out_device(core);
558 }
559
560 init_out_device(core);
561
562 if (core->device_id) {
563 update_out_device_playback_state(core);
564 }
565
566 bql_unlock();
567 return 0;
568 }
569
570 static int coreaudio_init_out(HWVoiceOut *hw, struct audsettings *as)
571 {
572 OSStatus status;
573 CoreaudioVoiceOut *core = (CoreaudioVoiceOut *)hw;
574 int err;
575 Audiodev *dev = hw->s->dev;
576 AudiodevCoreaudioPerDirectionOptions *cpdo = dev->u.coreaudio.out;
577 struct audsettings obt_as;
578
579 /* create mutex */
580 err = pthread_mutex_init(&core->buf_mutex, NULL);
581 if (err) {
582 error_report("coreaudio: Could not create mutex: %s", strerror(err));
583 return -1;
584 }
585
586 obt_as = *as;
587 as = &obt_as;
588 as->fmt = AUDIO_FORMAT_F32;
589 audio_pcm_init_info(&hw->info, as);
590
591 core->frame_size_setting = audio_buffer_frames(
592 qapi_AudiodevCoreaudioPerDirectionOptions_base(cpdo), as, 11610);
593
594 core->buffer_count = cpdo->has_buffer_count ? cpdo->buffer_count : 4;
595
596 status = AudioObjectAddPropertyListener(kAudioObjectSystemObject,
597 &voice_out_addr,
598 handle_voice_out_change,
599 core);
600 if (status != kAudioHardwareNoError) {
601 coreaudio_playback_logerr(status,
602 "Could not listen to voice property change");
603 return -1;
604 }
605
606 if (init_out_device(core)) {
607 status = AudioObjectRemovePropertyListener(kAudioObjectSystemObject,
608 &voice_out_addr,
609 handle_voice_out_change,
610 core);
611 if (status != kAudioHardwareNoError) {
612 coreaudio_playback_logerr(status,
613 "Could not remove voice property change listener");
614 }
615
616 return -1;
617 }
618
619 return 0;
620 }
621
622 static void coreaudio_fini_out (HWVoiceOut *hw)
623 {
624 OSStatus status;
625 int err;
626 CoreaudioVoiceOut *core = (CoreaudioVoiceOut *)hw;
627
628 status = AudioObjectRemovePropertyListener(kAudioObjectSystemObject,
629 &voice_out_addr,
630 handle_voice_out_change,
631 core);
632 if (status != kAudioHardwareNoError) {
633 coreaudio_logerr(status, "Could not remove voice property change listener");
634 }
635
636 fini_out_device(core);
637
638 /* destroy mutex */
639 err = pthread_mutex_destroy(&core->buf_mutex);
640 if (err) {
641 error_report("coreaudio: Could not destroy mutex: %s", strerror(err));
642 }
643 }
644
645 static void coreaudio_enable_out(HWVoiceOut *hw, bool enable)
646 {
647 CoreaudioVoiceOut *core = (CoreaudioVoiceOut *)hw;
648
649 core->enabled = enable;
650 update_out_device_playback_state(core);
651 }
652
653 static void audio_coreaudio_class_init(ObjectClass *klass, const void *data)
654 {
655 AudioMixengBackendClass *k = AUDIO_MIXENG_BACKEND_CLASS(klass);
656
657 k->max_voices_out = 1;
658 k->max_voices_in = 0;
659 k->voice_size_out = sizeof(CoreaudioVoiceOut);
660 k->voice_size_in = 0;
661
662 k->init_out = coreaudio_init_out;
663 k->fini_out = coreaudio_fini_out;
664 /* wrapper for audio_generic_write */
665 k->write = coreaudio_write;
666 /* wrapper for audio_generic_buffer_get_free */
667 k->buffer_get_free = coreaudio_buffer_get_free;
668 /* wrapper for audio_generic_get_buffer_out */
669 k->get_buffer_out = coreaudio_get_buffer_out;
670 /* wrapper for audio_generic_put_buffer_out */
671 k->put_buffer_out = coreaudio_put_buffer_out;
672 k->enable_out = coreaudio_enable_out;
673 }
674
675 static const TypeInfo audio_types[] = {
676 {
677 .name = TYPE_AUDIO_COREAUDIO,
678 .parent = TYPE_AUDIO_MIXENG_BACKEND,
679 .instance_size = sizeof(AudioCoreaudio),
680 .class_init = audio_coreaudio_class_init,
681 },
682 };
683
684 DEFINE_TYPES(audio_types)
685 module_obj(TYPE_AUDIO_COREAUDIO);