From: bk0121.shin Date: Wed, 25 Nov 2015 02:53:53 +0000 (+0900) Subject: audio: apply IN feature to coreaudio X-Git-Tag: Tizen_Studio_1.3_Release_p2.3.2~147 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=75d01002605513c6d742b064c969b94ade82cfa7;p=sdk%2Femulator%2Fqemu.git audio: apply IN feature to coreaudio The original coreaudio does not support audio-in feature. To support this feature, I ported coreaudio from tizen_2.4. There are 3 different following points; 1. Audio in callbacks are added. 2. Init callback has drv_opaque argument. 3. The new logging API is applied. Change-Id: I36a3d772e038a11ee3592cde2ee9c5e277ac9c8e Signed-off-by: bk0121.shin --- diff --git a/audio/coreaudio.c b/audio/coreaudio.c index 6dfd63eb42..7e9b348e52 100644 --- a/audio/coreaudio.c +++ b/audio/coreaudio.c @@ -1,6 +1,7 @@ /* * QEMU OS X CoreAudio audio driver * + * Copyright (c) 2008 The Android Open Source Project * Copyright (c) 2005 Mike Kronenberg * * Permission is hereby granted, free of charge, to any person obtaining a copy @@ -32,24 +33,22 @@ #define AUDIO_CAP "coreaudio" #include "audio_int.h" +#ifdef CONFIG_MARU +#include "../tizen/src/util/new_debug_ch.h" +DECLARE_DEBUG_CHANNEL(coreaudio); +#else +#define LOG_TRACE printf +#endif + static int isAtexit; typedef struct { - int buffer_frames; - int nbuffers; + int o_buffer_frames; + int o_nbuffers; + int i_buffer_frames; + int i_nbuffers; } CoreaudioConf; -typedef struct coreaudioVoiceOut { - HWVoiceOut hw; - pthread_mutex_t mutex; - AudioDeviceID outputDeviceID; - UInt32 audioDevicePropertyBufferFrameSize; - AudioStreamBasicDescription outputStreamBasicDescription; - int live; - int decr; - int rpos; -} coreaudioVoiceOut; - static void coreaudio_logstatus (OSStatus status) { const char *str = "BUG"; @@ -140,13 +139,26 @@ static void GCC_FMT_ATTR (3, 4) coreaudio_logerr2 ( coreaudio_logstatus (status); } -static inline UInt32 isPlaying (AudioDeviceID outputDeviceID) +typedef struct coreAudioVoice { + pthread_mutex_t mutex; + AudioDeviceID deviceID; + Boolean isInput; + UInt32 bufferFrameSize; + AudioStreamBasicDescription streamBasicDescription; + AudioDeviceIOProc ioproc; + int live; + int decr; + int pos; +} coreaudioVoice; + +static inline UInt32 +coreaudio_voice_isPlaying (coreaudioVoice *core) { OSStatus status; UInt32 result = 0; - UInt32 propertySize = sizeof(outputDeviceID); + UInt32 propertySize = sizeof(core->deviceID); status = AudioDeviceGetProperty( - outputDeviceID, 0, 0, + core->deviceID, 0, core->isInput, kAudioDevicePropertyDeviceIsRunning, &propertySize, &result); if (status != kAudioHardwareNoError) { coreaudio_logerr(status, @@ -160,7 +172,7 @@ static void coreaudio_atexit (void) isAtexit = 1; } -static int coreaudio_lock (coreaudioVoiceOut *core, const char *fn_name) +static int coreaudio_lock (coreaudioVoice *core, const char *fn_name) { int err; @@ -173,7 +185,7 @@ static int coreaudio_lock (coreaudioVoiceOut *core, const char *fn_name) return 0; } -static int coreaudio_unlock (coreaudioVoiceOut *core, const char *fn_name) +static int coreaudio_unlock (coreaudioVoice *core, const char *fn_name) { int err; @@ -186,113 +198,81 @@ static int coreaudio_unlock (coreaudioVoiceOut *core, const char *fn_name) return 0; } -static int coreaudio_run_out (HWVoiceOut *hw, int live) +static int +coreaudio_voice_ctl (coreaudioVoice* core, int cmd) { - int decr; - coreaudioVoiceOut *core = (coreaudioVoiceOut *) hw; + OSStatus status; - if (coreaudio_lock (core, "coreaudio_run_out")) { - return 0; - } + switch (cmd) { + case VOICE_ENABLE: + /* start playback */ + LOG_TRACE("%s: %s started\n", __FUNCTION__, core->isInput ? "input" : "output"); + if (!coreaudio_voice_isPlaying(core)) { + status = AudioDeviceStart(core->deviceID, core->ioproc); + if (status != kAudioHardwareNoError) { + coreaudio_logerr (status, "Could not resume playback\n"); + } + } + break; - if (core->decr > live) { - ldebug ("core->decr %d live %d core->live %d\n", - core->decr, - live, - core->live); + case VOICE_DISABLE: + /* stop playback */ + LOG_TRACE("%s: %s stopped\n", __FUNCTION__, core->isInput ? "input" : "output"); + if (!isAtexit) { + if (coreaudio_voice_isPlaying(core)) { + status = AudioDeviceStop(core->deviceID, core->ioproc); + if (status != kAudioHardwareNoError) { + coreaudio_logerr (status, "Could not pause playback\n"); + } + } + } + break; } - - decr = audio_MIN (core->decr, live); - core->decr -= decr; - - core->live = live - decr; - hw->rpos = core->rpos; - - coreaudio_unlock (core, "coreaudio_run_out"); - return decr; + return 0; } -/* callback to feed audiooutput buffer */ -static OSStatus audioDeviceIOProc( - AudioDeviceID inDevice, - const AudioTimeStamp* inNow, - const AudioBufferList* inInputData, - const AudioTimeStamp* inInputTime, - AudioBufferList* outOutputData, - const AudioTimeStamp* inOutputTime, - void* hwptr) +static void +coreaudio_voice_fini (coreaudioVoice* core) { - UInt32 frame, frameCount; - float *out = outOutputData->mBuffers[0].mData; - HWVoiceOut *hw = hwptr; - coreaudioVoiceOut *core = (coreaudioVoiceOut *) hwptr; - int rpos, live; - struct st_sample *src; -#ifndef FLOAT_MIXENG -#ifdef RECIPROCAL - const float scale = 1.f / UINT_MAX; -#else - const float scale = UINT_MAX; -#endif -#endif - - if (coreaudio_lock (core, "audioDeviceIOProc")) { - inInputTime = 0; - return 0; - } + OSStatus status; + int err; - frameCount = core->audioDevicePropertyBufferFrameSize; - live = core->live; + if (!isAtexit) { + /* stop playback */ + coreaudio_voice_ctl(core, VOICE_DISABLE); - /* if there are not enough samples, set signal and return */ - if (live < frameCount) { - inInputTime = 0; - coreaudio_unlock (core, "audioDeviceIOProc(empty)"); - return 0; + /* remove callback */ + status = AudioDeviceRemoveIOProc(core->deviceID, core->ioproc); + if (status != kAudioHardwareNoError) { + coreaudio_logerr (status, "Could not remove IOProc\n"); + } } + core->deviceID = kAudioDeviceUnknown; - rpos = core->rpos; - src = hw->mix_buf + rpos; - - /* fill buffer */ - for (frame = 0; frame < frameCount; frame++) { -#ifdef FLOAT_MIXENG - *out++ = src[frame].l; /* left channel */ - *out++ = src[frame].r; /* right channel */ -#else -#ifdef RECIPROCAL - *out++ = src[frame].l * scale; /* left channel */ - *out++ = src[frame].r * scale; /* right channel */ -#else - *out++ = src[frame].l / scale; /* left channel */ - *out++ = src[frame].r / scale; /* right channel */ -#endif -#endif + /* destroy mutex */ + err = pthread_mutex_destroy(&core->mutex); + if (err) { + dolog("Could not destroy mutex\nReason: %s\n", strerror (err)); } - - rpos = (rpos + frameCount) % hw->samples; - core->decr += frameCount; - core->rpos = rpos; - - coreaudio_unlock (core, "audioDeviceIOProc"); - return 0; } -static int coreaudio_write (SWVoiceOut *sw, void *buf, int len) -{ - return audio_pcm_sw_write (sw, buf, len); -} -static int coreaudio_init_out(HWVoiceOut *hw, struct audsettings *as, - void *drv_opaque) +static int +coreaudio_voice_init (coreaudioVoice* core, + struct audsettings* as, + int frameSize, + AudioDeviceIOProc ioproc, + void* hw, + int input) { - OSStatus status; - coreaudioVoiceOut *core = (coreaudioVoiceOut *) hw; - UInt32 propertySize; - int err; - const char *typ = "playback"; + OSStatus status; + UInt32 propertySize; + int err; +// int bits = 8; AudioValueRange frameRange; - CoreaudioConf *conf = drv_opaque; + const char* typ = input ? "input" : "playback"; + + core->isInput = input ? true : false; /* create mutex */ err = pthread_mutex_init(&core->mutex, NULL); @@ -301,20 +281,28 @@ static int coreaudio_init_out(HWVoiceOut *hw, struct audsettings *as, return -1; } - audio_pcm_init_info (&hw->info, as); + if (as->fmt == AUD_FMT_S16 || as->fmt == AUD_FMT_U16) { +// bits = 16; + } + // TODO: audio_pcm_init_info (&hw->info, as); /* open default output device */ - propertySize = sizeof(core->outputDeviceID); + /* note: we use DefaultSystemOutputDevice because DefaultOutputDevice seems to + * always link to the internal speakers, and not the ones selected through system properties + * go figure... + */ + propertySize = sizeof(core->deviceID); status = AudioHardwareGetProperty( - kAudioHardwarePropertyDefaultOutputDevice, + input ? kAudioHardwarePropertyDefaultInputDevice : + kAudioHardwarePropertyDefaultSystemOutputDevice, &propertySize, - &core->outputDeviceID); + &core->deviceID); if (status != kAudioHardwareNoError) { coreaudio_logerr2 (status, typ, - "Could not get default output Device\n"); + "Could not get default %s device\n", typ); return -1; } - if (core->outputDeviceID == kAudioDeviceUnknown) { + if (core->deviceID == kAudioDeviceUnknown) { dolog ("Could not initialize %s - Unknown Audiodevice\n", typ); return -1; } @@ -322,9 +310,9 @@ static int coreaudio_init_out(HWVoiceOut *hw, struct audsettings *as, /* get minimum and maximum buffer frame sizes */ propertySize = sizeof(frameRange); status = AudioDeviceGetProperty( - core->outputDeviceID, - 0, + core->deviceID, 0, + core->isInput, kAudioDevicePropertyBufferFrameSizeRange, &propertySize, &frameRange); @@ -334,100 +322,101 @@ static int coreaudio_init_out(HWVoiceOut *hw, struct audsettings *as, return -1; } - if (frameRange.mMinimum > conf->buffer_frames) { - core->audioDevicePropertyBufferFrameSize = (UInt32) frameRange.mMinimum; - dolog ("warning: Upsizing Buffer Frames to %f\n", frameRange.mMinimum); + if (frameRange.mMinimum > frameSize) { + core->bufferFrameSize = (UInt32) frameRange.mMinimum; + dolog ("warning: Upsizing Output Buffer Frames to %f\n", frameRange.mMinimum); } - else if (frameRange.mMaximum < conf->buffer_frames) { - core->audioDevicePropertyBufferFrameSize = (UInt32) frameRange.mMaximum; - dolog ("warning: Downsizing Buffer Frames to %f\n", frameRange.mMaximum); + else if (frameRange.mMaximum < frameSize) { + core->bufferFrameSize = (UInt32) frameRange.mMaximum; + dolog ("warning: Downsizing Output Buffer Frames to %f\n", frameRange.mMaximum); } else { - core->audioDevicePropertyBufferFrameSize = conf->buffer_frames; + core->bufferFrameSize = frameSize; } /* set Buffer Frame Size */ - propertySize = sizeof(core->audioDevicePropertyBufferFrameSize); + propertySize = sizeof(core->bufferFrameSize); status = AudioDeviceSetProperty( - core->outputDeviceID, + core->deviceID, NULL, 0, - false, + core->isInput, kAudioDevicePropertyBufferFrameSize, propertySize, - &core->audioDevicePropertyBufferFrameSize); + &core->bufferFrameSize); if (status != kAudioHardwareNoError) { coreaudio_logerr2 (status, typ, - "Could not set device buffer frame size %" PRIu32 "\n", - (uint32_t)core->audioDevicePropertyBufferFrameSize); + "Could not set device buffer frame size %ld\n", + (long)core->bufferFrameSize); return -1; } /* get Buffer Frame Size */ - propertySize = sizeof(core->audioDevicePropertyBufferFrameSize); + propertySize = sizeof(core->bufferFrameSize); status = AudioDeviceGetProperty( - core->outputDeviceID, + core->deviceID, 0, - false, + core->isInput, kAudioDevicePropertyBufferFrameSize, &propertySize, - &core->audioDevicePropertyBufferFrameSize); + &core->bufferFrameSize); if (status != kAudioHardwareNoError) { coreaudio_logerr2 (status, typ, "Could not get device buffer frame size\n"); return -1; } - hw->samples = conf->nbuffers * core->audioDevicePropertyBufferFrameSize; + // TODO: hw->samples = *pNBuffers * core->bufferFrameSize; /* get StreamFormat */ - propertySize = sizeof(core->outputStreamBasicDescription); + propertySize = sizeof(core->streamBasicDescription); status = AudioDeviceGetProperty( - core->outputDeviceID, + core->deviceID, 0, - false, + core->isInput, kAudioDevicePropertyStreamFormat, &propertySize, - &core->outputStreamBasicDescription); + &core->streamBasicDescription); if (status != kAudioHardwareNoError) { coreaudio_logerr2 (status, typ, "Could not get Device Stream properties\n"); - core->outputDeviceID = kAudioDeviceUnknown; + core->deviceID = kAudioDeviceUnknown; return -1; } /* set Samplerate */ - core->outputStreamBasicDescription.mSampleRate = (Float64) as->freq; - propertySize = sizeof(core->outputStreamBasicDescription); + core->streamBasicDescription.mSampleRate = (Float64) as->freq; + propertySize = sizeof(core->streamBasicDescription); status = AudioDeviceSetProperty( - core->outputDeviceID, - 0, + core->deviceID, 0, 0, + core->isInput, kAudioDevicePropertyStreamFormat, propertySize, - &core->outputStreamBasicDescription); + &core->streamBasicDescription); if (status != kAudioHardwareNoError) { coreaudio_logerr2 (status, typ, "Could not set samplerate %d\n", as->freq); - core->outputDeviceID = kAudioDeviceUnknown; + core->deviceID = kAudioDeviceUnknown; return -1; } /* set Callback */ - status = AudioDeviceAddIOProc(core->outputDeviceID, audioDeviceIOProc, hw); + core->ioproc = ioproc; + status = AudioDeviceAddIOProc(core->deviceID, ioproc, hw); if (status != kAudioHardwareNoError) { coreaudio_logerr2 (status, typ, "Could not set IOProc\n"); - core->outputDeviceID = kAudioDeviceUnknown; + core->deviceID = kAudioDeviceUnknown; return -1; } /* start Playback */ - if (!isPlaying(core->outputDeviceID)) { - status = AudioDeviceStart(core->outputDeviceID, audioDeviceIOProc); + if (!input && !coreaudio_voice_isPlaying(core)) { + status = AudioDeviceStart(core->deviceID, core->ioproc); if (status != kAudioHardwareNoError) { coreaudio_logerr2 (status, typ, "Could not start playback\n"); - AudioDeviceRemoveIOProc(core->outputDeviceID, audioDeviceIOProc); - core->outputDeviceID = kAudioDeviceUnknown; + AudioDeviceRemoveIOProc(core->deviceID, core->ioproc); + core->deviceID = kAudioDeviceUnknown; return -1; } } @@ -435,71 +424,291 @@ static int coreaudio_init_out(HWVoiceOut *hw, struct audsettings *as, return 0; } -static void coreaudio_fini_out (HWVoiceOut *hw) +typedef struct coreaudioVoiceOut { + HWVoiceOut hw; + coreaudioVoice core[1]; +} coreaudioVoiceOut; + +#define CORE_OUT(hw) ((coreaudioVoiceOut*)(hw))->core + + +static int coreaudio_run_out (HWVoiceOut *hw, int live) { - OSStatus status; + int decr; + coreaudioVoice *core = CORE_OUT(hw); + + if (coreaudio_lock (core, "coreaudio_run_out")) { + return 0; + } + + if (core->decr > live) { + ldebug ("core->decr %d live %d core->live %d\n", + core->decr, + live, + core->live); + } + + decr = audio_MIN (core->decr, live); + core->decr -= decr; + + core->live = live - decr; + hw->rpos = core->pos; + + coreaudio_unlock (core, "coreaudio_run_out"); + return decr; +} + +/* callback to feed audiooutput buffer */ +static OSStatus audioOutDeviceIOProc( + AudioDeviceID inDevice, + const AudioTimeStamp* inNow, + const AudioBufferList* inInputData, + const AudioTimeStamp* inInputTime, + AudioBufferList* outOutputData, + const AudioTimeStamp* inOutputTime, + void* hwptr) +{ + UInt32 frame, frameCount; + float *out = outOutputData->mBuffers[0].mData; + HWVoiceOut *hw = hwptr; + coreaudioVoice *core = CORE_OUT(hw); + int rpos, live; + struct st_sample *src; +#ifndef FLOAT_MIXENG +#ifdef RECIPROCAL + const float scale = 1.f / UINT_MAX; +#else + const float scale = UINT_MAX; +#endif +#endif + + if (coreaudio_lock (core, "audioDeviceIOProc")) { + inInputTime = 0; + return 0; + } + + frameCount = core->bufferFrameSize; + live = core->live; + + /* if there are not enough samples, set signal and return */ + if (live < frameCount) { + inInputTime = 0; + coreaudio_unlock (core, "audioDeviceIOProc(empty)"); + return 0; + } + + rpos = core->pos; + src = hw->mix_buf + rpos; + + /* fill buffer */ + for (frame = 0; frame < frameCount; frame++) { +#ifdef FLOAT_MIXENG + *out++ = src[frame].l; /* left channel */ + *out++ = src[frame].r; /* right channel */ +#else +#ifdef RECIPROCAL + *out++ = src[frame].l * scale; /* left channel */ + *out++ = src[frame].r * scale; /* right channel */ +#else + *out++ = src[frame].l / scale; /* left channel */ + *out++ = src[frame].r / scale; /* right channel */ +#endif +#endif + } + + rpos = (rpos + frameCount) % hw->samples; + core->decr += frameCount; + core->pos = rpos; + + coreaudio_unlock (core, "audioDeviceIOProc"); + return 0; +} + +static int coreaudio_write (SWVoiceOut *sw, void *buf, int len) +{ + return audio_pcm_sw_write (sw, buf, len); +} + +static int coreaudio_init_out (HWVoiceOut *hw, struct audsettings *as, + void *drv_opaque) +{ + coreaudioVoice* core = CORE_OUT(hw); int err; - coreaudioVoiceOut *core = (coreaudioVoiceOut *) hw; + CoreaudioConf *conf = drv_opaque; - if (!isAtexit) { - /* stop playback */ - if (isPlaying(core->outputDeviceID)) { - status = AudioDeviceStop(core->outputDeviceID, audioDeviceIOProc); - if (status != kAudioHardwareNoError) { - coreaudio_logerr (status, "Could not stop playback\n"); - } - } + audio_pcm_init_info (&hw->info, as); - /* remove callback */ - status = AudioDeviceRemoveIOProc(core->outputDeviceID, - audioDeviceIOProc); - if (status != kAudioHardwareNoError) { - coreaudio_logerr (status, "Could not remove IOProc\n"); - } + err = coreaudio_voice_init (core, as, conf->o_buffer_frames, audioOutDeviceIOProc, hw, 0); + if (err < 0) + return err; + + hw->samples = core->bufferFrameSize * conf->o_nbuffers; + return 0; +} + +static void coreaudio_fini_out (HWVoiceOut *hw) +{ + coreaudioVoice *core = CORE_OUT(hw); + + coreaudio_voice_fini (core); +} + +static int +coreaudio_ctl_out (HWVoiceOut *hw, int cmd, ...) +{ + coreaudioVoice *core = CORE_OUT(hw); + + return coreaudio_voice_ctl (core, cmd); +} + +// +// Enable coreaudio audio-in +// + +typedef struct coreaudioVoiceIn { + HWVoiceIn hw; + coreaudioVoice core[1]; +} coreaudioVoiceIn; + +#define CORE_IN(hw) ((coreaudioVoiceIn *) (hw))->core + + +static int coreaudio_run_in (HWVoiceIn *hw) +{ + int decr; + + coreaudioVoice *core = CORE_IN(hw); + + if (coreaudio_lock (core, "coreaudio_run_in")) { + return 0; } - core->outputDeviceID = kAudioDeviceUnknown; + LOG_TRACE("%s: core.decr=%d core.pos=%d\n", __FUNCTION__, core->decr, core->pos); + decr = core->decr; + core->decr -= decr; + hw->wpos = core->pos; - /* destroy mutex */ - err = pthread_mutex_destroy(&core->mutex); - if (err) { - dolog("Could not destroy mutex\nReason: %s\n", strerror (err)); + coreaudio_unlock (core, "coreaudio_run_in"); + return decr; +} + + +/* callback to feed audiooutput buffer */ +static OSStatus audioInDeviceIOProc( + AudioDeviceID inDevice, + const AudioTimeStamp* inNow, + const AudioBufferList* inInputData, + const AudioTimeStamp* inInputTime, + AudioBufferList* outOutputData, + const AudioTimeStamp* inOutputTime, + void* hwptr) +{ + UInt32 frame, frameCount; + float *in = inInputData->mBuffers[0].mData; + HWVoiceIn *hw = hwptr; + coreaudioVoice *core = CORE_IN(hw); + int wpos, avail; + struct st_sample *dst; +#ifndef FLOAT_MIXENG +#ifdef RECIPROCAL + const float scale = 1.f / UINT_MAX; +#else + const float scale = UINT_MAX; +#endif +#endif + + if (coreaudio_lock (core, "audioDeviceIOProc")) { + inInputTime = 0; + return 0; } + + frameCount = core->bufferFrameSize; + avail = hw->samples - hw->total_samples_captured - core->decr; + + LOG_TRACE("%s: enter avail=%d core.decr=%d core.pos=%d hw.samples=%d hw.total_samples_captured=%d frameCount=%d\n", + __FUNCTION__, avail, core->decr, core->pos, hw->samples, hw->total_samples_captured, (int)frameCount); + + /* if there are not enough samples, set signal and return */ + if (avail < frameCount) { + inInputTime = 0; + coreaudio_unlock (core, "audioDeviceIOProc(empty)"); + return 0; + } + + wpos = core->pos; + dst = hw->conv_buf + wpos; + + /* fill buffer */ + for (frame = 0; frame < frameCount; frame++) { +#ifdef FLOAT_MIXENG + dst[frame].l = *in++; /* left channel */ + dst[frame].r = *in++; /* right channel */ +#else +#ifdef RECIPROCAL + dst[frame].l = *in++ * scale; /* left channel */ + dst[frame].r = *in++ * scale; /* right channel */ +#else + dst[frame].l = *in++ / scale; /* left channel */ + dst[frame].r = *in++ / scale; /* right channel */ +#endif +#endif + } + + wpos = (wpos + frameCount) % hw->samples; + core->decr += frameCount; + core->pos = wpos; + + LOG_TRACE("exit: core.decr=%d core.pos=%d\n", core->decr, core->pos); + coreaudio_unlock (core, "audioDeviceIOProc"); + return 0; } -static int coreaudio_ctl_out (HWVoiceOut *hw, int cmd, ...) +static int +coreaudio_read (SWVoiceIn *sw, void *buf, int len) { - OSStatus status; - coreaudioVoiceOut *core = (coreaudioVoiceOut *) hw; + int result = audio_pcm_sw_read (sw, buf, len); + LOG_TRACE("%s: audio_pcm_sw_read(%d) returned %d\n", __FUNCTION__, len, result); + return result; +} - switch (cmd) { - case VOICE_ENABLE: - /* start playback */ - if (!isPlaying(core->outputDeviceID)) { - status = AudioDeviceStart(core->outputDeviceID, audioDeviceIOProc); - if (status != kAudioHardwareNoError) { - coreaudio_logerr (status, "Could not resume playback\n"); - } - } - break; +static int +coreaudio_init_in (HWVoiceIn *hw, struct audsettings *as, + void *drv_opaque) +{ + coreaudioVoice* core = CORE_IN(hw); + int err; + CoreaudioConf *conf = drv_opaque; - case VOICE_DISABLE: - /* stop playback */ - if (!isAtexit) { - if (isPlaying(core->outputDeviceID)) { - status = AudioDeviceStop(core->outputDeviceID, audioDeviceIOProc); - if (status != kAudioHardwareNoError) { - coreaudio_logerr (status, "Could not pause playback\n"); - } - } - } - break; + audio_pcm_init_info (&hw->info, as); + + err = coreaudio_voice_init (core, as, conf->i_buffer_frames, audioInDeviceIOProc, hw, 1); + if (err < 0) { + return err; } + + hw->samples = core->bufferFrameSize * conf->i_nbuffers; return 0; } +static void +coreaudio_fini_in (HWVoiceIn *hw) +{ + coreaudioVoice* core = CORE_IN(hw); + coreaudio_voice_fini(core); +} + +static int +coreaudio_ctl_in (HWVoiceIn *hw, int cmd, ...) +{ + coreaudioVoice* core = CORE_IN(hw); + + return coreaudio_voice_ctl(core, cmd); +} + static CoreaudioConf glob_conf = { - .buffer_frames = 512, - .nbuffers = 4, + .o_buffer_frames = 512, + .o_nbuffers = 4, + .i_buffer_frames = 512, + .i_nbuffers = 4, }; static void *coreaudio_audio_init (void) @@ -518,16 +727,28 @@ static void coreaudio_audio_fini (void *opaque) static struct audio_option coreaudio_options[] = { { - .name = "BUFFER_SIZE", + .name = "O_BUFFER_SIZE", + .tag = AUD_OPT_INT, + .valp = &glob_conf.o_buffer_frames, + .descr = "Size of the output buffer in frames" + }, + { + .name = "O_BUFFER_COUNT", .tag = AUD_OPT_INT, - .valp = &glob_conf.buffer_frames, - .descr = "Size of the buffer in frames" + .valp = &glob_conf.o_nbuffers, + .descr = "Number of output buffers" }, { - .name = "BUFFER_COUNT", + .name = "I_BUFFER_SIZE", .tag = AUD_OPT_INT, - .valp = &glob_conf.nbuffers, - .descr = "Number of buffers" + .valp = &glob_conf.i_buffer_frames, + .descr = "Size of the input buffer in frames" + }, + { + .name = "I_BUFFER_COUNT", + .tag = AUD_OPT_INT, + .valp = &glob_conf.i_nbuffers, + .descr = "Number of input buffers" }, { /* End of list */ } }; @@ -537,7 +758,13 @@ static struct audio_pcm_ops coreaudio_pcm_ops = { .fini_out = coreaudio_fini_out, .run_out = coreaudio_run_out, .write = coreaudio_write, - .ctl_out = coreaudio_ctl_out + .ctl_out = coreaudio_ctl_out, + + .init_in = coreaudio_init_in, + .fini_in = coreaudio_fini_in, + .run_in = coreaudio_run_in, + .read = coreaudio_read, + .ctl_in = coreaudio_ctl_in }; struct audio_driver coreaudio_audio_driver = { @@ -549,7 +776,7 @@ struct audio_driver coreaudio_audio_driver = { .pcm_ops = &coreaudio_pcm_ops, .can_be_default = 1, .max_voices_out = 1, - .max_voices_in = 0, + .max_voices_in = 1, // enable auido-in .voice_size_out = sizeof (coreaudioVoiceOut), - .voice_size_in = 0 + .voice_size_in = sizeof (coreaudioVoiceIn), };