31 |
#define AUDIO_CAP "coreaudio" |
#define AUDIO_CAP "coreaudio" |
32 |
#include "audio_int.h" |
#include "audio_int.h" |
33 |
|
|
|
#define DEVICE_BUFFER_FRAMES (512) |
|
|
|
|
34 |
struct { |
struct { |
35 |
int buffer_frames; |
int buffer_frames; |
36 |
} conf = { |
} conf = { |
130 |
{ |
{ |
131 |
va_list ap; |
va_list ap; |
132 |
|
|
133 |
AUD_log (AUDIO_CAP, "Can not initialize %s\n", typ); |
AUD_log (AUDIO_CAP, "Could not initialize %s\n", typ); |
134 |
|
|
135 |
va_start (ap, fmt); |
va_start (ap, fmt); |
136 |
AUD_vlog (AUDIO_CAP, fmt, ap); |
AUD_vlog (AUDIO_CAP, fmt, ap); |
145 |
|
|
146 |
err = pthread_mutex_lock (&core->mutex); |
err = pthread_mutex_lock (&core->mutex); |
147 |
if (err) { |
if (err) { |
148 |
dolog ("Can not lock voice for %s\nReason: %s\n", |
dolog ("Could not lock voice for %s\nReason: %s\n", |
149 |
fn_name, strerror (err)); |
fn_name, strerror (err)); |
150 |
return -1; |
return -1; |
151 |
} |
} |
158 |
|
|
159 |
err = pthread_mutex_unlock (&core->mutex); |
err = pthread_mutex_unlock (&core->mutex); |
160 |
if (err) { |
if (err) { |
161 |
dolog ("Can not unlock voice for %s\nReason: %s\n", |
dolog ("Could not unlock voice for %s\nReason: %s\n", |
162 |
fn_name, strerror (err)); |
fn_name, strerror (err)); |
163 |
return -1; |
return -1; |
164 |
} |
} |
266 |
return audio_pcm_sw_write (sw, buf, len); |
return audio_pcm_sw_write (sw, buf, len); |
267 |
} |
} |
268 |
|
|
269 |
static int coreaudio_init_out (HWVoiceOut *hw, int freq, |
static int coreaudio_init_out (HWVoiceOut *hw, audsettings_t *as) |
|
int nchannels, audfmt_e fmt) |
|
270 |
{ |
{ |
271 |
OSStatus status; |
OSStatus status; |
272 |
coreaudioVoiceOut *core = (coreaudioVoiceOut *) hw; |
coreaudioVoiceOut *core = (coreaudioVoiceOut *) hw; |
279 |
/* create mutex */ |
/* create mutex */ |
280 |
err = pthread_mutex_init(&core->mutex, NULL); |
err = pthread_mutex_init(&core->mutex, NULL); |
281 |
if (err) { |
if (err) { |
282 |
dolog("Can not create mutex\nReason: %s\n", strerror (err)); |
dolog("Could not create mutex\nReason: %s\n", strerror (err)); |
283 |
return -1; |
return -1; |
284 |
} |
} |
285 |
|
|
286 |
if (fmt == AUD_FMT_S16 || fmt == AUD_FMT_U16) { |
if (as->fmt == AUD_FMT_S16 || as->fmt == AUD_FMT_U16) { |
287 |
bits = 16; |
bits = 16; |
288 |
endianess = 1; |
endianess = 1; |
289 |
} |
} |
290 |
|
|
291 |
audio_pcm_init_info ( |
audio_pcm_init_info ( |
292 |
&hw->info, |
&hw->info, |
293 |
freq, |
as, |
|
nchannels, |
|
|
fmt, |
|
294 |
/* Following is irrelevant actually since we do not use |
/* Following is irrelevant actually since we do not use |
295 |
mixengs clipping routines */ |
mixengs clipping routines */ |
296 |
audio_need_to_swap_endian (endianess) |
audio_need_to_swap_endian (endianess) |
297 |
); |
); |
|
hw->bufsize = 4 * conf.buffer_frames * nchannels * bits; |
|
298 |
|
|
299 |
/* open default output device */ |
/* open default output device */ |
300 |
propertySize = sizeof(core->outputDeviceID); |
propertySize = sizeof(core->outputDeviceID); |
304 |
&core->outputDeviceID); |
&core->outputDeviceID); |
305 |
if (status != kAudioHardwareNoError) { |
if (status != kAudioHardwareNoError) { |
306 |
coreaudio_logerr2 (status, typ, |
coreaudio_logerr2 (status, typ, |
307 |
"Can not get default output Device\n"); |
"Could not get default output Device\n"); |
308 |
return -1; |
return -1; |
309 |
} |
} |
310 |
if (core->outputDeviceID == kAudioDeviceUnknown) { |
if (core->outputDeviceID == kAudioDeviceUnknown) { |
311 |
dolog ("Can not initialize %s - Unknown Audiodevice\n", typ); |
dolog ("Could not initialize %s - Unknown Audiodevice\n", typ); |
312 |
return -1; |
return -1; |
313 |
} |
} |
314 |
|
|
315 |
/* set Buffersize to conf.buffer_frames frames */ |
/* set Buffersize to conf.buffer_frames frames */ |
316 |
propertySize = sizeof(core->audioDevicePropertyBufferSize); |
propertySize = sizeof(core->audioDevicePropertyBufferSize); |
317 |
core->audioDevicePropertyBufferSize = |
core->audioDevicePropertyBufferSize = |
318 |
conf.buffer_frames * sizeof(float) * 2; |
conf.buffer_frames * sizeof(float) << (as->nchannels == 2); |
319 |
status = AudioDeviceSetProperty( |
status = AudioDeviceSetProperty( |
320 |
core->outputDeviceID, |
core->outputDeviceID, |
321 |
NULL, |
NULL, |
326 |
&core->audioDevicePropertyBufferSize); |
&core->audioDevicePropertyBufferSize); |
327 |
if (status != kAudioHardwareNoError) { |
if (status != kAudioHardwareNoError) { |
328 |
coreaudio_logerr2 (status, typ, |
coreaudio_logerr2 (status, typ, |
329 |
"Can not set device buffer size %d\n", |
"Could not set device buffer size %d\n", |
330 |
kAudioDevicePropertyBufferSize); |
kAudioDevicePropertyBufferSize); |
331 |
return -1; |
return -1; |
332 |
} |
} |
341 |
&propertySize, |
&propertySize, |
342 |
&core->audioDevicePropertyBufferSize); |
&core->audioDevicePropertyBufferSize); |
343 |
if (status != kAudioHardwareNoError) { |
if (status != kAudioHardwareNoError) { |
344 |
coreaudio_logerr2 (status, typ, "Can not get device buffer size\n"); |
coreaudio_logerr2 (status, typ, "Could not get device buffer size\n"); |
345 |
return -1; |
return -1; |
346 |
} |
} |
347 |
|
hw->samples = (core->audioDevicePropertyBufferSize / sizeof (float)) |
348 |
|
>> (as->nchannels == 2); |
349 |
|
|
350 |
/* get StreamFormat */ |
/* get StreamFormat */ |
351 |
propertySize = sizeof(core->outputStreamBasicDescription); |
propertySize = sizeof(core->outputStreamBasicDescription); |
358 |
&core->outputStreamBasicDescription); |
&core->outputStreamBasicDescription); |
359 |
if (status != kAudioHardwareNoError) { |
if (status != kAudioHardwareNoError) { |
360 |
coreaudio_logerr2 (status, typ, |
coreaudio_logerr2 (status, typ, |
361 |
"Can not get Device Stream properties\n"); |
"Could not get Device Stream properties\n"); |
362 |
core->outputDeviceID = kAudioDeviceUnknown; |
core->outputDeviceID = kAudioDeviceUnknown; |
363 |
return -1; |
return -1; |
364 |
} |
} |
365 |
|
|
366 |
/* set Samplerate */ |
/* set Samplerate */ |
367 |
core->outputStreamBasicDescription.mSampleRate = (Float64)freq; |
core->outputStreamBasicDescription.mSampleRate = (Float64)as->freq; |
368 |
propertySize = sizeof(core->outputStreamBasicDescription); |
propertySize = sizeof(core->outputStreamBasicDescription); |
369 |
status = AudioDeviceSetProperty( |
status = AudioDeviceSetProperty( |
370 |
core->outputDeviceID, |
core->outputDeviceID, |
375 |
propertySize, |
propertySize, |
376 |
&core->outputStreamBasicDescription); |
&core->outputStreamBasicDescription); |
377 |
if (status != kAudioHardwareNoError) { |
if (status != kAudioHardwareNoError) { |
378 |
coreaudio_logerr2 (status, typ, "Can not set samplerate %d\n", freq); |
coreaudio_logerr2 (status, typ, "Could not set samplerate %d\n", freq); |
379 |
core->outputDeviceID = kAudioDeviceUnknown; |
core->outputDeviceID = kAudioDeviceUnknown; |
380 |
return -1; |
return -1; |
381 |
} |
} |
383 |
/* set Callback */ |
/* set Callback */ |
384 |
status = AudioDeviceAddIOProc(core->outputDeviceID, audioDeviceIOProc, hw); |
status = AudioDeviceAddIOProc(core->outputDeviceID, audioDeviceIOProc, hw); |
385 |
if (status != kAudioHardwareNoError) { |
if (status != kAudioHardwareNoError) { |
386 |
coreaudio_logerr2 (status, typ, "Can not set IOProc\n"); |
coreaudio_logerr2 (status, typ, "Could not set IOProc\n"); |
387 |
core->outputDeviceID = kAudioDeviceUnknown; |
core->outputDeviceID = kAudioDeviceUnknown; |
388 |
return -1; |
return -1; |
389 |
} |
} |
392 |
if (!core->isPlaying) { |
if (!core->isPlaying) { |
393 |
status = AudioDeviceStart(core->outputDeviceID, audioDeviceIOProc); |
status = AudioDeviceStart(core->outputDeviceID, audioDeviceIOProc); |
394 |
if (status != kAudioHardwareNoError) { |
if (status != kAudioHardwareNoError) { |
395 |
coreaudio_logerr2 (status, typ, "Can not start playback\n"); |
coreaudio_logerr2 (status, typ, "Could not start playback\n"); |
396 |
AudioDeviceRemoveIOProc(core->outputDeviceID, audioDeviceIOProc); |
AudioDeviceRemoveIOProc(core->outputDeviceID, audioDeviceIOProc); |
397 |
core->outputDeviceID = kAudioDeviceUnknown; |
core->outputDeviceID = kAudioDeviceUnknown; |
398 |
return -1; |
return -1; |
413 |
if (core->isPlaying) { |
if (core->isPlaying) { |
414 |
status = AudioDeviceStop(core->outputDeviceID, audioDeviceIOProc); |
status = AudioDeviceStop(core->outputDeviceID, audioDeviceIOProc); |
415 |
if (status != kAudioHardwareNoError) { |
if (status != kAudioHardwareNoError) { |
416 |
coreaudio_logerr (status, "Can not stop playback\n"); |
coreaudio_logerr (status, "Could not stop playback\n"); |
417 |
} |
} |
418 |
core->isPlaying = 0; |
core->isPlaying = 0; |
419 |
} |
} |
421 |
/* remove callback */ |
/* remove callback */ |
422 |
status = AudioDeviceRemoveIOProc(core->outputDeviceID, audioDeviceIOProc); |
status = AudioDeviceRemoveIOProc(core->outputDeviceID, audioDeviceIOProc); |
423 |
if (status != kAudioHardwareNoError) { |
if (status != kAudioHardwareNoError) { |
424 |
coreaudio_logerr (status, "Can not remove IOProc\n"); |
coreaudio_logerr (status, "Could not remove IOProc\n"); |
425 |
} |
} |
426 |
core->outputDeviceID = kAudioDeviceUnknown; |
core->outputDeviceID = kAudioDeviceUnknown; |
427 |
|
|
428 |
/* destroy mutex */ |
/* destroy mutex */ |
429 |
err = pthread_mutex_destroy(&core->mutex); |
err = pthread_mutex_destroy(&core->mutex); |
430 |
if (err) { |
if (err) { |
431 |
dolog("Can not destroy mutex\nReason: %s\n", strerror (err)); |
dolog("Could not destroy mutex\nReason: %s\n", strerror (err)); |
432 |
} |
} |
433 |
} |
} |
434 |
|
|
443 |
if (!core->isPlaying) { |
if (!core->isPlaying) { |
444 |
status = AudioDeviceStart(core->outputDeviceID, audioDeviceIOProc); |
status = AudioDeviceStart(core->outputDeviceID, audioDeviceIOProc); |
445 |
if (status != kAudioHardwareNoError) { |
if (status != kAudioHardwareNoError) { |
446 |
coreaudio_logerr (status, "Can not unpause playback\n"); |
coreaudio_logerr (status, "Could not unpause playback\n"); |
447 |
} |
} |
448 |
core->isPlaying = 1; |
core->isPlaying = 1; |
449 |
} |
} |
454 |
if (core->isPlaying) { |
if (core->isPlaying) { |
455 |
status = AudioDeviceStop(core->outputDeviceID, audioDeviceIOProc); |
status = AudioDeviceStop(core->outputDeviceID, audioDeviceIOProc); |
456 |
if (status != kAudioHardwareNoError) { |
if (status != kAudioHardwareNoError) { |
457 |
coreaudio_logerr (status, "Can not pause playback\n"); |
coreaudio_logerr (status, "Could not pause playback\n"); |
458 |
} |
} |
459 |
core->isPlaying = 0; |
core->isPlaying = 0; |
460 |
} |
} |