--- jack-audio-connection-kit-0.100.0/drivers/coreaudio/coreaudio_driver.c 2005-06-09 13:14:45 -0500 +++ jack-cvs/drivers/coreaudio/coreaudio_driver.c 2005-09-10 18:47:27 -0500 @@ -37,10 +37,10 @@ May 20, 2005: S.Letz: Add "systemic" latencies management. Jun 06, 2005: S.Letz: Remove the "-I" parameter, change the semantic of "-n" parameter : -n (driver name) now correctly uses the PropertyDeviceUID (persistent accross reboot...) as the identifier for the used coreaudio driver. + Jun 14, 2005: S.Letz: Since the "-I" parameter is not used anymore, rename the "systemic" latencies management parametes "-I" and "-O" like for the ALSA driver. + 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. - TODO: - - fix cpu load behavior. - - multiple-device processing. */ #include @@ -98,15 +98,15 @@ JCALog("error code : kAudioDevicePermissionsError\n"); break; default: - JCALog("error code : unknown\n"); + JCALog("error code : unknown %ld\n", err); break; } #endif } -static OSStatus get_device_name_from_id(AudioDeviceID id, char name[60]) +static OSStatus get_device_name_from_id(AudioDeviceID id, char name[256]) { - UInt32 size = sizeof(char) * 60; + UInt32 size = sizeof(char) * 256; OSStatus res = AudioDeviceGetProperty(id, 0, false, kAudioDevicePropertyDeviceName, &size, @@ -124,27 +124,35 @@ } else { OSStatus res = AudioHardwareGetProperty(kAudioHardwarePropertyDeviceForUID, &size, &value); CFRelease(inIUD); - return res; + JCALog("get_device_id_from_uid %s %ld \n", UID, *id); + return (*id == kAudioDeviceUnknown) ? kAudioHardwareBadDeviceError : res; } } -static OSStatus get_device_id_from_num(int i, AudioDeviceID * id) +static OSStatus get_default_device(AudioDeviceID * id) { - OSStatus theStatus; - UInt32 theSize; - int nDevices; - AudioDeviceID* theDeviceList; - - theStatus = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices, - &theSize, NULL); - nDevices = theSize / sizeof(AudioDeviceID); - theDeviceList = - (AudioDeviceID*) malloc(nDevices * sizeof(AudioDeviceID)); - theStatus = AudioHardwareGetProperty(kAudioHardwarePropertyDevices, - &theSize, theDeviceList); - - *id = theDeviceList[i]; - return theStatus; + OSStatus res; + UInt32 theSize = sizeof(UInt32); + AudioDeviceID inDefault; + AudioDeviceID outDefault; + + if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice, + &theSize, &inDefault)) != noErr) + return res; + + if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, + &theSize, &outDefault)) != noErr) + return res; + + JCALog("get_default_device: input %ld output %ld\n", inDefault, outDefault); + + // Get the device only if default input and ouput are the same + if (inDefault == outDefault) { + *id = inDefault; + return noErr; + } else { + return kAudioHardwareBadDeviceError; + } } static OSStatus render(void *inRefCon, @@ -257,8 +265,6 @@ */ for (chn = 0; chn < driver->capture_nchannels; chn++) { - //snprintf (buf, sizeof(buf) - 1, "capture_%lu", chn+1); - err = AudioDeviceGetPropertyInfo(driver->device_id, chn + 1, true, kAudioDevicePropertyChannelName, &size, &isWritable); if (err == noErr && size > 0) { err = AudioDeviceGetProperty(driver->device_id, chn + 1, true, kAudioDevicePropertyChannelName, &size, channel_name); @@ -293,8 +299,6 @@ port_flags = JackPortIsInput | JackPortIsPhysical | JackPortIsTerminal; for (chn = 0; chn < driver->playback_nchannels; chn++) { - //snprintf (buf, sizeof(buf) - 1, "playback_%lu", chn+1); - err = AudioDeviceGetPropertyInfo(driver->device_id, chn + 1, false, kAudioDevicePropertyChannelName, &size, &isWritable); if (err == noErr && size > 0) { err = AudioDeviceGetProperty(driver->device_id, chn + 1, false, kAudioDevicePropertyChannelName, &size, channel_name); @@ -428,8 +432,9 @@ ComponentResult err1; UInt32 outSize; Boolean isWritable; - AudioStreamBasicDescription srcFormat, dstFormat, sampleRate; + AudioStreamBasicDescription srcFormat, dstFormat; int in_nChannels, out_nChannels, i; + Float64 nominalSampleRate; driver = (coreaudio_driver_t *) calloc(1, sizeof(coreaudio_driver_t)); jack_driver_init((jack_driver_t *) driver); @@ -459,14 +464,17 @@ driver->playback_frame_latency = playback_latency; if (driver_uid) { - if (get_device_id_from_uid(driver_uid, &driver->device_id) != noErr) - return NULL; + if (get_device_id_from_uid(driver_uid, &driver->device_id) != noErr) { + if (get_default_device(&driver->device_id) != noErr) + goto error; + } } else { - get_device_id_from_num(0, &driver->device_id); // takes a default value (first device) + if (get_default_device(&driver->device_id) != noErr) + goto error; } if (get_device_name_from_id(driver->device_id, driver->driver_name) != noErr) - return NULL; + goto error; driver->client = client; driver->period_usecs = @@ -481,31 +489,42 @@ err = AudioDeviceSetProperty(driver->device_id, NULL, 0, false, kAudioDevicePropertyBufferFrameSize, outSize, &frames_per_cycle); if (err != noErr) { - jack_error("Cannot set buffer size %ld\n", frames_per_cycle); + JCALog("Cannot set buffer size %ld\n", frames_per_cycle); printError1(err); - return NULL; + goto error; } - - // Setting sample rate - outSize = sizeof(AudioStreamBasicDescription); + + outSize = sizeof(Float64); err = AudioDeviceGetProperty(driver->device_id, 0, false, - kAudioDevicePropertyStreamFormat, &outSize, &sampleRate); + kAudioDevicePropertyNominalSampleRate, &outSize, &nominalSampleRate); if (err != noErr) { - jack_error("Cannot get sample rate\n"); + JCALog("Cannot get sample rate\n"); printError1(err); - return NULL; - } + goto error; + } else { + JCALog("Read nominalSampleRate %f\n", nominalSampleRate); + } - if (rate != (unsigned long)sampleRate.mSampleRate) { - sampleRate.mSampleRate = (Float64)rate; + if (rate != (jack_nframes_t)nominalSampleRate) { + nominalSampleRate = (Float64)rate; err = AudioDeviceSetProperty(driver->device_id, NULL, 0, - false, kAudioDevicePropertyStreamFormat, outSize, &sampleRate); + false, kAudioDevicePropertyNominalSampleRate, outSize, &nominalSampleRate); if (err != noErr) { - jack_error("Cannot set sample rate %ld\n", rate); + JCALog("Cannot set sample rate %ld\n", rate); printError1(err); - return NULL; + 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); + } // AUHAL ComponentDescription cd = {kAudioUnitType_Output, @@ -516,22 +535,18 @@ if (err1 != noErr) 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"); - return NULL; - } - err1 = AudioUnitInitialize(driver->au_hal); - if (err1 != noErr) + if (err1 != noErr) { + printError1(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; } @@ -541,28 +556,42 @@ kAudioUnitScope_Input, 1, &outSize, sizeof(outSize)); if (err1 != noErr) { JCALog("error: calling AudioUnitSetProperty - kAudioOutputUnitProperty_EnableIO,kAudioUnitScope_Input\n"); + printError1(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); + 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) + if (err1 != noErr) { JCALog("error: calling AudioUnitSetProperty - kAudioOutputUnitProperty_ChannelMap-INFO 1\n"); + printError1(err1); + } in_nChannels = outSize / sizeof(SInt32); err1 = AudioUnitGetPropertyInfo(driver->au_hal, kAudioOutputUnitProperty_ChannelMap, kAudioUnitScope_Output, 0, &outSize, &isWritable); - if (err1 != noErr) + if (err1 != noErr) { JCALog("error: calling AudioUnitSetProperty - kAudioOutputUnitProperty_ChannelMap-INFO 0\n"); + printError1(err1); + } out_nChannels = outSize / sizeof(SInt32); @@ -576,7 +605,7 @@ } if (chan_out < out_nChannels) { - SInt32 chanArr[out_nChannels]; // ??? + SInt32 chanArr[out_nChannels]; for (i = 0;i < out_nChannels; i++) { chanArr[i] = -1; } @@ -585,8 +614,10 @@ } err1 = AudioUnitSetProperty(driver->au_hal, kAudioOutputUnitProperty_ChannelMap, kAudioUnitScope_Output, 0, chanArr, sizeof(SInt32) * out_nChannels); - if (err1 != noErr) + if (err1 != noErr) { JCALog("error: calling AudioUnitSetProperty - kAudioOutputUnitProperty_ChannelMap 0\n"); + printError1(err1); + } } if (chan_in < in_nChannels) { @@ -599,8 +630,10 @@ } AudioUnitSetProperty(driver->au_hal, kAudioOutputUnitProperty_ChannelMap, kAudioUnitScope_Input, 1, chanArr, sizeof(SInt32) * in_nChannels); - if (err1 != noErr) + if (err1 != noErr) { JCALog("error: calling AudioUnitSetProperty - kAudioOutputUnitProperty_ChannelMap 1\n"); + printError1(err1); + } } srcFormat.mSampleRate = rate; @@ -617,8 +650,10 @@ err1 = AudioUnitSetProperty(driver->au_hal, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &srcFormat, sizeof(AudioStreamBasicDescription)); - if (err1 != noErr) + if (err1 != noErr) { JCALog("error: calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Input\n"); + printError1(err1); + } dstFormat.mSampleRate = rate; dstFormat.mFormatID = kAudioFormatLinearPCM; @@ -634,8 +669,10 @@ err1 = AudioUnitSetProperty(driver->au_hal, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &dstFormat, sizeof(AudioStreamBasicDescription)); - if (err1 != noErr) + if (err1 != noErr) { JCALog("error: calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Output\n"); + printError1(err1); + } if (chan_in > 0 && chan_out== 0) { AURenderCallbackStruct output; @@ -645,6 +682,7 @@ kAudioUnitScope_Output, 1, &output, sizeof(output)); if (err1 != noErr) { JCALog("AudioUnitSetProperty - kAudioUnitProperty_SetRenderCallback 1\n"); + printError1(err1); goto error; } } else { @@ -655,6 +693,7 @@ kAudioUnitScope_Input, 0, &output, sizeof(output)); if (err1 != noErr) { JCALog("AudioUnitSetProperty - kAudioUnitProperty_SetRenderCallback 0\n"); + printError1(err1); goto error; } } @@ -689,7 +728,7 @@ error: AudioUnitUninitialize(driver->au_hal); CloseComponent(driver->au_hal); - jack_error("Cannot open the coreaudio driver\n"); + jack_error("Cannot open the coreaudio driver"); free(driver); return NULL; } @@ -796,7 +835,7 @@ i++; strcpy(desc->params[i].name, "input-latency"); - desc->params[i].character = 'l'; + desc->params[i].character = 'I'; desc->params[i].type = JackDriverParamUInt; desc->params[i].value.i = 0; strcpy(desc->params[i].short_desc, "Extra input latency"); @@ -804,7 +843,7 @@ i++; strcpy(desc->params[i].name, "output-latency"); - desc->params[i].character = 'L'; + desc->params[i].character = 'O'; desc->params[i].type = JackDriverParamUInt; desc->params[i].value.i = 0; strcpy(desc->params[i].short_desc, "Extra output latency"); @@ -870,18 +909,17 @@ frames_per_interrupt = (unsigned int) param->value.ui; break; - case 'l': + case 'I': systemic_input_latency = param->value.ui; break; - case 'L': + case 'O': systemic_output_latency = param->value.ui; break; } } /* duplex is the default */ - if (!capture && !playback) { capture = TRUE; playback = TRUE;