]> Git Repo - qemu.git/blob - audio/coreaudio.c
Merge remote-tracking branch 'remotes/kraxel/tags/audio-20200207-pull-request' into...
[qemu.git] / 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 "qemu/osdep.h"
26 #include <CoreAudio/CoreAudio.h>
27 #include <pthread.h>            /* pthread_X */
28
29 #include "qemu/module.h"
30 #include "audio.h"
31
32 #define AUDIO_CAP "coreaudio"
33 #include "audio_int.h"
34
35 #ifndef MAC_OS_X_VERSION_10_6
36 #define MAC_OS_X_VERSION_10_6 1060
37 #endif
38
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 } coreaudioVoiceOut;
47
48 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
49 /* The APIs used here only become available from 10.6 */
50
51 static OSStatus coreaudio_get_voice(AudioDeviceID *id)
52 {
53     UInt32 size = sizeof(*id);
54     AudioObjectPropertyAddress addr = {
55         kAudioHardwarePropertyDefaultOutputDevice,
56         kAudioObjectPropertyScopeGlobal,
57         kAudioObjectPropertyElementMaster
58     };
59
60     return AudioObjectGetPropertyData(kAudioObjectSystemObject,
61                                       &addr,
62                                       0,
63                                       NULL,
64                                       &size,
65                                       id);
66 }
67
68 static OSStatus coreaudio_get_framesizerange(AudioDeviceID id,
69                                              AudioValueRange *framerange)
70 {
71     UInt32 size = sizeof(*framerange);
72     AudioObjectPropertyAddress addr = {
73         kAudioDevicePropertyBufferFrameSizeRange,
74         kAudioDevicePropertyScopeOutput,
75         kAudioObjectPropertyElementMaster
76     };
77
78     return AudioObjectGetPropertyData(id,
79                                       &addr,
80                                       0,
81                                       NULL,
82                                       &size,
83                                       framerange);
84 }
85
86 static OSStatus coreaudio_get_framesize(AudioDeviceID id, UInt32 *framesize)
87 {
88     UInt32 size = sizeof(*framesize);
89     AudioObjectPropertyAddress addr = {
90         kAudioDevicePropertyBufferFrameSize,
91         kAudioDevicePropertyScopeOutput,
92         kAudioObjectPropertyElementMaster
93     };
94
95     return AudioObjectGetPropertyData(id,
96                                       &addr,
97                                       0,
98                                       NULL,
99                                       &size,
100                                       framesize);
101 }
102
103 static OSStatus coreaudio_set_framesize(AudioDeviceID id, UInt32 *framesize)
104 {
105     UInt32 size = sizeof(*framesize);
106     AudioObjectPropertyAddress addr = {
107         kAudioDevicePropertyBufferFrameSize,
108         kAudioDevicePropertyScopeOutput,
109         kAudioObjectPropertyElementMaster
110     };
111
112     return AudioObjectSetPropertyData(id,
113                                       &addr,
114                                       0,
115                                       NULL,
116                                       size,
117                                       framesize);
118 }
119
120 static OSStatus coreaudio_get_streamformat(AudioDeviceID id,
121                                            AudioStreamBasicDescription *d)
122 {
123     UInt32 size = sizeof(*d);
124     AudioObjectPropertyAddress addr = {
125         kAudioDevicePropertyStreamFormat,
126         kAudioDevicePropertyScopeOutput,
127         kAudioObjectPropertyElementMaster
128     };
129
130     return AudioObjectGetPropertyData(id,
131                                       &addr,
132                                       0,
133                                       NULL,
134                                       &size,
135                                       d);
136 }
137
138 static OSStatus coreaudio_set_streamformat(AudioDeviceID id,
139                                            AudioStreamBasicDescription *d)
140 {
141     UInt32 size = sizeof(*d);
142     AudioObjectPropertyAddress addr = {
143         kAudioDevicePropertyStreamFormat,
144         kAudioDevicePropertyScopeOutput,
145         kAudioObjectPropertyElementMaster
146     };
147
148     return AudioObjectSetPropertyData(id,
149                                       &addr,
150                                       0,
151                                       NULL,
152                                       size,
153                                       d);
154 }
155
156 static OSStatus coreaudio_get_isrunning(AudioDeviceID id, UInt32 *result)
157 {
158     UInt32 size = sizeof(*result);
159     AudioObjectPropertyAddress addr = {
160         kAudioDevicePropertyDeviceIsRunning,
161         kAudioDevicePropertyScopeOutput,
162         kAudioObjectPropertyElementMaster
163     };
164
165     return AudioObjectGetPropertyData(id,
166                                       &addr,
167                                       0,
168                                       NULL,
169                                       &size,
170                                       result);
171 }
172 #else
173 /* Legacy versions of functions using deprecated APIs */
174
175 static OSStatus coreaudio_get_voice(AudioDeviceID *id)
176 {
177     UInt32 size = sizeof(*id);
178
179     return AudioHardwareGetProperty(
180         kAudioHardwarePropertyDefaultOutputDevice,
181         &size,
182         id);
183 }
184
185 static OSStatus coreaudio_get_framesizerange(AudioDeviceID id,
186                                              AudioValueRange *framerange)
187 {
188     UInt32 size = sizeof(*framerange);
189
190     return AudioDeviceGetProperty(
191         id,
192         0,
193         0,
194         kAudioDevicePropertyBufferFrameSizeRange,
195         &size,
196         framerange);
197 }
198
199 static OSStatus coreaudio_get_framesize(AudioDeviceID id, UInt32 *framesize)
200 {
201     UInt32 size = sizeof(*framesize);
202
203     return AudioDeviceGetProperty(
204         id,
205         0,
206         false,
207         kAudioDevicePropertyBufferFrameSize,
208         &size,
209         framesize);
210 }
211
212 static OSStatus coreaudio_set_framesize(AudioDeviceID id, UInt32 *framesize)
213 {
214     UInt32 size = sizeof(*framesize);
215
216     return AudioDeviceSetProperty(
217         id,
218         NULL,
219         0,
220         false,
221         kAudioDevicePropertyBufferFrameSize,
222         size,
223         framesize);
224 }
225
226 static OSStatus coreaudio_get_streamformat(AudioDeviceID id,
227                                            AudioStreamBasicDescription *d)
228 {
229     UInt32 size = sizeof(*d);
230
231     return AudioDeviceGetProperty(
232         id,
233         0,
234         false,
235         kAudioDevicePropertyStreamFormat,
236         &size,
237         d);
238 }
239
240 static OSStatus coreaudio_set_streamformat(AudioDeviceID id,
241                                            AudioStreamBasicDescription *d)
242 {
243     UInt32 size = sizeof(*d);
244
245     return AudioDeviceSetProperty(
246         id,
247         0,
248         0,
249         0,
250         kAudioDevicePropertyStreamFormat,
251         size,
252         d);
253 }
254
255 static OSStatus coreaudio_get_isrunning(AudioDeviceID id, UInt32 *result)
256 {
257     UInt32 size = sizeof(*result);
258
259     return AudioDeviceGetProperty(
260         id,
261         0,
262         0,
263         kAudioDevicePropertyDeviceIsRunning,
264         &size,
265         result);
266 }
267 #endif
268
269 static void coreaudio_logstatus (OSStatus status)
270 {
271     const char *str = "BUG";
272
273     switch(status) {
274     case kAudioHardwareNoError:
275         str = "kAudioHardwareNoError";
276         break;
277
278     case kAudioHardwareNotRunningError:
279         str = "kAudioHardwareNotRunningError";
280         break;
281
282     case kAudioHardwareUnspecifiedError:
283         str = "kAudioHardwareUnspecifiedError";
284         break;
285
286     case kAudioHardwareUnknownPropertyError:
287         str = "kAudioHardwareUnknownPropertyError";
288         break;
289
290     case kAudioHardwareBadPropertySizeError:
291         str = "kAudioHardwareBadPropertySizeError";
292         break;
293
294     case kAudioHardwareIllegalOperationError:
295         str = "kAudioHardwareIllegalOperationError";
296         break;
297
298     case kAudioHardwareBadDeviceError:
299         str = "kAudioHardwareBadDeviceError";
300         break;
301
302     case kAudioHardwareBadStreamError:
303         str = "kAudioHardwareBadStreamError";
304         break;
305
306     case kAudioHardwareUnsupportedOperationError:
307         str = "kAudioHardwareUnsupportedOperationError";
308         break;
309
310     case kAudioDeviceUnsupportedFormatError:
311         str = "kAudioDeviceUnsupportedFormatError";
312         break;
313
314     case kAudioDevicePermissionsError:
315         str = "kAudioDevicePermissionsError";
316         break;
317
318     default:
319         AUD_log (AUDIO_CAP, "Reason: status code %" PRId32 "\n", (int32_t)status);
320         return;
321     }
322
323     AUD_log (AUDIO_CAP, "Reason: %s\n", str);
324 }
325
326 static void GCC_FMT_ATTR (2, 3) coreaudio_logerr (
327     OSStatus status,
328     const char *fmt,
329     ...
330     )
331 {
332     va_list ap;
333
334     va_start (ap, fmt);
335     AUD_log (AUDIO_CAP, fmt, ap);
336     va_end (ap);
337
338     coreaudio_logstatus (status);
339 }
340
341 static void GCC_FMT_ATTR (3, 4) coreaudio_logerr2 (
342     OSStatus status,
343     const char *typ,
344     const char *fmt,
345     ...
346     )
347 {
348     va_list ap;
349
350     AUD_log (AUDIO_CAP, "Could not initialize %s\n", typ);
351
352     va_start (ap, fmt);
353     AUD_vlog (AUDIO_CAP, fmt, ap);
354     va_end (ap);
355
356     coreaudio_logstatus (status);
357 }
358
359 static inline UInt32 isPlaying (AudioDeviceID outputDeviceID)
360 {
361     OSStatus status;
362     UInt32 result = 0;
363     status = coreaudio_get_isrunning(outputDeviceID, &result);
364     if (status != kAudioHardwareNoError) {
365         coreaudio_logerr(status,
366                          "Could not determine whether Device is playing\n");
367     }
368     return result;
369 }
370
371 static int coreaudio_lock (coreaudioVoiceOut *core, const char *fn_name)
372 {
373     int err;
374
375     err = pthread_mutex_lock (&core->mutex);
376     if (err) {
377         dolog ("Could not lock voice for %s\nReason: %s\n",
378                fn_name, strerror (err));
379         return -1;
380     }
381     return 0;
382 }
383
384 static int coreaudio_unlock (coreaudioVoiceOut *core, const char *fn_name)
385 {
386     int err;
387
388     err = pthread_mutex_unlock (&core->mutex);
389     if (err) {
390         dolog ("Could not unlock voice for %s\nReason: %s\n",
391                fn_name, strerror (err));
392         return -1;
393     }
394     return 0;
395 }
396
397 #define COREAUDIO_WRAPPER_FUNC(name, ret_type, args_decl, args) \
398     static ret_type glue(coreaudio_, name)args_decl             \
399     {                                                           \
400         coreaudioVoiceOut *core = (coreaudioVoiceOut *) hw;     \
401         ret_type ret;                                           \
402                                                                 \
403         if (coreaudio_lock(core, "coreaudio_" #name)) {         \
404             return 0;                                           \
405         }                                                       \
406                                                                 \
407         ret = glue(audio_generic_, name)args;                   \
408                                                                 \
409         coreaudio_unlock(core, "coreaudio_" #name);             \
410         return ret;                                             \
411     }
412 COREAUDIO_WRAPPER_FUNC(get_buffer_out, void *, (HWVoiceOut *hw, size_t *size),
413                        (hw, size))
414 COREAUDIO_WRAPPER_FUNC(put_buffer_out, size_t,
415                        (HWVoiceOut *hw, void *buf, size_t size),
416                        (hw, buf, size))
417 COREAUDIO_WRAPPER_FUNC(write, size_t, (HWVoiceOut *hw, void *buf, size_t size),
418                        (hw, buf, size))
419 #undef COREAUDIO_WRAPPER_FUNC
420
421 /* callback to feed audiooutput buffer */
422 static OSStatus audioDeviceIOProc(
423     AudioDeviceID inDevice,
424     const AudioTimeStamp* inNow,
425     const AudioBufferList* inInputData,
426     const AudioTimeStamp* inInputTime,
427     AudioBufferList* outOutputData,
428     const AudioTimeStamp* inOutputTime,
429     void* hwptr)
430 {
431     UInt32 frameCount, pending_frames;
432     void *out = outOutputData->mBuffers[0].mData;
433     HWVoiceOut *hw = hwptr;
434     coreaudioVoiceOut *core = (coreaudioVoiceOut *) hwptr;
435     size_t len;
436
437     if (coreaudio_lock (core, "audioDeviceIOProc")) {
438         inInputTime = 0;
439         return 0;
440     }
441
442     frameCount = core->audioDevicePropertyBufferFrameSize;
443     pending_frames = hw->pending_emul / hw->info.bytes_per_frame;
444
445     /* if there are not enough samples, set signal and return */
446     if (pending_frames < frameCount) {
447         inInputTime = 0;
448         coreaudio_unlock (core, "audioDeviceIOProc(empty)");
449         return 0;
450     }
451
452     len = frameCount * hw->info.bytes_per_frame;
453     while (len) {
454         size_t write_len;
455         ssize_t start = ((ssize_t) hw->pos_emul) - hw->pending_emul;
456         if (start < 0) {
457             start += hw->size_emul;
458         }
459         assert(start >= 0 && start < hw->size_emul);
460
461         write_len = MIN(MIN(hw->pending_emul, len),
462                         hw->size_emul - start);
463
464         memcpy(out, hw->buf_emul + start, write_len);
465         hw->pending_emul -= write_len;
466         len -= write_len;
467         out += write_len;
468     }
469
470     coreaudio_unlock (core, "audioDeviceIOProc");
471     return 0;
472 }
473
474 static int coreaudio_init_out(HWVoiceOut *hw, struct audsettings *as,
475                               void *drv_opaque)
476 {
477     OSStatus status;
478     coreaudioVoiceOut *core = (coreaudioVoiceOut *) hw;
479     int err;
480     const char *typ = "playback";
481     AudioValueRange frameRange;
482     Audiodev *dev = drv_opaque;
483     AudiodevCoreaudioPerDirectionOptions *cpdo = dev->u.coreaudio.out;
484     int frames;
485     struct audsettings fake_as;
486
487     /* create mutex */
488     err = pthread_mutex_init(&core->mutex, NULL);
489     if (err) {
490         dolog("Could not create mutex\nReason: %s\n", strerror (err));
491         return -1;
492     }
493
494     fake_as = *as;
495     as = &fake_as;
496     as->fmt = AUDIO_FORMAT_F32;
497     audio_pcm_init_info (&hw->info, as);
498
499     status = coreaudio_get_voice(&core->outputDeviceID);
500     if (status != kAudioHardwareNoError) {
501         coreaudio_logerr2 (status, typ,
502                            "Could not get default output Device\n");
503         return -1;
504     }
505     if (core->outputDeviceID == kAudioDeviceUnknown) {
506         dolog ("Could not initialize %s - Unknown Audiodevice\n", typ);
507         return -1;
508     }
509
510     /* get minimum and maximum buffer frame sizes */
511     status = coreaudio_get_framesizerange(core->outputDeviceID,
512                                           &frameRange);
513     if (status != kAudioHardwareNoError) {
514         coreaudio_logerr2 (status, typ,
515                            "Could not get device buffer frame range\n");
516         return -1;
517     }
518
519     frames = audio_buffer_frames(
520         qapi_AudiodevCoreaudioPerDirectionOptions_base(cpdo), as, 11610);
521     if (frameRange.mMinimum > frames) {
522         core->audioDevicePropertyBufferFrameSize = (UInt32) frameRange.mMinimum;
523         dolog ("warning: Upsizing Buffer Frames to %f\n", frameRange.mMinimum);
524     } else if (frameRange.mMaximum < frames) {
525         core->audioDevicePropertyBufferFrameSize = (UInt32) frameRange.mMaximum;
526         dolog ("warning: Downsizing Buffer Frames to %f\n", frameRange.mMaximum);
527     }
528     else {
529         core->audioDevicePropertyBufferFrameSize = frames;
530     }
531
532     /* set Buffer Frame Size */
533     status = coreaudio_set_framesize(core->outputDeviceID,
534                                      &core->audioDevicePropertyBufferFrameSize);
535     if (status != kAudioHardwareNoError) {
536         coreaudio_logerr2 (status, typ,
537                            "Could not set device buffer frame size %" PRIu32 "\n",
538                            (uint32_t)core->audioDevicePropertyBufferFrameSize);
539         return -1;
540     }
541
542     /* get Buffer Frame Size */
543     status = coreaudio_get_framesize(core->outputDeviceID,
544                                      &core->audioDevicePropertyBufferFrameSize);
545     if (status != kAudioHardwareNoError) {
546         coreaudio_logerr2 (status, typ,
547                            "Could not get device buffer frame size\n");
548         return -1;
549     }
550     hw->samples = (cpdo->has_buffer_count ? cpdo->buffer_count : 4) *
551         core->audioDevicePropertyBufferFrameSize;
552
553     /* get StreamFormat */
554     status = coreaudio_get_streamformat(core->outputDeviceID,
555                                         &core->outputStreamBasicDescription);
556     if (status != kAudioHardwareNoError) {
557         coreaudio_logerr2 (status, typ,
558                            "Could not get Device Stream properties\n");
559         core->outputDeviceID = kAudioDeviceUnknown;
560         return -1;
561     }
562
563     /* set Samplerate */
564     core->outputStreamBasicDescription.mSampleRate = (Float64) as->freq;
565
566     status = coreaudio_set_streamformat(core->outputDeviceID,
567                                         &core->outputStreamBasicDescription);
568     if (status != kAudioHardwareNoError) {
569         coreaudio_logerr2 (status, typ, "Could not set samplerate %d\n",
570                            as->freq);
571         core->outputDeviceID = kAudioDeviceUnknown;
572         return -1;
573     }
574
575     /* set Callback */
576     core->ioprocid = NULL;
577     status = AudioDeviceCreateIOProcID(core->outputDeviceID,
578                                        audioDeviceIOProc,
579                                        hw,
580                                        &core->ioprocid);
581     if (status != kAudioHardwareNoError || core->ioprocid == NULL) {
582         coreaudio_logerr2 (status, typ, "Could not set IOProc\n");
583         core->outputDeviceID = kAudioDeviceUnknown;
584         return -1;
585     }
586
587     /* start Playback */
588     if (!isPlaying(core->outputDeviceID)) {
589         status = AudioDeviceStart(core->outputDeviceID, core->ioprocid);
590         if (status != kAudioHardwareNoError) {
591             coreaudio_logerr2 (status, typ, "Could not start playback\n");
592             AudioDeviceDestroyIOProcID(core->outputDeviceID, core->ioprocid);
593             core->outputDeviceID = kAudioDeviceUnknown;
594             return -1;
595         }
596     }
597
598     return 0;
599 }
600
601 static void coreaudio_fini_out (HWVoiceOut *hw)
602 {
603     OSStatus status;
604     int err;
605     coreaudioVoiceOut *core = (coreaudioVoiceOut *) hw;
606
607     if (!audio_is_cleaning_up()) {
608         /* stop playback */
609         if (isPlaying(core->outputDeviceID)) {
610             status = AudioDeviceStop(core->outputDeviceID, core->ioprocid);
611             if (status != kAudioHardwareNoError) {
612                 coreaudio_logerr (status, "Could not stop playback\n");
613             }
614         }
615
616         /* remove callback */
617         status = AudioDeviceDestroyIOProcID(core->outputDeviceID,
618                                             core->ioprocid);
619         if (status != kAudioHardwareNoError) {
620             coreaudio_logerr (status, "Could not remove IOProc\n");
621         }
622     }
623     core->outputDeviceID = kAudioDeviceUnknown;
624
625     /* destroy mutex */
626     err = pthread_mutex_destroy(&core->mutex);
627     if (err) {
628         dolog("Could not destroy mutex\nReason: %s\n", strerror (err));
629     }
630 }
631
632 static void coreaudio_enable_out(HWVoiceOut *hw, bool enable)
633 {
634     OSStatus status;
635     coreaudioVoiceOut *core = (coreaudioVoiceOut *) hw;
636
637     if (enable) {
638         /* start playback */
639         if (!isPlaying(core->outputDeviceID)) {
640             status = AudioDeviceStart(core->outputDeviceID, core->ioprocid);
641             if (status != kAudioHardwareNoError) {
642                 coreaudio_logerr (status, "Could not resume playback\n");
643             }
644         }
645     } else {
646         /* stop playback */
647         if (!audio_is_cleaning_up()) {
648             if (isPlaying(core->outputDeviceID)) {
649                 status = AudioDeviceStop(core->outputDeviceID,
650                                          core->ioprocid);
651                 if (status != kAudioHardwareNoError) {
652                     coreaudio_logerr (status, "Could not pause playback\n");
653                 }
654             }
655         }
656     }
657 }
658
659 static void *coreaudio_audio_init(Audiodev *dev)
660 {
661     return dev;
662 }
663
664 static void coreaudio_audio_fini (void *opaque)
665 {
666 }
667
668 static struct audio_pcm_ops coreaudio_pcm_ops = {
669     .init_out = coreaudio_init_out,
670     .fini_out = coreaudio_fini_out,
671   /* wrapper for audio_generic_write */
672     .write    = coreaudio_write,
673   /* wrapper for audio_generic_get_buffer_out */
674     .get_buffer_out = coreaudio_get_buffer_out,
675   /* wrapper for audio_generic_put_buffer_out */
676     .put_buffer_out = coreaudio_put_buffer_out,
677     .enable_out = coreaudio_enable_out
678 };
679
680 static struct audio_driver coreaudio_audio_driver = {
681     .name           = "coreaudio",
682     .descr          = "CoreAudio http://developer.apple.com/audio/coreaudio.html",
683     .init           = coreaudio_audio_init,
684     .fini           = coreaudio_audio_fini,
685     .pcm_ops        = &coreaudio_pcm_ops,
686     .can_be_default = 1,
687     .max_voices_out = 1,
688     .max_voices_in  = 0,
689     .voice_size_out = sizeof (coreaudioVoiceOut),
690     .voice_size_in  = 0
691 };
692
693 static void register_audio_coreaudio(void)
694 {
695     audio_driver_register(&coreaudio_audio_driver);
696 }
697 type_init(register_audio_coreaudio);
This page took 0.062236 seconds and 4 git commands to generate.