From a1e4f13085b35a8485ea10ab05dfdae1aec61dd0 Mon Sep 17 00:00:00 2001 From: sletz Date: Fri, 30 Oct 2009 13:50:10 +0000 Subject: [PATCH] In JackCoreAudioDriver, improve management of input/output channels: -1 is now used internally to indicate a wanted max value. git-svn-id: http://subversion.jackaudio.org/jack/jack2/trunk/jackmp@3682 0c269be4-1314-0410-8aa9-9f06e86f4224 --- ChangeLog | 7 + common/JackAudioAdapterInterface.cpp | 12 +- common/JackDriverLoader.cpp | 2 +- macosx/coreaudio/JackCoreAudioAdapter.cpp | 293 +++++++++++++--------- macosx/coreaudio/JackCoreAudioAdapter.h | 15 +- macosx/coreaudio/JackCoreAudioDriver.cpp | 195 ++++++++------ macosx/coreaudio/JackCoreAudioDriver.h | 3 +- 7 files changed, 331 insertions(+), 196 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1de114eb..aef1bad9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -25,6 +25,13 @@ Paul Davis Jackdmp changes log --------------------------- +2009-10-30 Stephane Letz + + * In JackCoreAudioDriver, improve management of input/output channels: -1 is now used internally to indicate a wanted max value. + * In JackCoreAudioDriver::OpenAUHAL, correct stream format setup and cleanup. + * Correct crash bug in JackAudioAdapterInterface when not input is used in adapter (temporary fix...) + * Sync JackCoreAudioAdapter code on JackCoreAudioDriver one. + 2009-10-29 Stephane Letz * In JackCoreAudioDriver::Start, wait for the audio driver to effectively start (use the MeasureCallback). diff --git a/common/JackAudioAdapterInterface.cpp b/common/JackAudioAdapterInterface.cpp index 3dbc2b67..dff17818 100644 --- a/common/JackAudioAdapterInterface.cpp +++ b/common/JackAudioAdapterInterface.cpp @@ -230,10 +230,18 @@ namespace Jack // Finer estimation of the position in the ringbuffer int delta_frames = (fPullAndPushTime > 0) ? (int)((float(long(GetMicroSeconds() - fPullAndPushTime)) * float(fAdaptedSampleRate)) / 1000000.f) : 0; - double ratio = fPIControler.GetRatio(fCaptureRingBuffer[0]->GetError() - delta_frames); + + double ratio = 1; + + // TODO : done like this just to avoid crash when input only or output only... + if (fCaptureChannels > 0) + ratio = fPIControler.GetRatio(fCaptureRingBuffer[0]->GetError() - delta_frames); + else if (fPlaybackChannels > 0) + ratio = fPIControler.GetRatio(fPlaybackRingBuffer[0]->GetError() - delta_frames); #ifdef JACK_MONITOR - fTable.Write(fCaptureRingBuffer[0]->GetError(), fCaptureRingBuffer[0]->GetError() - delta_frames, ratio, 1/ratio, fCaptureRingBuffer[0]->ReadSpace(), fCaptureRingBuffer[0]->ReadSpace()); + if (fCaptureRingBuffer[0] != NULL) + fTable.Write(fCaptureRingBuffer[0]->GetError(), fCaptureRingBuffer[0]->GetError() - delta_frames, ratio, 1/ratio, fCaptureRingBuffer[0]->ReadSpace(), fCaptureRingBuffer[0]->ReadSpace()); #endif // Push/pull from ringbuffer diff --git a/common/JackDriverLoader.cpp b/common/JackDriverLoader.cpp index 52c4aeed..428d3ab0 100644 --- a/common/JackDriverLoader.cpp +++ b/common/JackDriverLoader.cpp @@ -62,7 +62,7 @@ SERVER_EXPORT void jack_print_driver_options (jack_driver_desc_t* desc, FILE* fi fprintf (file, "\t-%c, --%s \t%s (default: %s)\n", desc->params[i].character, desc->params[i].name, - desc->params[i].short_desc, + desc->params[i].long_desc, arg_default); } } diff --git a/macosx/coreaudio/JackCoreAudioAdapter.cpp b/macosx/coreaudio/JackCoreAudioAdapter.cpp index 9b04253a..630366ec 100644 --- a/macosx/coreaudio/JackCoreAudioAdapter.cpp +++ b/macosx/coreaudio/JackCoreAudioAdapter.cpp @@ -26,6 +26,20 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. namespace Jack { +static void PrintStreamDesc(AudioStreamBasicDescription *inDesc) +{ + jack_log("- - - - - - - - - - - - - - - - - - - -"); + jack_log(" Sample Rate:%f", inDesc->mSampleRate); + jack_log(" Format ID:%.*s", (int) sizeof(inDesc->mFormatID), (char*)&inDesc->mFormatID); + jack_log(" Format Flags:%lX", inDesc->mFormatFlags); + jack_log(" Bytes per Packet:%ld", inDesc->mBytesPerPacket); + jack_log(" Frames per Packet:%ld", inDesc->mFramesPerPacket); + jack_log(" Bytes per Frame:%ld", inDesc->mBytesPerFrame); + jack_log(" Channels per Frame:%ld", inDesc->mChannelsPerFrame); + jack_log(" Bits per Channel:%ld", inDesc->mBitsPerChannel); + jack_log("- - - - - - - - - - - - - - - - - - - -"); +} + static OSStatus DisplayDeviceNames() { UInt32 size; @@ -279,19 +293,33 @@ OSStatus JackCoreAudioAdapter::Render(void *inRefCon, JackCoreAudioAdapter::JackCoreAudioAdapter(jack_nframes_t buffer_size, jack_nframes_t sample_rate, const JSList* params) :JackAudioAdapterInterface(buffer_size, sample_rate), fInputData(0), fCapturing(false), fPlaying(false), fState(false) { - const JSList* node; const jack_driver_param_t* param; - + int in_nChannels = 0; + int out_nChannels = 0; char captureName[256]; char playbackName[256]; - fCaptureUID[0] = 0; fPlaybackUID[0] = 0; // Default values - fCaptureChannels = 0; - fPlaybackChannels = 0; + fCaptureChannels = -1; + fPlaybackChannels = -1; + + SInt32 major; + SInt32 minor; + Gestalt(gestaltSystemVersionMajor, &major); + Gestalt(gestaltSystemVersionMinor, &minor); + + // Starting with 10.6 systems, the HAL notification thread is created internally + if (major == 10 && minor >= 6) { + CFRunLoopRef theRunLoop = NULL; + AudioObjectPropertyAddress theAddress = { kAudioHardwarePropertyRunLoop, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster }; + OSStatus theError = AudioObjectSetPropertyData (kAudioObjectSystemObject, &theAddress, 0, NULL, sizeof(CFRunLoopRef), &theRunLoop); + if (theError != noErr) { + jack_error("JackCoreAudioAdapter::Open kAudioHardwarePropertyRunLoop error"); + } + } for (node = params; node; node = jack_slist_next(node)) { param = (const jack_driver_param_t*) node->data; @@ -357,26 +385,26 @@ JackCoreAudioAdapter::JackCoreAudioAdapter(jack_nframes_t buffer_size, jack_nfra fCapturing = true; fPlaying = true; } - - int in_nChannels = 0; - int out_nChannels = 0; - if (SetupDevices(fCaptureUID, fPlaybackUID, captureName, playbackName) < 0) + if (SetupDevices(fCaptureUID, fPlaybackUID, captureName, playbackName, fAdaptedSampleRate) < 0) throw -1; if (SetupChannels(fCapturing, fPlaying, fCaptureChannels, fPlaybackChannels, in_nChannels, out_nChannels, true) < 0) throw -1; + + if (SetupBufferSize(fAdaptedBufferSize) < 0) + throw -1; - if (SetupBufferSizeAndSampleRate(fAdaptedBufferSize, fAdaptedSampleRate) < 0) + if (SetupSampleRate(fAdaptedSampleRate) < 0) throw -1; - + + if (OpenAUHAL(fCapturing, fPlaying, fCaptureChannels, fPlaybackChannels, in_nChannels, out_nChannels, fAdaptedBufferSize, fAdaptedSampleRate) < 0) + throw -1; + if (fCapturing && fCaptureChannels > 0) if (SetupBuffers(fCaptureChannels) < 0) throw -1; - - if (OpenAUHAL(fCapturing, fPlaying, fCaptureChannels, fPlaybackChannels, in_nChannels, out_nChannels, fAdaptedBufferSize, fAdaptedSampleRate, true) < 0) - throw -1; - + if (AddListeners() < 0) throw -1; } @@ -484,7 +512,8 @@ OSStatus JackCoreAudioAdapter::GetDeviceNameFromID(AudioDeviceID id, char* name) int JackCoreAudioAdapter::SetupDevices(const char* capture_driver_uid, const char* playback_driver_uid, char* capture_driver_name, - char* playback_driver_name) + char* playback_driver_name, + jack_nframes_t samplerate) { capture_driver_name[0] = 0; playback_driver_name[0] = 0; @@ -515,7 +544,7 @@ int JackCoreAudioAdapter::SetupDevices(const char* capture_driver_uid, return -1; if (GetDeviceIDFromUID(playback_driver_uid, &playbackID) != noErr) return -1; - if (CreateAggregateDevice(captureID, playbackID, &fDeviceID) != noErr) + if (CreateAggregateDevice(captureID, playbackID, samplerate, &fDeviceID) != noErr) return -1; } @@ -607,72 +636,82 @@ int JackCoreAudioAdapter::SetupChannels(bool capturing, return -1; } - if (inchannels == 0) { + if (inchannels == -1) { jack_log("Setup max in channels = %ld", in_nChannels); inchannels = in_nChannels; } - if (outchannels == 0) { + if (outchannels == -1) { jack_log("Setup max out channels = %ld", out_nChannels); outchannels = out_nChannels; } - + return 0; } -int JackCoreAudioAdapter::SetupBufferSizeAndSampleRate(jack_nframes_t nframes, jack_nframes_t samplerate) +int JackCoreAudioAdapter::SetupBufferSize(jack_nframes_t buffer_size) { - OSStatus err = noErr; - UInt32 outSize; - Float64 sampleRate; - // Setting buffer size - outSize = sizeof(UInt32); - err = AudioDeviceSetProperty(fDeviceID, NULL, 0, false, kAudioDevicePropertyBufferFrameSize, outSize, &nframes); + UInt32 outSize = sizeof(UInt32); + OSStatus err = AudioDeviceSetProperty(fDeviceID, NULL, 0, false, kAudioDevicePropertyBufferFrameSize, outSize, &buffer_size); if (err != noErr) { - jack_error("Cannot set buffer size %ld", nframes); + jack_error("Cannot set buffer size %ld", buffer_size); printError(err); return -1; } + + return 0; +} +int JackCoreAudioAdapter::SetupSampleRate(jack_nframes_t samplerate) +{ + return SetupSampleRateAux(fDeviceID, samplerate); +} + +int JackCoreAudioAdapter::SetupSampleRateAux(AudioDeviceID inDevice, jack_nframes_t samplerate) +{ + OSStatus err = noErr; + UInt32 outSize; + Float64 sampleRate; + // Get sample rate outSize = sizeof(Float64); - err = AudioDeviceGetProperty(fDeviceID, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, &outSize, &sampleRate); + err = AudioDeviceGetProperty(inDevice, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, &outSize, &sampleRate); if (err != noErr) { jack_error("Cannot get current sample rate"); printError(err); return -1; } - + // If needed, set new sample rate if (samplerate != (jack_nframes_t)sampleRate) { sampleRate = (Float64)samplerate; - + // To get SR change notification - err = AudioDeviceAddPropertyListener(fDeviceID, 0, true, kAudioDevicePropertyNominalSampleRate, SRNotificationCallback, this); + err = AudioDeviceAddPropertyListener(inDevice, 0, true, kAudioDevicePropertyNominalSampleRate, SRNotificationCallback, this); if (err != noErr) { jack_error("Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyNominalSampleRate"); printError(err); return -1; } - err = AudioDeviceSetProperty(fDeviceID, NULL, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, outSize, &sampleRate); + err = AudioDeviceSetProperty(inDevice, NULL, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, outSize, &sampleRate); if (err != noErr) { jack_error("Cannot set sample rate = %ld", samplerate); printError(err); return -1; } - + // Waiting for SR change notification int count = 0; - while (!fState && count++ < 100) { + while (!fState && count++ < WAIT_COUNTER) { usleep(100000); - jack_log("Wait count = %ld", count); + jack_log("Wait count = %d", count); } - + // Remove SR change notification - AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioDevicePropertyNominalSampleRate, SRNotificationCallback); + AudioDeviceRemovePropertyListener(inDevice, 0, true, kAudioDevicePropertyNominalSampleRate, SRNotificationCallback); } - + return 0; } @@ -706,20 +745,21 @@ void JackCoreAudioAdapter::DisposeBuffers() } int JackCoreAudioAdapter::OpenAUHAL(bool capturing, - bool playing, - int inchannels, - int outchannels, - int in_nChannels, - int out_nChannels, - jack_nframes_t buffer_size, - jack_nframes_t samplerate, - bool strict) + bool playing, + int inchannels, + int outchannels, + int in_nChannels, + int out_nChannels, + jack_nframes_t buffer_size, + jack_nframes_t samplerate) { ComponentResult err1; UInt32 enableIO; AudioStreamBasicDescription srcFormat, dstFormat; + AudioDeviceID currAudioDeviceID; + UInt32 size; - jack_log("OpenAUHAL capturing = %ld playing = %ld inchannels = %ld outchannels = %ld in_nChannels = %ld out_nChannels = %ld ", capturing, playing, inchannels, outchannels, in_nChannels, out_nChannels); + jack_log("OpenAUHAL capturing = %d playing = %d inchannels = %d outchannels = %d in_nChannels = %d out_nChannels = %d", capturing, playing, inchannels, outchannels, in_nChannels, out_nChannels); if (inchannels == 0 && outchannels == 0) { jack_error("No input and output channels..."); @@ -734,14 +774,14 @@ int JackCoreAudioAdapter::OpenAUHAL(bool capturing, if (err1 != noErr) { jack_error("Error calling OpenAComponent"); printError(err1); - return -1; + goto error; } err1 = AudioUnitInitialize(fAUHAL); if (err1 != noErr) { jack_error("Cannot initialize AUHAL unit"); printError(err1); - return -1; + goto error; } // Start I/O @@ -757,8 +797,7 @@ int JackCoreAudioAdapter::OpenAUHAL(bool capturing, if (err1 != noErr) { jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input"); printError(err1); - if (strict) - return -1; + goto error; } if (playing && outchannels > 0) { @@ -773,18 +812,15 @@ int JackCoreAudioAdapter::OpenAUHAL(bool capturing, if (err1 != noErr) { jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_EnableIO,kAudioUnitScope_Output"); printError(err1); - if (strict) - return -1; + goto error; } - AudioDeviceID currAudioDeviceID; - UInt32 size = sizeof(AudioDeviceID); + size = sizeof(AudioDeviceID); err1 = AudioUnitGetProperty(fAUHAL, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &currAudioDeviceID, &size); if (err1 != noErr) { jack_error("Error calling AudioUnitGetProperty - kAudioOutputUnitProperty_CurrentDevice"); printError(err1); - if (strict) - return -1; + goto error; } else { jack_log("AudioUnitGetPropertyCurrentDevice = %d", currAudioDeviceID); } @@ -794,28 +830,16 @@ int JackCoreAudioAdapter::OpenAUHAL(bool capturing, if (err1 != noErr) { jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_CurrentDevice"); printError(err1); - if (strict) - return -1; + goto error; } - - err1 = AudioUnitGetProperty(fAUHAL, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &currAudioDeviceID, &size); - if (err1 != noErr) { - jack_error("Error calling AudioUnitGetProperty - kAudioOutputUnitProperty_CurrentDevice"); - printError(err1); - if (strict) - return -1; - } else { - jack_log("AudioUnitGetPropertyCurrentDevice = %d", currAudioDeviceID); - } - + // Set buffer size if (capturing && inchannels > 0) { err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 1, (UInt32*)&buffer_size, sizeof(UInt32)); if (err1 != noErr) { jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_MaximumFramesPerSlice"); printError(err1); - if (strict) - return -1; + goto error; } } @@ -824,8 +848,7 @@ int JackCoreAudioAdapter::OpenAUHAL(bool capturing, if (err1 != noErr) { jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_MaximumFramesPerSlice"); printError(err1); - if (strict) - return -1; + goto error; } } @@ -842,6 +865,7 @@ int JackCoreAudioAdapter::OpenAUHAL(bool capturing, if (err1 != noErr) { jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_ChannelMap 1"); printError(err1); + goto error; } } @@ -857,40 +881,71 @@ int JackCoreAudioAdapter::OpenAUHAL(bool capturing, if (err1 != noErr) { jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_ChannelMap 0"); printError(err1); + goto error; } } // Setup stream converters - jack_log("Setup AUHAL input stream converter SR = %ld", samplerate); - 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(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &srcFormat, sizeof(AudioStreamBasicDescription)); - if (err1 != noErr) { - jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Input"); - printError(err1); + if (capturing && inchannels > 0) { + + size = sizeof(AudioStreamBasicDescription); + err1 = AudioUnitGetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 0, &srcFormat, &size); + if (err1 != noErr) { + jack_error("Error calling AudioUnitGetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Input"); + printError(err1); + goto error; + } + PrintStreamDesc(&srcFormat); + + jack_log("Setup AUHAL input stream converter SR = %ld", samplerate); + srcFormat.mSampleRate = samplerate; + srcFormat.mFormatID = kAudioFormatLinearPCM; + srcFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kLinearPCMFormatFlagIsNonInterleaved; + srcFormat.mBytesPerPacket = sizeof(float); + srcFormat.mFramesPerPacket = 1; + srcFormat.mBytesPerFrame = sizeof(float); + srcFormat.mChannelsPerFrame = inchannels; + srcFormat.mBitsPerChannel = 32; + PrintStreamDesc(&srcFormat); + + err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &srcFormat, sizeof(AudioStreamBasicDescription)); + + if (err1 != noErr) { + jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Input"); + printError(err1); + goto error; + } } - jack_log("Setup AUHAL output stream converter SR = %ld", samplerate); - 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(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &dstFormat, sizeof(AudioStreamBasicDescription)); - if (err1 != noErr) { - jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Output"); - printError(err1); + if (playing && outchannels > 0) { + + size = sizeof(AudioStreamBasicDescription); + err1 = AudioUnitGetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 1, &dstFormat, &size); + if (err1 != noErr) { + jack_error("Error calling AudioUnitGetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Output"); + printError(err1); + goto error; + } + PrintStreamDesc(&dstFormat); + + jack_log("Setup AUHAL output stream converter SR = %ld", samplerate); + dstFormat.mSampleRate = samplerate; + dstFormat.mFormatID = kAudioFormatLinearPCM; + dstFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kLinearPCMFormatFlagIsNonInterleaved; + dstFormat.mBytesPerPacket = sizeof(float); + dstFormat.mFramesPerPacket = 1; + dstFormat.mBytesPerFrame = sizeof(float); + dstFormat.mChannelsPerFrame = outchannels; + dstFormat.mBitsPerChannel = 32; + PrintStreamDesc(&dstFormat); + + err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &dstFormat, sizeof(AudioStreamBasicDescription)); + + if (err1 != noErr) { + jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Output"); + printError(err1); + goto error; + } } // Setup callbacks @@ -902,7 +957,7 @@ int JackCoreAudioAdapter::OpenAUHAL(bool capturing, if (err1 != noErr) { jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_SetRenderCallback 1"); printError(err1); - return -1; + goto error; } } else { AURenderCallbackStruct output; @@ -912,11 +967,15 @@ int JackCoreAudioAdapter::OpenAUHAL(bool capturing, if (err1 != noErr) { jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_SetRenderCallback 0"); printError(err1); - return -1; + goto error; } } return 0; + +error: + CloseAUHAL(); + return -1; } OSStatus JackCoreAudioAdapter::DestroyAggregateDevice() @@ -953,7 +1012,7 @@ static CFStringRef GetDeviceName(AudioDeviceID id) return (err == noErr) ? UIname : NULL; } -OSStatus JackCoreAudioAdapter::CreateAggregateDevice(AudioDeviceID captureDeviceID, AudioDeviceID playbackDeviceID, AudioDeviceID* outAggregateDevice) +OSStatus JackCoreAudioAdapter::CreateAggregateDevice(AudioDeviceID captureDeviceID, AudioDeviceID playbackDeviceID, jack_nframes_t samplerate, AudioDeviceID* outAggregateDevice) { OSStatus osErr = noErr; UInt32 outSize; @@ -964,6 +1023,16 @@ OSStatus JackCoreAudioAdapter::CreateAggregateDevice(AudioDeviceID captureDevice jack_error("JackCoreAudioAdapter::CreateAggregateDevice : cannot agregate devices that are already aggregate devices..."); return -1; } + + //--------------------------------------------------------------------------- + // Setup SR of both devices otherwise creating AD may fail... + //--------------------------------------------------------------------------- + if (SetupSampleRateAux(captureDeviceID, samplerate) < 0) { + jack_error("JackCoreAudioDriver::CreateAggregateDevice : cannot set SR of input device"); + } + if (SetupSampleRateAux(playbackDeviceID, samplerate) < 0) { + jack_error("JackCoreAudioDriver::CreateAggregateDevice : cannot set SR of output device"); + } //--------------------------------------------------------------------------- // Start to create a new aggregate by getting the base audio hardware plugin @@ -1190,25 +1259,25 @@ extern "C" strcpy(desc->params[i].name, "channels"); desc->params[i].character = 'c'; desc->params[i].type = JackDriverParamInt; - desc->params[i].value.ui = 0; + desc->params[i].value.ui = -1; strcpy(desc->params[i].short_desc, "Maximum number of channels"); - strcpy(desc->params[i].long_desc, desc->params[i].short_desc); + strcpy(desc->params[i].long_desc, "Maximum number of channels. If -1, max possible number of channels will be used"); i++; strcpy(desc->params[i].name, "inchannels"); desc->params[i].character = 'i'; desc->params[i].type = JackDriverParamInt; - desc->params[i].value.ui = 0; + desc->params[i].value.ui = -1; strcpy(desc->params[i].short_desc, "Maximum number of input channels"); - strcpy(desc->params[i].long_desc, desc->params[i].short_desc); + strcpy(desc->params[i].long_desc, "Maximum number of input channels. If -1, max possible number of input channels will be used"); i++; strcpy(desc->params[i].name, "outchannels"); desc->params[i].character = 'o'; desc->params[i].type = JackDriverParamInt; - desc->params[i].value.ui = 0; + desc->params[i].value.ui = -1; strcpy(desc->params[i].short_desc, "Maximum number of output channels"); - strcpy(desc->params[i].long_desc, desc->params[i].short_desc); + strcpy(desc->params[i].long_desc, "Maximum number of output channels. If -1, max possible number of output channels will be used"); i++; strcpy(desc->params[i].name, "capture"); diff --git a/macosx/coreaudio/JackCoreAudioAdapter.h b/macosx/coreaudio/JackCoreAudioAdapter.h index fa9978a3..d2f61006 100644 --- a/macosx/coreaudio/JackCoreAudioAdapter.h +++ b/macosx/coreaudio/JackCoreAudioAdapter.h @@ -36,6 +36,8 @@ typedef UInt8 CAAudioHardwareDeviceSectionID; #define kAudioDeviceSectionGlobal ((CAAudioHardwareDeviceSectionID)0x00) #define kAudioDeviceSectionWildcard ((CAAudioHardwareDeviceSectionID)0xFF) +#define WAIT_COUNTER 60 + /*! \brief Audio adapter using CoreAudio API. */ @@ -88,14 +90,15 @@ class JackCoreAudioAdapter : public JackAudioAdapterInterface OSStatus GetDeviceNameFromID(AudioDeviceID id, char* name); // Setup - OSStatus CreateAggregateDevice(AudioDeviceID captureDeviceID, AudioDeviceID playbackDeviceID, AudioDeviceID* outAggregateDevice); + OSStatus CreateAggregateDevice(AudioDeviceID captureDeviceID, AudioDeviceID playbackDeviceID, jack_nframes_t samplerate, AudioDeviceID* outAggregateDevice); OSStatus DestroyAggregateDevice(); bool IsAggregateDevice(AudioDeviceID device); int SetupDevices(const char* capture_driver_uid, const char* playback_driver_uid, char* capture_driver_name, - char* playback_driver_name); + char* playback_driver_name, + jack_nframes_t samplerate); int SetupChannels(bool capturing, bool playing, @@ -112,10 +115,12 @@ class JackCoreAudioAdapter : public JackAudioAdapterInterface int in_nChannels, int out_nChannels, jack_nframes_t buffer_size, - jack_nframes_t samplerate, - bool strict); + jack_nframes_t samplerate); - int SetupBufferSizeAndSampleRate(jack_nframes_t buffer_size, jack_nframes_t samplerate); + int SetupBufferSize(jack_nframes_t buffer_size); + int SetupSampleRate(jack_nframes_t samplerate); + int SetupSampleRateAux(AudioDeviceID inDevice, jack_nframes_t samplerate); + int SetupBuffers(int inchannels); void DisposeBuffers(); void CloseAUHAL(); diff --git a/macosx/coreaudio/JackCoreAudioDriver.cpp b/macosx/coreaudio/JackCoreAudioDriver.cpp index 69c16a0a..3b2620cb 100644 --- a/macosx/coreaudio/JackCoreAudioDriver.cpp +++ b/macosx/coreaudio/JackCoreAudioDriver.cpp @@ -44,6 +44,20 @@ static void Print4CharCode(const char* msg, long c) jack_log("%s'%s'", (msg), __4CC_string); } +static void PrintStreamDesc(AudioStreamBasicDescription *inDesc) +{ + jack_log("- - - - - - - - - - - - - - - - - - - -"); + jack_log(" Sample Rate:%f", inDesc->mSampleRate); + jack_log(" Format ID:%.*s", (int) sizeof(inDesc->mFormatID), (char*)&inDesc->mFormatID); + jack_log(" Format Flags:%lX", inDesc->mFormatFlags); + jack_log(" Bytes per Packet:%ld", inDesc->mBytesPerPacket); + jack_log(" Frames per Packet:%ld", inDesc->mFramesPerPacket); + jack_log(" Bytes per Frame:%ld", inDesc->mBytesPerFrame); + jack_log(" Channels per Frame:%ld", inDesc->mChannelsPerFrame); + jack_log(" Bits per Channel:%ld", inDesc->mBitsPerChannel); + jack_log("- - - - - - - - - - - - - - - - - - - -\n"); +} + static void printError(OSStatus err) { switch (err) { @@ -629,7 +643,11 @@ error: return -1; } -int JackCoreAudioDriver::SetupDevices(const char* capture_driver_uid, const char* playback_driver_uid, char* capture_driver_name, char* playback_driver_name, jack_nframes_t samplerate) +int JackCoreAudioDriver::SetupDevices(const char* capture_driver_uid, + const char* playback_driver_uid, + char* capture_driver_name, + char* playback_driver_name, + jack_nframes_t samplerate) { capture_driver_name[0] = 0; playback_driver_name[0] = 0; @@ -760,12 +778,12 @@ int JackCoreAudioDriver::SetupChannels(bool capturing, bool playing, int& inchan return -1; } - if (inchannels == 0) { + if (inchannels == -1) { jack_log("Setup max in channels = %d", in_nChannels); inchannels = in_nChannels; } - if (outchannels == 0) { + if (outchannels == -1) { jack_log("Setup max out channels = %d", out_nChannels); outchannels = out_nChannels; } @@ -839,7 +857,6 @@ int JackCoreAudioDriver::SetupSampleRateAux(AudioDeviceID inDevice, jack_nframes return 0; } - int JackCoreAudioDriver::OpenAUHAL(bool capturing, bool playing, int inchannels, @@ -847,12 +864,13 @@ int JackCoreAudioDriver::OpenAUHAL(bool capturing, int in_nChannels, int out_nChannels, jack_nframes_t buffer_size, - jack_nframes_t samplerate, - bool strict) + jack_nframes_t samplerate) { ComponentResult err1; UInt32 enableIO; AudioStreamBasicDescription srcFormat, dstFormat; + AudioDeviceID currAudioDeviceID; + UInt32 size; jack_log("OpenAUHAL capturing = %d playing = %d inchannels = %d outchannels = %d in_nChannels = %d out_nChannels = %d", capturing, playing, inchannels, outchannels, in_nChannels, out_nChannels); @@ -869,14 +887,14 @@ int JackCoreAudioDriver::OpenAUHAL(bool capturing, if (err1 != noErr) { jack_error("Error calling OpenAComponent"); printError(err1); - return -1; + goto error; } err1 = AudioUnitInitialize(fAUHAL); if (err1 != noErr) { jack_error("Cannot initialize AUHAL unit"); printError(err1); - return -1; + goto error; } // Start I/O @@ -892,8 +910,7 @@ int JackCoreAudioDriver::OpenAUHAL(bool capturing, if (err1 != noErr) { jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input"); printError(err1); - if (strict) - return -1; + goto error; } if (playing && outchannels > 0) { @@ -908,18 +925,15 @@ int JackCoreAudioDriver::OpenAUHAL(bool capturing, if (err1 != noErr) { jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_EnableIO,kAudioUnitScope_Output"); printError(err1); - if (strict) - return -1; + goto error; } - AudioDeviceID currAudioDeviceID; - UInt32 size = sizeof(AudioDeviceID); + size = sizeof(AudioDeviceID); err1 = AudioUnitGetProperty(fAUHAL, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &currAudioDeviceID, &size); if (err1 != noErr) { jack_error("Error calling AudioUnitGetProperty - kAudioOutputUnitProperty_CurrentDevice"); printError(err1); - if (strict) - return -1; + goto error; } else { jack_log("AudioUnitGetPropertyCurrentDevice = %d", currAudioDeviceID); } @@ -929,8 +943,7 @@ int JackCoreAudioDriver::OpenAUHAL(bool capturing, if (err1 != noErr) { jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_CurrentDevice"); printError(err1); - if (strict) - return -1; + goto error; } // Set buffer size @@ -939,8 +952,7 @@ int JackCoreAudioDriver::OpenAUHAL(bool capturing, if (err1 != noErr) { jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_MaximumFramesPerSlice"); printError(err1); - if (strict) - return -1; + goto error; } } @@ -949,8 +961,7 @@ int JackCoreAudioDriver::OpenAUHAL(bool capturing, if (err1 != noErr) { jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_MaximumFramesPerSlice"); printError(err1); - if (strict) - return -1; + goto error; } } @@ -967,6 +978,7 @@ int JackCoreAudioDriver::OpenAUHAL(bool capturing, if (err1 != noErr) { jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_ChannelMap 1"); printError(err1); + goto error; } } @@ -982,40 +994,71 @@ int JackCoreAudioDriver::OpenAUHAL(bool capturing, if (err1 != noErr) { jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_ChannelMap 0"); printError(err1); + goto error; } } // Setup stream converters - jack_log("Setup AUHAL input stream converter SR = %ld", samplerate); - 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(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &srcFormat, sizeof(AudioStreamBasicDescription)); - if (err1 != noErr) { - jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Input"); - printError(err1); + if (capturing && inchannels > 0) { + + size = sizeof(AudioStreamBasicDescription); + err1 = AudioUnitGetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 0, &srcFormat, &size); + if (err1 != noErr) { + jack_error("Error calling AudioUnitGetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Input"); + printError(err1); + goto error; + } + PrintStreamDesc(&srcFormat); + + jack_log("Setup AUHAL input stream converter SR = %ld", samplerate); + srcFormat.mSampleRate = samplerate; + srcFormat.mFormatID = kAudioFormatLinearPCM; + srcFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kLinearPCMFormatFlagIsNonInterleaved; + srcFormat.mBytesPerPacket = sizeof(float); + srcFormat.mFramesPerPacket = 1; + srcFormat.mBytesPerFrame = sizeof(float); + srcFormat.mChannelsPerFrame = inchannels; + srcFormat.mBitsPerChannel = 32; + PrintStreamDesc(&srcFormat); + + err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &srcFormat, sizeof(AudioStreamBasicDescription)); + + if (err1 != noErr) { + jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Input"); + printError(err1); + goto error; + } } - jack_log("Setup AUHAL output stream converter SR = %ld", samplerate); - 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(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &dstFormat, sizeof(AudioStreamBasicDescription)); - if (err1 != noErr) { - jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Output"); - printError(err1); + if (playing && outchannels > 0) { + + size = sizeof(AudioStreamBasicDescription); + err1 = AudioUnitGetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 1, &dstFormat, &size); + if (err1 != noErr) { + jack_error("Error calling AudioUnitGetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Output"); + printError(err1); + goto error; + } + PrintStreamDesc(&dstFormat); + + jack_log("Setup AUHAL output stream converter SR = %ld", samplerate); + dstFormat.mSampleRate = samplerate; + dstFormat.mFormatID = kAudioFormatLinearPCM; + dstFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kLinearPCMFormatFlagIsNonInterleaved; + dstFormat.mBytesPerPacket = sizeof(float); + dstFormat.mFramesPerPacket = 1; + dstFormat.mBytesPerFrame = sizeof(float); + dstFormat.mChannelsPerFrame = outchannels; + dstFormat.mBitsPerChannel = 32; + PrintStreamDesc(&dstFormat); + + err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &dstFormat, sizeof(AudioStreamBasicDescription)); + + if (err1 != noErr) { + jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Output"); + printError(err1); + goto error; + } } // Setup callbacks @@ -1027,7 +1070,7 @@ int JackCoreAudioDriver::OpenAUHAL(bool capturing, if (err1 != noErr) { jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_SetRenderCallback 1"); printError(err1); - return -1; + goto error; } } else { AURenderCallbackStruct output; @@ -1037,11 +1080,15 @@ int JackCoreAudioDriver::OpenAUHAL(bool capturing, if (err1 != noErr) { jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_SetRenderCallback 0"); printError(err1); - return -1; + goto error; } } return 0; + +error: + CloseAUHAL(); + return -1; } int JackCoreAudioDriver::SetupBuffers(int inchannels) @@ -1202,13 +1249,13 @@ int JackCoreAudioDriver::Open(jack_nframes_t buffer_size, if (SetupChannels(capturing, playing, inchannels, outchannels, in_nChannels, out_nChannels, true) < 0) goto error; - if (SetupBufferSize(buffer_size) < 0) + if (SetupBufferSize(buffer_size) < 0) goto error; if (SetupSampleRate(samplerate) < 0) goto error; - if (OpenAUHAL(capturing, playing, inchannels, outchannels, in_nChannels, out_nChannels, buffer_size, samplerate, true) < 0) + if (OpenAUHAL(capturing, playing, inchannels, outchannels, in_nChannels, out_nChannels, buffer_size, samplerate) < 0) goto error; if (capturing && inchannels > 0) @@ -1520,25 +1567,25 @@ extern "C" strcpy(desc->params[i].name, "channels"); desc->params[i].character = 'c'; desc->params[i].type = JackDriverParamInt; - desc->params[i].value.ui = 0; + desc->params[i].value.ui = -1; strcpy(desc->params[i].short_desc, "Maximum number of channels"); - strcpy(desc->params[i].long_desc, desc->params[i].short_desc); + strcpy(desc->params[i].long_desc, "Maximum number of channels. If -1, max possible number of channels will be used"); i++; strcpy(desc->params[i].name, "inchannels"); desc->params[i].character = 'i'; desc->params[i].type = JackDriverParamInt; - desc->params[i].value.ui = 0; + desc->params[i].value.ui = -1; strcpy(desc->params[i].short_desc, "Maximum number of input channels"); - strcpy(desc->params[i].long_desc, desc->params[i].short_desc); + strcpy(desc->params[i].long_desc, "Maximum number of input channels. If -1, max possible number of input channels will be used"); i++; strcpy(desc->params[i].name, "outchannels"); desc->params[i].character = 'o'; desc->params[i].type = JackDriverParamInt; - desc->params[i].value.ui = 0; + desc->params[i].value.ui = -1; strcpy(desc->params[i].short_desc, "Maximum number of output channels"); - strcpy(desc->params[i].long_desc, desc->params[i].short_desc); + strcpy(desc->params[i].long_desc, "Maximum number of output channels. If -1, max possible number of output channels will be used"); i++; strcpy(desc->params[i].name, "capture"); @@ -1651,10 +1698,10 @@ extern "C" { jack_nframes_t srate = 44100; jack_nframes_t frames_per_interrupt = 128; - int capture = FALSE; - int playback = FALSE; - int chan_in = 0; - int chan_out = 0; + bool capture = false; + bool playback = false; + int chan_in = -1; // Default: if not explicitely set, then max possible will be used... + int chan_out = -1; // Default: ifà not explicitely set, then max possible will be used... bool monitor = false; const char* capture_driver_uid = ""; const char* playback_driver_uid = ""; @@ -1677,31 +1724,31 @@ extern "C" break; case 'D': - capture = TRUE; - playback = TRUE; + capture = true; + playback = true; break; case 'c': - chan_in = chan_out = (int) param->value.ui; + chan_in = chan_out = (int)param->value.ui; break; case 'i': - chan_in = (int) param->value.ui; + chan_in = (int)param->value.ui; break; case 'o': - chan_out = (int) param->value.ui; + chan_out = (int)param->value.ui; break; case 'C': - capture = TRUE; + capture = true; if (strcmp(param->value.str, "none") != 0) { capture_driver_uid = strdup(param->value.str); } break; case 'P': - playback = TRUE; + playback = true; if (strcmp(param->value.str, "none") != 0) { playback_driver_uid = strdup(param->value.str); } @@ -1716,7 +1763,7 @@ extern "C" break; case 'p': - frames_per_interrupt = (unsigned int) param->value.ui; + frames_per_interrupt = (unsigned int)param->value.ui; break; case 'I': @@ -1747,8 +1794,8 @@ extern "C" /* duplex is the default */ if (!capture && !playback) { - capture = TRUE; - playback = TRUE; + capture = true; + playback = true; } Jack::JackCoreAudioDriver* driver = new Jack::JackCoreAudioDriver("system", "coreaudio", engine, table); diff --git a/macosx/coreaudio/JackCoreAudioDriver.h b/macosx/coreaudio/JackCoreAudioDriver.h index e0dedcbd..f3d909d2 100644 --- a/macosx/coreaudio/JackCoreAudioDriver.h +++ b/macosx/coreaudio/JackCoreAudioDriver.h @@ -151,8 +151,7 @@ class JackCoreAudioDriver : public JackAudioDriver int in_nChannels, int out_nChannels, jack_nframes_t nframes, - jack_nframes_t samplerate, - bool strict); + jack_nframes_t samplerate); void CloseAUHAL(); int AddListeners();