ia64/xen-unstable

view tools/ioemu/audio/coreaudio.c @ 15841:c5f735271e22

[IA64] Foreign p2m: Fix vti domain builder.

It should set arch_domain::convmem_end.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
author Alex Williamson <alex.williamson@hp.com>
date Thu Sep 06 13:48:43 2007 -0600 (2007-09-06)
parents 08a11694b109
children
line source
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 */
25 #include <CoreAudio/CoreAudio.h>
26 #include <string.h> /* strerror */
27 #include <pthread.h> /* pthread_X */
29 #include "vl.h"
31 #define AUDIO_CAP "coreaudio"
32 #include "audio_int.h"
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 };
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;
56 static void coreaudio_logstatus (OSStatus status)
57 {
58 char *str = "BUG";
60 switch(status) {
61 case kAudioHardwareNoError:
62 str = "kAudioHardwareNoError";
63 break;
65 case kAudioHardwareNotRunningError:
66 str = "kAudioHardwareNotRunningError";
67 break;
69 case kAudioHardwareUnspecifiedError:
70 str = "kAudioHardwareUnspecifiedError";
71 break;
73 case kAudioHardwareUnknownPropertyError:
74 str = "kAudioHardwareUnknownPropertyError";
75 break;
77 case kAudioHardwareBadPropertySizeError:
78 str = "kAudioHardwareBadPropertySizeError";
79 break;
81 case kAudioHardwareIllegalOperationError:
82 str = "kAudioHardwareIllegalOperationError";
83 break;
85 case kAudioHardwareBadDeviceError:
86 str = "kAudioHardwareBadDeviceError";
87 break;
89 case kAudioHardwareBadStreamError:
90 str = "kAudioHardwareBadStreamError";
91 break;
93 case kAudioHardwareUnsupportedOperationError:
94 str = "kAudioHardwareUnsupportedOperationError";
95 break;
97 case kAudioDeviceUnsupportedFormatError:
98 str = "kAudioDeviceUnsupportedFormatError";
99 break;
101 case kAudioDevicePermissionsError:
102 str = "kAudioDevicePermissionsError";
103 break;
105 default:
106 AUD_log (AUDIO_CAP, "Reason: status code %ld\n", status);
107 return;
108 }
110 AUD_log (AUDIO_CAP, "Reason: %s\n", str);
111 }
113 static void GCC_FMT_ATTR (2, 3) coreaudio_logerr (
114 OSStatus status,
115 const char *fmt,
116 ...
117 )
118 {
119 va_list ap;
121 va_start (ap, fmt);
122 AUD_log (AUDIO_CAP, fmt, ap);
123 va_end (ap);
125 coreaudio_logstatus (status);
126 }
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;
137 AUD_log (AUDIO_CAP, "Could not initialize %s\n", typ);
139 va_start (ap, fmt);
140 AUD_vlog (AUDIO_CAP, fmt, ap);
141 va_end (ap);
143 coreaudio_logstatus (status);
144 }
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 }
161 static void coreaudio_atexit (void)
162 {
163 conf.isAtexit = 1;
164 }
166 static int coreaudio_lock (coreaudioVoiceOut *core, const char *fn_name)
167 {
168 int err;
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 }
179 static int coreaudio_unlock (coreaudioVoiceOut *core, const char *fn_name)
180 {
181 int err;
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 }
192 static int coreaudio_run_out (HWVoiceOut *hw)
193 {
194 int live, decr;
195 coreaudioVoiceOut *core = (coreaudioVoiceOut *) hw;
197 if (coreaudio_lock (core, "coreaudio_run_out")) {
198 return 0;
199 }
201 live = audio_pcm_hw_get_live_out (hw);
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 }
210 decr = audio_MIN (core->decr, live);
211 core->decr -= decr;
213 core->live = live - decr;
214 hw->rpos = core->rpos;
216 coreaudio_unlock (core, "coreaudio_run_out");
217 return decr;
218 }
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
244 if (coreaudio_lock (core, "audioDeviceIOProc")) {
245 inInputTime = 0;
246 return 0;
247 }
249 frameCount = core->audioDevicePropertyBufferFrameSize;
250 live = core->live;
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 }
259 rpos = core->rpos;
260 src = hw->mix_buf + rpos;
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 }
278 rpos = (rpos + frameCount) % hw->samples;
279 core->decr += frameCount;
280 core->rpos = rpos;
282 coreaudio_unlock (core, "audioDeviceIOProc");
283 return 0;
284 }
286 static int coreaudio_write (SWVoiceOut *sw, void *buf, int len)
287 {
288 return audio_pcm_sw_write (sw, buf, len);
289 }
291 static int coreaudio_init_out (HWVoiceOut *hw, audsettings_t *as)
292 {
293 OSStatus status;
294 coreaudioVoiceOut *core = (coreaudioVoiceOut *) hw;
295 UInt32 propertySize;
296 int err;
297 int bits = 8;
298 const char *typ = "playback";
299 AudioValueRange frameRange;
301 /* create mutex */
302 err = pthread_mutex_init(&core->mutex, NULL);
303 if (err) {
304 dolog("Could not create mutex\nReason: %s\n", strerror (err));
305 return -1;
306 }
308 if (as->fmt == AUD_FMT_S16 || as->fmt == AUD_FMT_U16) {
309 bits = 16;
310 }
312 audio_pcm_init_info (&hw->info, as);
314 /* open default output device */
315 propertySize = sizeof(core->outputDeviceID);
316 status = AudioHardwareGetProperty(
317 kAudioHardwarePropertyDefaultOutputDevice,
318 &propertySize,
319 &core->outputDeviceID);
320 if (status != kAudioHardwareNoError) {
321 coreaudio_logerr2 (status, typ,
322 "Could not get default output Device\n");
323 return -1;
324 }
325 if (core->outputDeviceID == kAudioDeviceUnknown) {
326 dolog ("Could not initialize %s - Unknown Audiodevice\n", typ);
327 return -1;
328 }
330 /* get minimum and maximum buffer frame sizes */
331 propertySize = sizeof(frameRange);
332 status = AudioDeviceGetProperty(
333 core->outputDeviceID,
334 0,
335 0,
336 kAudioDevicePropertyBufferFrameSizeRange,
337 &propertySize,
338 &frameRange);
339 if (status != kAudioHardwareNoError) {
340 coreaudio_logerr2 (status, typ,
341 "Could not get device buffer frame range\n");
342 return -1;
343 }
345 if (frameRange.mMinimum > conf.buffer_frames) {
346 core->audioDevicePropertyBufferFrameSize = (UInt32) frameRange.mMinimum;
347 dolog ("warning: Upsizing Buffer Frames to %f\n", frameRange.mMinimum);
348 }
349 else if (frameRange.mMaximum < conf.buffer_frames) {
350 core->audioDevicePropertyBufferFrameSize = (UInt32) frameRange.mMaximum;
351 dolog ("warning: Downsizing Buffer Frames to %f\n", frameRange.mMaximum);
352 }
353 else {
354 core->audioDevicePropertyBufferFrameSize = conf.buffer_frames;
355 }
357 /* set Buffer Frame Size */
358 propertySize = sizeof(core->audioDevicePropertyBufferFrameSize);
359 status = AudioDeviceSetProperty(
360 core->outputDeviceID,
361 NULL,
362 0,
363 false,
364 kAudioDevicePropertyBufferFrameSize,
365 propertySize,
366 &core->audioDevicePropertyBufferFrameSize);
367 if (status != kAudioHardwareNoError) {
368 coreaudio_logerr2 (status, typ,
369 "Could not set device buffer frame size %ld\n",
370 core->audioDevicePropertyBufferFrameSize);
371 return -1;
372 }
374 /* get Buffer Frame Size */
375 propertySize = sizeof(core->audioDevicePropertyBufferFrameSize);
376 status = AudioDeviceGetProperty(
377 core->outputDeviceID,
378 0,
379 false,
380 kAudioDevicePropertyBufferFrameSize,
381 &propertySize,
382 &core->audioDevicePropertyBufferFrameSize);
383 if (status != kAudioHardwareNoError) {
384 coreaudio_logerr2 (status, typ,
385 "Could not get device buffer frame size\n");
386 return -1;
387 }
388 hw->samples = conf.nbuffers * core->audioDevicePropertyBufferFrameSize;
390 /* get StreamFormat */
391 propertySize = sizeof(core->outputStreamBasicDescription);
392 status = AudioDeviceGetProperty(
393 core->outputDeviceID,
394 0,
395 false,
396 kAudioDevicePropertyStreamFormat,
397 &propertySize,
398 &core->outputStreamBasicDescription);
399 if (status != kAudioHardwareNoError) {
400 coreaudio_logerr2 (status, typ,
401 "Could not get Device Stream properties\n");
402 core->outputDeviceID = kAudioDeviceUnknown;
403 return -1;
404 }
406 /* set Samplerate */
407 core->outputStreamBasicDescription.mSampleRate = (Float64) as->freq;
408 propertySize = sizeof(core->outputStreamBasicDescription);
409 status = AudioDeviceSetProperty(
410 core->outputDeviceID,
411 0,
412 0,
413 0,
414 kAudioDevicePropertyStreamFormat,
415 propertySize,
416 &core->outputStreamBasicDescription);
417 if (status != kAudioHardwareNoError) {
418 coreaudio_logerr2 (status, typ, "Could not set samplerate %d\n",
419 as->freq);
420 core->outputDeviceID = kAudioDeviceUnknown;
421 return -1;
422 }
424 /* set Callback */
425 status = AudioDeviceAddIOProc(core->outputDeviceID, audioDeviceIOProc, hw);
426 if (status != kAudioHardwareNoError) {
427 coreaudio_logerr2 (status, typ, "Could not set IOProc\n");
428 core->outputDeviceID = kAudioDeviceUnknown;
429 return -1;
430 }
432 /* start Playback */
433 if (!isPlaying(core->outputDeviceID)) {
434 status = AudioDeviceStart(core->outputDeviceID, audioDeviceIOProc);
435 if (status != kAudioHardwareNoError) {
436 coreaudio_logerr2 (status, typ, "Could not start playback\n");
437 AudioDeviceRemoveIOProc(core->outputDeviceID, audioDeviceIOProc);
438 core->outputDeviceID = kAudioDeviceUnknown;
439 return -1;
440 }
441 }
443 return 0;
444 }
446 static void coreaudio_fini_out (HWVoiceOut *hw)
447 {
448 OSStatus status;
449 int err;
450 coreaudioVoiceOut *core = (coreaudioVoiceOut *) hw;
452 if (!conf.isAtexit) {
453 /* stop playback */
454 if (isPlaying(core->outputDeviceID)) {
455 status = AudioDeviceStop(core->outputDeviceID, audioDeviceIOProc);
456 if (status != kAudioHardwareNoError) {
457 coreaudio_logerr (status, "Could not stop playback\n");
458 }
459 }
461 /* remove callback */
462 status = AudioDeviceRemoveIOProc(core->outputDeviceID,
463 audioDeviceIOProc);
464 if (status != kAudioHardwareNoError) {
465 coreaudio_logerr (status, "Could not remove IOProc\n");
466 }
467 }
468 core->outputDeviceID = kAudioDeviceUnknown;
470 /* destroy mutex */
471 err = pthread_mutex_destroy(&core->mutex);
472 if (err) {
473 dolog("Could not destroy mutex\nReason: %s\n", strerror (err));
474 }
475 }
477 static int coreaudio_ctl_out (HWVoiceOut *hw, int cmd, ...)
478 {
479 OSStatus status;
480 coreaudioVoiceOut *core = (coreaudioVoiceOut *) hw;
482 switch (cmd) {
483 case VOICE_ENABLE:
484 /* start playback */
485 if (!isPlaying(core->outputDeviceID)) {
486 status = AudioDeviceStart(core->outputDeviceID, audioDeviceIOProc);
487 if (status != kAudioHardwareNoError) {
488 coreaudio_logerr (status, "Could not resume playback\n");
489 }
490 }
491 break;
493 case VOICE_DISABLE:
494 /* stop playback */
495 if (!conf.isAtexit) {
496 if (isPlaying(core->outputDeviceID)) {
497 status = AudioDeviceStop(core->outputDeviceID, audioDeviceIOProc);
498 if (status != kAudioHardwareNoError) {
499 coreaudio_logerr (status, "Could not pause playback\n");
500 }
501 }
502 }
503 break;
504 }
505 return 0;
506 }
508 static void *coreaudio_audio_init (void)
509 {
510 atexit(coreaudio_atexit);
511 return &coreaudio_audio_init;
512 }
514 static void coreaudio_audio_fini (void *opaque)
515 {
516 (void) opaque;
517 }
519 static struct audio_option coreaudio_options[] = {
520 {"BUFFER_SIZE", AUD_OPT_INT, &conf.buffer_frames,
521 "Size of the buffer in frames", NULL, 0},
522 {"BUFFER_COUNT", AUD_OPT_INT, &conf.nbuffers,
523 "Number of buffers", NULL, 0},
524 {NULL, 0, NULL, NULL, NULL, 0}
525 };
527 static struct audio_pcm_ops coreaudio_pcm_ops = {
528 coreaudio_init_out,
529 coreaudio_fini_out,
530 coreaudio_run_out,
531 coreaudio_write,
532 coreaudio_ctl_out,
534 NULL,
535 NULL,
536 NULL,
537 NULL,
538 NULL
539 };
541 struct audio_driver coreaudio_audio_driver = {
542 INIT_FIELD (name = ) "coreaudio",
543 INIT_FIELD (descr = )
544 "CoreAudio http://developer.apple.com/audio/coreaudio.html",
545 INIT_FIELD (options = ) coreaudio_options,
546 INIT_FIELD (init = ) coreaudio_audio_init,
547 INIT_FIELD (fini = ) coreaudio_audio_fini,
548 INIT_FIELD (pcm_ops = ) &coreaudio_pcm_ops,
549 INIT_FIELD (can_be_default = ) 1,
550 INIT_FIELD (max_voices_out = ) 1,
551 INIT_FIELD (max_voices_in = ) 0,
552 INIT_FIELD (voice_size_out = ) sizeof (coreaudioVoiceOut),
553 INIT_FIELD (voice_size_in = ) 0
554 };