diff options
author | letz <letz@0c269be4-1314-0410-8aa9-9f06e86f4224> | 2006-04-12 19:39:55 +0000 |
---|---|---|
committer | letz <letz@0c269be4-1314-0410-8aa9-9f06e86f4224> | 2006-04-12 19:39:55 +0000 |
commit | c09e10cc7df26f2743751d87dbabced1356f8502 (patch) | |
tree | be39f1435b3d1cb3597986c05bacb815056b4906 /drivers | |
parent | b28337f688e9d017bec358007228f73f56219065 (diff) | |
download | jack1-c09e10cc7df26f2743751d87dbabced1356f8502.tar.gz |
Synchronization with the jackdmp coreaudio driver version: improve half-duplex management
git-svn-id: svn+ssh://jackaudio.org/trunk/jack@941 0c269be4-1314-0410-8aa9-9f06e86f4224
Diffstat (limited to 'drivers')
-rwxr-xr-x | drivers/coreaudio/coreaudio_driver.c | 705 | ||||
-rwxr-xr-x | drivers/coreaudio/coreaudio_driver.h | 4 |
2 files changed, 430 insertions, 279 deletions
diff --git a/drivers/coreaudio/coreaudio_driver.c b/drivers/coreaudio/coreaudio_driver.c index 46671f4..177590c 100755 --- a/drivers/coreaudio/coreaudio_driver.c +++ b/drivers/coreaudio/coreaudio_driver.c @@ -41,6 +41,7 @@ Aug 16, 2005: S.Letz: Remove get_device_id_from_num, use get_default_device instead. If the -n option is not used or the device name cannot be found, the default device is used. Note: the default device can be used only if both default input and default output are the same. Dec 19, 2005: S.Letz: Add -d option (display_device_names). + Apri 7, 2006: S.Letz: Synchronization with the jackdmp coreaudio driver version: improve half-duplex management. */ @@ -64,7 +65,7 @@ static void JCALog(char *fmt, ...) #endif } -static void printError1(OSStatus err) +static void printError(OSStatus err) { #ifdef DEBUG switch (err) { @@ -152,10 +153,86 @@ static OSStatus get_default_device(AudioDeviceID * id) *id = inDefault; return noErr; } else { + jack_error("Default input and output devices are not the same !!"); return kAudioHardwareBadDeviceError; } } +static OSStatus get_default_input_device(AudioDeviceID* id) +{ + OSStatus res; + UInt32 theSize = sizeof(UInt32); + AudioDeviceID inDefault; + + if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice, + &theSize, &inDefault)) != noErr) + return res; + + JCALog("get_default_input_device: input = %ld \n", inDefault); + *id = inDefault; + return noErr; +} + +static OSStatus get_default_output_device(AudioDeviceID* id) +{ + OSStatus res; + UInt32 theSize = sizeof(UInt32); + AudioDeviceID outDefault; + + if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, + &theSize, &outDefault)) != noErr) + return res; + + JCALog("get_default_output_device: output = %ld\n", outDefault); + *id = outDefault; + return noErr; +} + +OSStatus get_total_channels(AudioDeviceID device, int* channelCount, bool isInput) +{ + OSStatus err = noErr; + UInt32 outSize; + Boolean outWritable; + AudioBufferList* bufferList = 0; + AudioStreamID* streamList = 0; + int i, numStream; + + err = AudioDeviceGetPropertyInfo(device, 0, isInput, kAudioDevicePropertyStreams, &outSize, &outWritable); + if (err == noErr) { + streamList = (AudioStreamID*)malloc(outSize); + numStream = outSize/sizeof(AudioStreamID); + JCALog("get_total_channels device stream number = %ld numStream = %ld\n", device, numStream); + err = AudioDeviceGetProperty(device, 0, isInput, kAudioDevicePropertyStreams, &outSize, streamList); + if (err == noErr) { + AudioStreamBasicDescription streamDesc; + outSize = sizeof(AudioStreamBasicDescription); + for (i = 0; i < numStream; i++) { + err = AudioStreamGetProperty(streamList[i], 0, kAudioDevicePropertyStreamFormat, &outSize, &streamDesc); + JCALog("get_total_channels streamDesc mFormatFlags = %ld mChannelsPerFrame = %ld\n", streamDesc.mFormatFlags, streamDesc.mChannelsPerFrame); + } + } + } + + *channelCount = 0; + err = AudioDeviceGetPropertyInfo(device, 0, isInput, kAudioDevicePropertyStreamConfiguration, &outSize, &outWritable); + if (err == noErr) { + bufferList = (AudioBufferList*)malloc(outSize); + err = AudioDeviceGetProperty(device, 0, isInput, kAudioDevicePropertyStreamConfiguration, &outSize, bufferList); + if (err == noErr) { + for (i = 0; i < bufferList->mNumberBuffers; i++) + *channelCount += bufferList->mBuffers[i].mNumberChannels; + } + } + + if (streamList) + free(streamList); + if (bufferList) + free(bufferList); + + return err; +} + + static OSStatus display_device_names() { UInt32 size; @@ -205,11 +282,11 @@ error: } static OSStatus render(void *inRefCon, - AudioUnitRenderActionFlags *ioActionFlags, - const AudioTimeStamp *inTimeStamp, - UInt32 inBusNumber, - UInt32 inNumberFrames, - AudioBufferList *ioData) + AudioUnitRenderActionFlags *ioActionFlags, + const AudioTimeStamp *inTimeStamp, + UInt32 inBusNumber, + UInt32 inNumberFrames, + AudioBufferList *ioData) { int res, i; @@ -248,11 +325,11 @@ static OSStatus render(void *inRefCon, } static OSStatus render_input(void *inRefCon, - AudioUnitRenderActionFlags *ioActionFlags, - const AudioTimeStamp *inTimeStamp, - UInt32 inBusNumber, - UInt32 inNumberFrames, - AudioBufferList *ioData) + AudioUnitRenderActionFlags *ioActionFlags, + const AudioTimeStamp *inTimeStamp, + UInt32 inBusNumber, + UInt32 inNumberFrames, + AudioBufferList *ioData) { coreaudio_driver_t* ca_driver = (coreaudio_driver_t*)inRefCon; @@ -273,10 +350,10 @@ static OSStatus render_input(void *inRefCon, } static OSStatus notification(AudioDeviceID inDevice, - UInt32 inChannel, - Boolean isInput, - AudioDevicePropertyID inPropertyID, - void* inClientData) + UInt32 inChannel, + Boolean isInput, + AudioDevicePropertyID inPropertyID, + void* inClientData) { coreaudio_driver_t* ca_driver = (coreaudio_driver_t*)inClientData; if (inPropertyID == kAudioDeviceProcessorOverload) { @@ -286,8 +363,7 @@ static OSStatus notification(AudioDeviceID inDevice, } static int -coreaudio_driver_attach(coreaudio_driver_t * driver, - jack_engine_t * engine) +coreaudio_driver_attach(coreaudio_driver_t * driver, jack_engine_t * engine) { jack_port_t *port; JSList *node; @@ -319,9 +395,9 @@ coreaudio_driver_attach(coreaudio_driver_t * driver, err = AudioDeviceGetProperty(driver->device_id, chn + 1, true, kAudioDevicePropertyChannelName, &size, channel_name); if (err != noErr) JCALog("AudioDeviceGetProperty kAudioDevicePropertyChannelName error \n"); - snprintf(buf, sizeof(buf) - 1, "%s:out_%s%lu", driver->driver_name, channel_name, chn + 1); + snprintf(buf, sizeof(buf) - 1, "%s:out_%s%lu", driver->capture_driver_name, channel_name, chn + 1); } else { - snprintf(buf, sizeof(buf) - 1, "%s:out%lu", driver->driver_name, chn + 1); + snprintf(buf, sizeof(buf) - 1, "%s:out%lu", driver->capture_driver_name, chn + 1); } if ((port = jack_port_register(driver->client, buf, @@ -353,9 +429,9 @@ coreaudio_driver_attach(coreaudio_driver_t * driver, err = AudioDeviceGetProperty(driver->device_id, chn + 1, false, kAudioDevicePropertyChannelName, &size, channel_name); if (err != noErr) JCALog("AudioDeviceGetProperty kAudioDevicePropertyChannelName error \n"); - snprintf(buf, sizeof(buf) - 1, "%s:in_%s%lu", driver->driver_name, channel_name, chn + 1); + snprintf(buf, sizeof(buf) - 1, "%s:in_%s%lu", driver->playback_driver_name, channel_name, chn + 1); } else { - snprintf(buf, sizeof(buf) - 1, "%s:in%lu", driver->driver_name, chn + 1); + snprintf(buf, sizeof(buf) - 1, "%s:in%lu", driver->playback_driver_name, chn + 1); } if ((port = jack_port_register(driver->client, buf, @@ -390,8 +466,7 @@ coreaudio_driver_attach(coreaudio_driver_t * driver, } static int -coreaudio_driver_detach(coreaudio_driver_t * driver, - jack_engine_t * engine) +coreaudio_driver_detach(coreaudio_driver_t * driver, jack_engine_t * engine) { JSList *node; @@ -418,8 +493,7 @@ coreaudio_driver_detach(coreaudio_driver_t * driver, } static int -coreaudio_driver_null_cycle(coreaudio_driver_t * driver, - jack_nframes_t nframes) +coreaudio_driver_null_cycle(coreaudio_driver_t * driver, jack_nframes_t nframes) { driver->null_cycle_occured = 1; return 0; @@ -464,37 +538,39 @@ coreaudio_driver_bufsize(coreaudio_driver_t * driver, /** create a new driver instance */ static jack_driver_t *coreaudio_driver_new(char* name, - jack_client_t* client, - jack_nframes_t frames_per_cycle, - jack_nframes_t rate, - int capturing, - int playing, - int chan_in, - int chan_out, - char* driver_uid, - jack_nframes_t capture_latency, - jack_nframes_t playback_latency) + jack_client_t* client, + jack_nframes_t nframes, + jack_nframes_t samplerate, + int capturing, + int playing, + int inchannels, + int outchannels, + char* capture_driver_uid, + char* playback_driver_uid, + jack_nframes_t capture_latency, + jack_nframes_t playback_latency) { coreaudio_driver_t *driver; OSStatus err = noErr; ComponentResult err1; UInt32 outSize; - Boolean isWritable; - AudioStreamBasicDescription srcFormat, dstFormat; - int in_nChannels, out_nChannels, i; - Float64 nominalSampleRate; - + UInt32 enableIO; + AudioStreamBasicDescription srcFormat, dstFormat, sampleRate; + int in_nChannels = 0; + int out_nChannels = 0; + int i; + driver = (coreaudio_driver_t *) calloc(1, sizeof(coreaudio_driver_t)); jack_driver_init((jack_driver_t *) driver); - if (!jack_power_of_two(frames_per_cycle)) { + if (!jack_power_of_two(nframes)) { fprintf(stderr, "CA: -p must be a power of two.\n"); goto error; } - driver->frames_per_cycle = frames_per_cycle; - driver->frame_rate = rate; + driver->frames_per_cycle = nframes; + driver->frame_rate = samplerate; driver->capturing = capturing; driver->playing = playing; driver->xrun_detected = 0; @@ -511,263 +587,330 @@ static jack_driver_t *coreaudio_driver_new(char* name, driver->stop = (JackDriverStopFunction) coreaudio_driver_audio_stop; driver->capture_frame_latency = capture_latency; driver->playback_frame_latency = playback_latency; - - if (driver_uid) { - if (get_device_id_from_uid(driver_uid, &driver->device_id) != noErr) { - if (get_default_device(&driver->device_id) != noErr) + + // Duplex + if (capture_driver_uid != NULL && playback_driver_uid != NULL) { + JCALog("Open duplex \n"); + if (get_device_id_from_uid(playback_driver_uid, &driver->device_id) != noErr) { + if (get_default_device(&driver->device_id) != noErr) { + jack_error("Cannot open default device"); goto error; + } + } + if (get_device_name_from_id(driver->device_id, driver->capture_driver_name) != noErr || get_device_name_from_id(driver->device_id, driver->playback_driver_name) != noErr) { + jack_error("Cannot get device name from device ID"); + goto error; + } + + // Capture only + } else if (capture_driver_uid != NULL) { + JCALog("Open capture only \n"); + if (get_device_id_from_uid(capture_driver_uid, &driver->device_id) != noErr) { + if (get_default_input_device(&driver->device_id) != noErr) { + jack_error("Cannot open default device"); + goto error; + } + } + if (get_device_name_from_id(driver->device_id, driver->capture_driver_name) != noErr) { + jack_error("Cannot get device name from device ID"); + goto error; + } + + // Playback only + } else if (playback_driver_uid != NULL) { + JCALog("Open playback only \n"); + if (get_device_id_from_uid(playback_driver_uid, &driver->device_id) != noErr) { + if (get_default_output_device(&driver->device_id) != noErr) { + jack_error("Cannot open default device"); + goto error; + } + } + if (get_device_name_from_id(driver->device_id, driver->playback_driver_name) != noErr) { + jack_error("Cannot get device name from device ID"); + goto error; } + + // Use default driver in duplex mode } else { - if (get_default_device(&driver->device_id) != noErr) + JCALog("Open default driver \n"); + if (get_default_device(&driver->device_id) != noErr) { + jack_error("Cannot open default device"); + goto error; + } + if (get_device_name_from_id(driver->device_id, driver->capture_driver_name) != noErr || get_device_name_from_id(driver->device_id, driver->playback_driver_name) != noErr) { + jack_error("Cannot get device name from device ID"); goto error; + } } - - if (get_device_name_from_id(driver->device_id, driver->driver_name) != noErr) - goto error; - + driver->client = client; driver->period_usecs = (((float) driver->frames_per_cycle) / driver->frame_rate) * 1000000.0f; - - driver->playback_nchannels = chan_out; - driver->capture_nchannels = chan_in; - // Setting buffer size - outSize = sizeof(UInt32); - err = AudioDeviceSetProperty(driver->device_id, NULL, 0, false, - kAudioDevicePropertyBufferFrameSize, outSize, &frames_per_cycle); - if (err != noErr) { - JCALog("Cannot set buffer size %ld\n", frames_per_cycle); - printError1(err); + if (capturing) { + err = get_total_channels(driver->device_id, &in_nChannels, true); + if (err != noErr) { + jack_error("Cannot get input channel number"); + printError(err); + goto error; + } + } + + if (playing) { + err = get_total_channels(driver->device_id, &out_nChannels, false); + if (err != noErr) { + jack_error("Cannot get output channel number"); + printError(err); + goto error; + } + } + + if (inchannels > in_nChannels) { + jack_error("This device hasn't required input channels inchannels = %ld in_nChannels = %ld", inchannels, in_nChannels); goto error; } - outSize = sizeof(Float64); - err = AudioDeviceGetProperty(driver->device_id, 0, false, - kAudioDevicePropertyNominalSampleRate, &outSize, &nominalSampleRate); - if (err != noErr) { - JCALog("Cannot get sample rate\n"); - printError1(err); + if (outchannels > out_nChannels) { + jack_error("This device hasn't required output channels outchannels = %ld out_nChannels = %ld", outchannels, out_nChannels); goto error; - } else { - JCALog("Read nominalSampleRate %f\n", nominalSampleRate); + } + + if (inchannels == 0) { + JCALog("Setup max in channels = %ld\n", in_nChannels); + inchannels = in_nChannels; + } + + if (outchannels == 0) { + JCALog("Setup max out channels = %ld\n", out_nChannels); + outchannels = out_nChannels; } - if (rate != (jack_nframes_t)nominalSampleRate) { - nominalSampleRate = (Float64)rate; - err = AudioDeviceSetProperty(driver->device_id, NULL, 0, - false, kAudioDevicePropertyNominalSampleRate, outSize, &nominalSampleRate); - if (err != noErr) { - JCALog("Cannot set sample rate %ld\n", rate); - printError1(err); - goto error; - } + // Setting buffer size + outSize = sizeof(UInt32); + err = AudioDeviceSetProperty(driver->device_id, NULL, 0, false, kAudioDevicePropertyBufferFrameSize, outSize, &nframes); + if (err != noErr) { + jack_error("Cannot set buffer size %ld", nframes); + printError(err); + goto error; } + + // Set sample rate + if (capturing && inchannels > 0) { + outSize = sizeof(AudioStreamBasicDescription); + err = AudioDeviceGetProperty(driver->device_id, 0, true, kAudioDevicePropertyStreamFormat, &outSize, &sampleRate); + if (err != noErr) { + jack_error("Cannot get current sample rate"); + printError(err); + goto error; + } + + if (samplerate != (unsigned long)sampleRate.mSampleRate) { + sampleRate.mSampleRate = (Float64)samplerate; + err = AudioDeviceSetProperty(driver->device_id, NULL, 0, true, kAudioDevicePropertyStreamFormat, outSize, &sampleRate); + if (err != noErr) { + jack_error("Cannot set sample rate = %ld", samplerate); + printError(err); + goto error; + } + } + } - err = AudioDeviceGetProperty(driver->device_id, 0, false, - kAudioDevicePropertyNominalSampleRate, &outSize, &nominalSampleRate); - if (err != noErr) { - JCALog("Cannot get sample rate\n"); - printError1(err); - goto error; - } else { - JCALog("Read again nominalSampleRate %f\n", nominalSampleRate); + if (playing && outchannels > 0) { + outSize = sizeof(AudioStreamBasicDescription); + err = AudioDeviceGetProperty(driver->device_id, 0, false, kAudioDevicePropertyStreamFormat, &outSize, &sampleRate); + if (err != noErr) { + jack_error("Cannot get current sample rate"); + printError(err); + goto error; + } + + if (samplerate != (unsigned long)sampleRate.mSampleRate) { + sampleRate.mSampleRate = (Float64)samplerate; + err = AudioDeviceSetProperty(driver->device_id, NULL, 0, false, kAudioDevicePropertyStreamFormat, outSize, &sampleRate); + if (err != noErr) { + jack_error("Cannot set sample rate = %ld", samplerate); + printError(err); + goto error; + } + } } - // AUHAL - ComponentDescription cd = {kAudioUnitType_Output, - kAudioUnitSubType_HALOutput, kAudioUnitManufacturer_Apple, 0, 0}; - Component HALOutput = FindNextComponent(NULL, &cd); - - err1 = OpenAComponent(HALOutput, &driver->au_hal); - if (err1 != noErr) - goto error; + // AUHAL + ComponentDescription cd = {kAudioUnitType_Output, kAudioUnitSubType_HALOutput, kAudioUnitManufacturer_Apple, 0, 0}; + Component HALOutput = FindNextComponent(NULL, &cd); - err1 = AudioUnitInitialize(driver->au_hal); - if (err1 != noErr) { - printError1(err1); + err1 = OpenAComponent(HALOutput, &driver->au_hal); + if (err1 != noErr) { + jack_error("Error calling OpenAComponent"); + printError(err1); goto error; } - - outSize = 1; - err1 = AudioUnitSetProperty(driver->au_hal, kAudioOutputUnitProperty_EnableIO, - kAudioUnitScope_Output, 0, &outSize, sizeof(outSize)); - if (err1 != noErr) { - JCALog("error: calling AudioUnitSetProperty - kAudioOutputUnitProperty_EnableIO,kAudioUnitScope_Output\n"); - printError1(err1); - goto error; + + err1 = AudioUnitInitialize(driver->au_hal); + if (err1 != noErr) { + jack_error("Cannot initialize AUHAL unit"); + printError(err1); + goto error; } + + // Start I/O + enableIO = 1; + if (capturing && inchannels > 0) { + JCALog("Setup AUHAL input\n"); + err1 = AudioUnitSetProperty(driver->au_hal, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, 1, &enableIO, sizeof(enableIO)); + if (err1 != noErr) { + jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input"); + printError(err1); + goto error; + } + } - if (chan_in > 0) { - outSize = 1; - err1 = AudioUnitSetProperty(driver->au_hal, kAudioOutputUnitProperty_EnableIO, - kAudioUnitScope_Input, 1, &outSize, sizeof(outSize)); - if (err1 != noErr) { - JCALog("error: calling AudioUnitSetProperty - kAudioOutputUnitProperty_EnableIO,kAudioUnitScope_Input\n"); - printError1(err1); - goto error; + if (playing && outchannels > 0) { + JCALog("Setup AUHAL output\n"); + err1 = AudioUnitSetProperty(driver->au_hal, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, 0, &enableIO, sizeof(enableIO)); + if (err1 != noErr) { + jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_EnableIO,kAudioUnitScope_Output"); + printError(err1); + goto error; } } - err1 = AudioUnitSetProperty(driver->au_hal, kAudioOutputUnitProperty_CurrentDevice, - kAudioUnitScope_Global, 0, &driver->device_id, sizeof(AudioDeviceID)); - if (err1 != noErr) { - JCALog("error: calling AudioUnitSetProperty - kAudioOutputUnitProperty_CurrentDevice\n"); - printError1(err1); + // Setup up choosen device, in both input and output cases + err1 = AudioUnitSetProperty(driver->au_hal, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &driver->device_id, sizeof(AudioDeviceID)); + if (err1 != noErr) { + jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_CurrentDevice"); + printError(err1); goto error; } - - err1 = AudioUnitSetProperty(driver->au_hal, kAudioUnitProperty_MaximumFramesPerSlice, - kAudioUnitScope_Global, 0, (UInt32*)&frames_per_cycle, sizeof(UInt32)); - if (err1 != noErr) { - JCALog("error: calling AudioUnitSetProperty - kAudioUnitProperty_MaximumFramesPerSlice\n"); - printError1(err1); - goto error; - } - err1 = AudioUnitGetPropertyInfo(driver->au_hal, kAudioOutputUnitProperty_ChannelMap, - kAudioUnitScope_Input, 1, &outSize, &isWritable); - if (err1 != noErr) { - JCALog("error: calling AudioUnitSetProperty - kAudioOutputUnitProperty_ChannelMap-INFO 1\n"); - printError1(err1); + // Set buffer size + if (capturing && inchannels > 0) { + err1 = AudioUnitSetProperty(driver->au_hal, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 1, (UInt32*)&nframes, sizeof(UInt32)); + if (err1 != noErr) { + jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_MaximumFramesPerSlice"); + printError(err1); + goto error; + } } - in_nChannels = outSize / sizeof(SInt32); - - err1 = AudioUnitGetPropertyInfo(driver->au_hal, kAudioOutputUnitProperty_ChannelMap, - kAudioUnitScope_Output, 0, &outSize, &isWritable); - if (err1 != noErr) { - JCALog("error: calling AudioUnitSetProperty - kAudioOutputUnitProperty_ChannelMap-INFO 0\n"); - printError1(err1); + if (playing && outchannels > 0) { + err1 = AudioUnitSetProperty(driver->au_hal, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0, (UInt32*)&nframes, sizeof(UInt32)); + if (err1 != noErr) { + jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_MaximumFramesPerSlice"); + printError(err1); + goto error; + } } - out_nChannels = outSize / sizeof(SInt32); - - if (chan_out > out_nChannels) { - JCALog("This device hasn't required output channels.\n"); - goto error; - } - if (chan_in > in_nChannels) { - JCALog("This device hasn't required input channels.\n"); - goto error; - } + // Setup channel map + if (capturing && inchannels > 0 && inchannels < in_nChannels) { + SInt32 chanArr[in_nChannels]; + for (i = 0; i < in_nChannels; i++) { + chanArr[i] = -1; + } + for (i = 0; i < inchannels; i++) { + chanArr[i] = i; + } + AudioUnitSetProperty(driver->au_hal, kAudioOutputUnitProperty_ChannelMap , kAudioUnitScope_Input, 1, chanArr, sizeof(SInt32) * in_nChannels); + if (err1 != noErr) { + jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_ChannelMap 1"); + printError(err1); + } + } - if (chan_out < out_nChannels) { - SInt32 chanArr[out_nChannels]; - for (i = 0;i < out_nChannels; i++) { - chanArr[i] = -1; - } - for (i = 0; i < chan_out; i++) { - chanArr[i] = i; - } - err1 = AudioUnitSetProperty(driver->au_hal, kAudioOutputUnitProperty_ChannelMap, - kAudioUnitScope_Output, 0, chanArr, sizeof(SInt32) * out_nChannels); + if (playing && outchannels > 0 && outchannels < out_nChannels) { + SInt32 chanArr[out_nChannels]; + for (i = 0; i < out_nChannels; i++) { + chanArr[i] = -1; + } + for (i = 0; i < outchannels; i++) { + chanArr[i] = i; + } + err1 = AudioUnitSetProperty(driver->au_hal, kAudioOutputUnitProperty_ChannelMap, kAudioUnitScope_Output, 0, chanArr, sizeof(SInt32) * out_nChannels); + if (err1 != noErr) { + jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_ChannelMap 0"); + printError(err1); + } + } + + // Setup stream converters + if (capturing && inchannels > 0) { + srcFormat.mSampleRate = samplerate; + srcFormat.mFormatID = kAudioFormatLinearPCM; + srcFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kLinearPCMFormatFlagIsNonInterleaved; + srcFormat.mBytesPerPacket = sizeof(float); + srcFormat.mFramesPerPacket = 1; + srcFormat.mBytesPerFrame = sizeof(float); + srcFormat.mChannelsPerFrame = outchannels; + srcFormat.mBitsPerChannel = 32; + + err1 = AudioUnitSetProperty(driver->au_hal, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &srcFormat, sizeof(AudioStreamBasicDescription)); if (err1 != noErr) { - JCALog("error: calling AudioUnitSetProperty - kAudioOutputUnitProperty_ChannelMap 0\n"); - printError1(err1); + jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Input"); + printError(err1); } } - - if (chan_in < in_nChannels) { - SInt32 chanArr[in_nChannels]; - for (i = 0; i < in_nChannels; i++) { - chanArr[i] = -1; - } - for(i = 0;i < chan_in; i++) { - chanArr[i] = i; - } - AudioUnitSetProperty(driver->au_hal, kAudioOutputUnitProperty_ChannelMap, - kAudioUnitScope_Input, 1, chanArr, sizeof(SInt32) * in_nChannels); + + if (playing && outchannels > 0) { + dstFormat.mSampleRate = samplerate; + dstFormat.mFormatID = kAudioFormatLinearPCM; + dstFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kLinearPCMFormatFlagIsNonInterleaved; + dstFormat.mBytesPerPacket = sizeof(float); + dstFormat.mFramesPerPacket = 1; + dstFormat.mBytesPerFrame = sizeof(float); + dstFormat.mChannelsPerFrame = inchannels; + dstFormat.mBitsPerChannel = 32; + + err1 = AudioUnitSetProperty(driver->au_hal, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &dstFormat, sizeof(AudioStreamBasicDescription)); if (err1 != noErr) { - JCALog("error: calling AudioUnitSetProperty - kAudioOutputUnitProperty_ChannelMap 1\n"); - printError1(err1); + jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Output"); + printError(err1); } } - srcFormat.mSampleRate = rate; - srcFormat.mFormatID = kAudioFormatLinearPCM; - srcFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | - kLinearPCMFormatFlagIsNonInterleaved; - srcFormat.mBytesPerPacket = sizeof(float); - srcFormat.mFramesPerPacket = 1; - srcFormat.mBytesPerFrame = sizeof(float); - srcFormat.mChannelsPerFrame = chan_out; - srcFormat.mBitsPerChannel = 32; - - err1 = AudioUnitSetProperty(driver->au_hal, kAudioUnitProperty_StreamFormat, - kAudioUnitScope_Input, 0, &srcFormat, sizeof(AudioStreamBasicDescription)); - if (err1 != noErr) { - JCALog("error: calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Input\n"); - printError1(err1); - } + // Setup callbacks + if (inchannels > 0 && outchannels == 0) { + AURenderCallbackStruct output; + output.inputProc = render_input; + output.inputProcRefCon = driver; + err1 = AudioUnitSetProperty(driver->au_hal, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Global, 0, &output, sizeof(output)); + if (err1 != noErr) { + jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_SetRenderCallback 1"); + printError(err1); + goto error; + } + } else { + AURenderCallbackStruct output; + output.inputProc = render; + output.inputProcRefCon = driver; + err1 = AudioUnitSetProperty(driver->au_hal, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &output, sizeof(output)); + if (err1 != noErr) { + jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_SetRenderCallback 0"); + printError(err1); + goto error; + } + } + + if (capturing && inchannels > 0) { + driver->input_list = (AudioBufferList*)malloc(sizeof(UInt32) + inchannels * sizeof(AudioBuffer)); + if (driver->input_list == 0) + goto error; + driver->input_list->mNumberBuffers = inchannels; - dstFormat.mSampleRate = rate; - dstFormat.mFormatID = kAudioFormatLinearPCM; - dstFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | - kLinearPCMFormatFlagIsNonInterleaved; - dstFormat.mBytesPerPacket = sizeof(float); - dstFormat.mFramesPerPacket = 1; - dstFormat.mBytesPerFrame = sizeof(float); - dstFormat.mChannelsPerFrame = chan_in; - dstFormat.mBitsPerChannel = 32; - - err1 = AudioUnitSetProperty(driver->au_hal, kAudioUnitProperty_StreamFormat, - kAudioUnitScope_Output, 1, &dstFormat, sizeof(AudioStreamBasicDescription)); - if (err1 != noErr) { - JCALog("error: calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Output\n"); - printError1(err1); - } - - if (chan_in > 0 && chan_out== 0) { - AURenderCallbackStruct output; - output.inputProc = render_input; - output.inputProcRefCon = driver; - err1 = AudioUnitSetProperty(driver->au_hal, kAudioUnitProperty_SetRenderCallback, - kAudioUnitScope_Output, 1, &output, sizeof(output)); - if (err1 != noErr) { - JCALog("AudioUnitSetProperty - kAudioUnitProperty_SetRenderCallback 1\n"); - printError1(err1); - goto error; - } - } else { - AURenderCallbackStruct output; - output.inputProc = render; - output.inputProcRefCon = driver; - err1 = AudioUnitSetProperty(driver->au_hal, kAudioUnitProperty_SetRenderCallback, - kAudioUnitScope_Input, 0, &output, sizeof(output)); - if (err1 != noErr) { - JCALog("AudioUnitSetProperty - kAudioUnitProperty_SetRenderCallback 0\n"); - printError1(err1); - goto error; + // Prepare buffers + for (i = 0; i < driver->capture_nchannels; i++) { + driver->input_list->mBuffers[i].mNumberChannels = 1; + driver->input_list->mBuffers[i].mDataByteSize = nframes * sizeof(float); } } - - driver->input_list = (AudioBufferList*)malloc(sizeof(UInt32) + chan_in * sizeof(AudioBuffer)); - if (driver->input_list == 0) - goto error; - driver->input_list->mNumberBuffers = chan_in; - driver->output_list = (AudioBufferList*)malloc(sizeof(UInt32) + chan_out * sizeof(AudioBuffer)); - if (driver->output_list == 0) - goto error; - driver->output_list->mNumberBuffers = chan_out; - err = AudioDeviceAddPropertyListener(driver->device_id, 0, true, kAudioDeviceProcessorOverload, notification, driver); if (err != noErr) goto error; - // Prepare buffers - for (i = 0; i < driver->capture_nchannels; i++) { - driver->input_list->mBuffers[i].mNumberChannels = 1; - driver->input_list->mBuffers[i].mDataByteSize = frames_per_cycle * sizeof(float); - } - - for (i = 0; i < driver->playback_nchannels; i++) { - driver->output_list->mBuffers[i].mNumberChannels = 1; - driver->output_list->mBuffers[i].mDataByteSize = frames_per_cycle * sizeof(float); - } - + driver->playback_nchannels = outchannels; + driver->capture_nchannels = inchannels; return ((jack_driver_t *) driver); error: @@ -784,8 +927,7 @@ static void coreaudio_driver_delete(coreaudio_driver_t * driver) { AudioDeviceRemovePropertyListener(driver->device_id, 0, true, kAudioDeviceProcessorOverload, notification); free(driver->input_list); - free(driver->output_list); - AudioUnitUninitialize(driver->au_hal); + AudioUnitUninitialize(driver->au_hal); CloseComponent(driver->au_hal); free(driver); } @@ -831,20 +973,20 @@ jack_driver_desc_t *driver_get_descriptor() strcpy(desc->params[i].long_desc, desc->params[i].short_desc); i++; - strcpy(desc->params[i].name, "capture"); - desc->params[i].character = 'C'; - desc->params[i].type = JackDriverParamBool; - desc->params[i].value.i = TRUE; - strcpy(desc->params[i].short_desc, "Whether or not to capture"); - strcpy(desc->params[i].long_desc, desc->params[i].short_desc); + strcpy(desc->params[i].name, "capture"); + desc->params[i].character = 'C'; + desc->params[i].type = JackDriverParamString; + strcpy(desc->params[i].value.str, "will take default CoreAudio input device"); + strcpy(desc->params[i].short_desc, "Provide capture ports. Optionally set CoreAudio device name"); + strcpy(desc->params[i].long_desc, desc->params[i].short_desc); - i++; - strcpy(desc->params[i].name, "playback"); - desc->params[i].character = 'P'; - desc->params[i].type = JackDriverParamBool; - desc->params[i].value.i = TRUE; - strcpy(desc->params[i].short_desc, "Whether or not to playback"); - strcpy(desc->params[i].long_desc, desc->params[i].short_desc); + i++; + strcpy(desc->params[i].name, "playback"); + desc->params[i].character = 'P'; + desc->params[i].type = JackDriverParamString; + strcpy(desc->params[i].value.str, "will take default CoreAudio output device"); + strcpy(desc->params[i].short_desc, "Provide playback ports. Optionally set CoreAudio device name"); + strcpy(desc->params[i].long_desc, desc->params[i].short_desc); i++; strcpy(desc->params[i].name, "duplex"); @@ -871,12 +1013,13 @@ jack_driver_desc_t *driver_get_descriptor() strcpy(desc->params[i].long_desc, desc->params[i].short_desc); i++; - strcpy(desc->params[i].name, "name"); - desc->params[i].character = 'n'; - desc->params[i].type = JackDriverParamString; - desc->params[i].value.ui = 128U; - strcpy(desc->params[i].short_desc, "Driver name"); - strcpy(desc->params[i].long_desc, desc->params[i].short_desc); + strcpy(desc->params[i].name, "name"); + desc->params[i].character = 'n'; + desc->params[i].type = JackDriverParamString; + desc->params[i].value.ui = 128U; + strcpy(desc->params[i].value.str, "will take default CoreAudio device name"); + strcpy(desc->params[i].short_desc, "CoreAudio device name"); + strcpy(desc->params[i].long_desc, desc->params[i].short_desc); i++; strcpy(desc->params[i].name, "input-latency"); @@ -912,9 +1055,10 @@ jack_driver_t *driver_initialize(jack_client_t * client, jack_nframes_t frames_per_interrupt = 128; int capture = FALSE; int playback = FALSE; - int chan_in = 2; - int chan_out = 2; - char *name = NULL; + int chan_in = 0; + int chan_out = 0; + char* capture_pcm_name = NULL; + char* playback_pcm_name = NULL; const JSList *node; const jack_driver_param_t *param; jack_nframes_t systemic_input_latency = 0; @@ -926,7 +1070,8 @@ jack_driver_t *driver_initialize(jack_client_t * client, switch (param->character) { case 'n': - name = (char *) param->value.str; + capture_pcm_name = strdup(param->value.str); + playback_pcm_name = strdup(param->value.str); break; case 'D': @@ -947,11 +1092,17 @@ jack_driver_t *driver_initialize(jack_client_t * client, break; case 'C': - capture = param->value.i; + capture = TRUE; + if (strcmp(param->value.str, "none") != 0) { + capture_pcm_name = strdup(param->value.str); + } break; case 'P': - playback = param->value.i; + playback = TRUE; + if (strcmp(param->value.str, "none") != 0) { + playback_pcm_name = strdup(param->value.str); + } break; case 'r': @@ -984,7 +1135,7 @@ jack_driver_t *driver_initialize(jack_client_t * client, return coreaudio_driver_new("coreaudio", client, frames_per_interrupt, srate, capture, playback, chan_in, - chan_out, name, systemic_input_latency, systemic_output_latency); + chan_out, capture_pcm_name, playback_pcm_name, systemic_input_latency, systemic_output_latency); } void driver_finish(jack_driver_t * driver) diff --git a/drivers/coreaudio/coreaudio_driver.h b/drivers/coreaudio/coreaudio_driver.h index 99eabf6..b6a60ab 100755 --- a/drivers/coreaudio/coreaudio_driver.h +++ b/drivers/coreaudio/coreaudio_driver.h @@ -55,11 +55,11 @@ typedef struct { JSList *capture_ports; JSList *playback_ports; - char driver_name[256]; + char capture_driver_name[256]; + char playback_driver_name[256]; AudioUnit au_hal; AudioBufferList* input_list; - AudioBufferList* output_list; AudioDeviceID device_id; jack_nframes_t capture_frame_latency; |