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
25 #include <CoreAudio/CoreAudio.h>
26 #include <string.h> /* strerror */
27 #include <pthread.h> /* pthread_X */
31 #define AUDIO_CAP "coreaudio"
32 #include "audio_int.h"
34 #define DEVICE_BUFFER_FRAMES (512)
42 typedef struct coreaudioVoiceOut
{
44 pthread_mutex_t mutex
;
45 AudioDeviceID outputDeviceID
;
46 UInt32 audioDevicePropertyBufferSize
;
47 AudioStreamBasicDescription outputStreamBasicDescription
;
54 static void coreaudio_logstatus (OSStatus status
)
59 case kAudioHardwareNoError
:
60 str
= "kAudioHardwareNoError";
63 case kAudioHardwareNotRunningError
:
64 str
= "kAudioHardwareNotRunningError";
67 case kAudioHardwareUnspecifiedError
:
68 str
= "kAudioHardwareUnspecifiedError";
71 case kAudioHardwareUnknownPropertyError
:
72 str
= "kAudioHardwareUnknownPropertyError";
75 case kAudioHardwareBadPropertySizeError
:
76 str
= "kAudioHardwareBadPropertySizeError";
79 case kAudioHardwareIllegalOperationError
:
80 str
= "kAudioHardwareIllegalOperationError";
83 case kAudioHardwareBadDeviceError
:
84 str
= "kAudioHardwareBadDeviceError";
87 case kAudioHardwareBadStreamError
:
88 str
= "kAudioHardwareBadStreamError";
91 case kAudioHardwareUnsupportedOperationError
:
92 str
= "kAudioHardwareUnsupportedOperationError";
95 case kAudioDeviceUnsupportedFormatError
:
96 str
= "kAudioDeviceUnsupportedFormatError";
99 case kAudioDevicePermissionsError
:
100 str
= "kAudioDevicePermissionsError";
104 AUD_log (AUDIO_CAP
, "Reason: status code %ld\n", status
);
108 AUD_log (AUDIO_CAP
, "Reason: %s\n", str
);
111 static void GCC_FMT_ATTR (2, 3) coreaudio_logerr (
120 AUD_log (AUDIO_CAP
, fmt
, ap
);
123 coreaudio_logstatus (status
);
126 static void GCC_FMT_ATTR (3, 4) coreaudio_logerr2 (
135 AUD_log (AUDIO_CAP
, "Can not initialize %s\n", typ
);
138 AUD_vlog (AUDIO_CAP
, fmt
, ap
);
141 coreaudio_logstatus (status
);
144 static int coreaudio_lock (coreaudioVoiceOut
*core
, const char *fn_name
)
148 err
= pthread_mutex_lock (&core
->mutex
);
150 dolog ("Can not lock voice for %s\nReason: %s\n",
151 fn_name
, strerror (err
));
157 static int coreaudio_unlock (coreaudioVoiceOut
*core
, const char *fn_name
)
161 err
= pthread_mutex_unlock (&core
->mutex
);
163 dolog ("Can not unlock voice for %s\nReason: %s\n",
164 fn_name
, strerror (err
));
170 static int coreaudio_run_out (HWVoiceOut
*hw
)
173 coreaudioVoiceOut
*core
= (coreaudioVoiceOut
*) hw
;
175 if (coreaudio_lock (core
, "coreaudio_run_out")) {
179 live
= audio_pcm_hw_get_live_out (hw
);
181 if (core
->decr
> live
) {
182 ldebug ("core->decr %d live %d core->live %d\n",
188 decr
= audio_MIN (core
->decr
, live
);
191 core
->live
= live
- decr
;
192 hw
->rpos
= core
->rpos
;
194 coreaudio_unlock (core
, "coreaudio_run_out");
198 /* callback to feed audiooutput buffer */
199 static OSStatus
audioDeviceIOProc(
200 AudioDeviceID inDevice
,
201 const AudioTimeStamp
* inNow
,
202 const AudioBufferList
* inInputData
,
203 const AudioTimeStamp
* inInputTime
,
204 AudioBufferList
* outOutputData
,
205 const AudioTimeStamp
* inOutputTime
,
208 unsigned int frame
, frameCount
;
209 float *out
= outOutputData
->mBuffers
[0].mData
;
210 HWVoiceOut
*hw
= hwptr
;
211 coreaudioVoiceOut
*core
= (coreaudioVoiceOut
*) hwptr
;
216 const float scale
= 1.f
/ UINT_MAX
;
218 const float scale
= UINT_MAX
;
222 if (coreaudio_lock (core
, "audioDeviceIOProc")) {
227 frameCount
= conf
.buffer_frames
;
230 /* if there are not enough samples, set signal and return */
231 if (live
< frameCount
) {
233 coreaudio_unlock (core
, "audioDeviceIOProc(empty)");
238 src
= hw
->mix_buf
+ rpos
;
241 for (frame
= 0; frame
< frameCount
; frame
++) {
243 *out
++ = src
[frame
].l
; /* left channel */
244 *out
++ = src
[frame
].r
; /* right channel */
247 *out
++ = src
[frame
].l
* scale
; /* left channel */
248 *out
++ = src
[frame
].r
* scale
; /* right channel */
250 *out
++ = src
[frame
].l
/ scale
; /* left channel */
251 *out
++ = src
[frame
].r
/ scale
; /* right channel */
257 mixeng_clear (src
, frameCount
);
258 rpos
= (rpos
+ frameCount
) % hw
->samples
;
259 core
->decr
= frameCount
;
262 coreaudio_unlock (core
, "audioDeviceIOProc");
266 static int coreaudio_write (SWVoiceOut
*sw
, void *buf
, int len
)
268 return audio_pcm_sw_write (sw
, buf
, len
);
271 static int coreaudio_init_out (HWVoiceOut
*hw
, int freq
,
272 int nchannels
, audfmt_e fmt
)
275 coreaudioVoiceOut
*core
= (coreaudioVoiceOut
*) hw
;
280 const char *typ
= "DAC";
283 err
= pthread_mutex_init(&core
->mutex
, NULL
);
285 dolog("Can not create mutex\nReason: %s\n", strerror (err
));
289 if (fmt
== AUD_FMT_S16
|| fmt
== AUD_FMT_U16
) {
294 audio_pcm_init_info (
299 /* Following is irrelevant actually since we do not use
300 mixengs clipping routines */
301 audio_need_to_swap_endian (endianess
)
303 hw
->bufsize
= 4 * conf
.buffer_frames
* nchannels
* bits
;
305 /* open default output device */
306 propertySize
= sizeof(core
->outputDeviceID
);
307 status
= AudioHardwareGetProperty(
308 kAudioHardwarePropertyDefaultOutputDevice
,
310 &core
->outputDeviceID
);
311 if (status
!= kAudioHardwareNoError
) {
312 coreaudio_logerr2 (status
, typ
,
313 "Can not get default output Device\n");
316 if (core
->outputDeviceID
== kAudioDeviceUnknown
) {
317 dolog ("Can not initialize %s - Unknown Audiodevice\n", typ
);
321 /* set Buffersize to conf.buffer_frames frames */
322 propertySize
= sizeof(core
->audioDevicePropertyBufferSize
);
323 core
->audioDevicePropertyBufferSize
=
324 conf
.buffer_frames
* sizeof(float) * 2;
325 status
= AudioDeviceSetProperty(
326 core
->outputDeviceID
,
330 kAudioDevicePropertyBufferSize
,
332 &core
->audioDevicePropertyBufferSize
);
333 if (status
!= kAudioHardwareNoError
) {
334 coreaudio_logerr2 (status
, typ
,
335 "Can not set device buffer size %d\n",
336 kAudioDevicePropertyBufferSize
);
341 propertySize
= sizeof(core
->audioDevicePropertyBufferSize
);
342 status
= AudioDeviceGetProperty(
343 core
->outputDeviceID
,
346 kAudioDevicePropertyBufferSize
,
348 &core
->audioDevicePropertyBufferSize
);
349 if (status
!= kAudioHardwareNoError
) {
350 coreaudio_logerr2 (status
, typ
, "Can not get device buffer size\n");
354 /* get StreamFormat */
355 propertySize
= sizeof(core
->outputStreamBasicDescription
);
356 status
= AudioDeviceGetProperty(
357 core
->outputDeviceID
,
360 kAudioDevicePropertyStreamFormat
,
362 &core
->outputStreamBasicDescription
);
363 if (status
!= kAudioHardwareNoError
) {
364 coreaudio_logerr2 (status
, typ
,
365 "Can not get Device Stream properties\n");
366 core
->outputDeviceID
= kAudioDeviceUnknown
;
371 core
->outputStreamBasicDescription
.mSampleRate
= (Float64
)freq
;
372 propertySize
= sizeof(core
->outputStreamBasicDescription
);
373 status
= AudioDeviceSetProperty(
374 core
->outputDeviceID
,
378 kAudioDevicePropertyStreamFormat
,
380 &core
->outputStreamBasicDescription
);
381 if (status
!= kAudioHardwareNoError
) {
382 coreaudio_logerr2 (status
, typ
, "Can not set samplerate %d\n", freq
);
383 core
->outputDeviceID
= kAudioDeviceUnknown
;
388 status
= AudioDeviceAddIOProc(core
->outputDeviceID
, audioDeviceIOProc
, hw
);
389 if (status
!= kAudioHardwareNoError
) {
390 coreaudio_logerr2 (status
, typ
, "Can not set IOProc\n");
391 core
->outputDeviceID
= kAudioDeviceUnknown
;
396 if (!core
->isPlaying
) {
397 status
= AudioDeviceStart(core
->outputDeviceID
, audioDeviceIOProc
);
398 if (status
!= kAudioHardwareNoError
) {
399 coreaudio_logerr2 (status
, typ
, "Can not start playback\n");
400 AudioDeviceRemoveIOProc(core
->outputDeviceID
, audioDeviceIOProc
);
401 core
->outputDeviceID
= kAudioDeviceUnknown
;
410 static void coreaudio_fini_out (HWVoiceOut
*hw
)
414 coreaudioVoiceOut
*core
= (coreaudioVoiceOut
*) hw
;
417 if (core
->isPlaying
) {
418 status
= AudioDeviceStop(core
->outputDeviceID
, audioDeviceIOProc
);
419 if (status
!= kAudioHardwareNoError
) {
420 coreaudio_logerr (status
, "Can not stop playback\n");
425 /* remove callback */
426 status
= AudioDeviceRemoveIOProc(core
->outputDeviceID
, audioDeviceIOProc
);
427 if (status
!= kAudioHardwareNoError
) {
428 coreaudio_logerr (status
, "Can not remove IOProc\n");
430 core
->outputDeviceID
= kAudioDeviceUnknown
;
433 err
= pthread_mutex_destroy(&core
->mutex
);
435 dolog("Can not destroy mutex\nReason: %s\n", strerror (err
));
439 static int coreaudio_ctl_out (HWVoiceOut
*hw
, int cmd
, ...)
442 coreaudioVoiceOut
*core
= (coreaudioVoiceOut
*) hw
;
447 if (!core
->isPlaying
) {
448 status
= AudioDeviceStart(core
->outputDeviceID
, audioDeviceIOProc
);
449 if (status
!= kAudioHardwareNoError
) {
450 coreaudio_logerr (status
, "Can not unpause playback\n");
458 if (core
->isPlaying
) {
459 status
= AudioDeviceStop(core
->outputDeviceID
, audioDeviceIOProc
);
460 if (status
!= kAudioHardwareNoError
) {
461 coreaudio_logerr (status
, "Can not pause playback\n");
470 static void *coreaudio_audio_init (void)
472 return &coreaudio_audio_init
;
475 static void coreaudio_audio_fini (void *opaque
)
480 static struct audio_option coreaudio_options
[] = {
481 {"BUFFER_SIZE", AUD_OPT_INT
, &conf
.buffer_frames
,
482 "Size of the buffer in frames", NULL
, 0},
483 {NULL
, 0, NULL
, NULL
, NULL
, 0}
486 static struct audio_pcm_ops coreaudio_pcm_ops
= {
500 struct audio_driver coreaudio_audio_driver
= {
501 INIT_FIELD (name
= ) "coreaudio",
502 INIT_FIELD (descr
= )
503 "CoreAudio http://developer.apple.com/audio/coreaudio.html",
504 INIT_FIELD (options
= ) coreaudio_options
,
505 INIT_FIELD (init
= ) coreaudio_audio_init
,
506 INIT_FIELD (fini
= ) coreaudio_audio_fini
,
507 INIT_FIELD (pcm_ops
= ) &coreaudio_pcm_ops
,
508 INIT_FIELD (can_be_default
= ) 1,
509 INIT_FIELD (max_voices_out
= ) 1,
510 INIT_FIELD (max_voices_in
= ) 0,
511 INIT_FIELD (voice_size_out
= ) sizeof (coreaudioVoiceOut
),
512 INIT_FIELD (voice_size_in
= ) 0