Browse Source

Merge remote branch 'remotes/orcz/netone-isolateion' into netone-isolateion

tags/v1.9.4
Torben Hohn 16 years ago
parent
commit
5ea3a4c9fa
7 changed files with 382 additions and 43 deletions
  1. +10
    -0
      ChangeLog
  2. +3
    -0
      common/JackClient.cpp
  3. +218
    -12
      macosx/coreaudio/JackCoreAudioAdapter.cpp
  4. +6
    -1
      macosx/coreaudio/JackCoreAudioAdapter.h
  5. +137
    -23
      macosx/coreaudio/JackCoreAudioDriver.cpp
  6. +8
    -3
      macosx/coreaudio/JackCoreAudioDriver.h
  7. +0
    -4
      posix/JackSocketServerChannel.cpp

+ 10
- 0
ChangeLog View File

@@ -25,9 +25,19 @@ Paul Davis
Jackdmp changes log
---------------------------

2009-10-27 Stephane Letz <letz@grame.fr>
* Dynamic system version detection in JackCoreAudioDriver to either create public or private aggregate device.

2009-10-26 Stephane Letz <letz@grame.fr>
* Implement "hog mode" (exclusive access of the audio device) in JackCoreAudioDriver.
* Fix jack_set_sample_rate_callback to have he same behavior as in JACK1.

2009-10-25 Stephane Letz <letz@grame.fr>
* Improve aggregate device management in JackCoreAudioDriver : now a "private" device only and cleanup properly.
* Aggregate device code added to JackCoreAudioAdapter.

2009-10-23 Stephane Letz <letz@grame.fr>


+ 3
- 0
common/JackClient.cpp View File

@@ -874,6 +874,9 @@ int JackClient::SetSampleRateCallback(JackSampleRateCallback callback, void *arg
GetClientControl()->fCallback[kSampleRateCallback] = (callback != NULL);
fSampleRateArg = arg;
fSampleRate = callback;
// Now invoke it
if (callback)
callback(GetEngineControl()->fSampleRate, arg);
return 0;
}
}


+ 218
- 12
macosx/coreaudio/JackCoreAudioAdapter.cpp View File

@@ -396,7 +396,7 @@ OSStatus JackCoreAudioAdapter::GetDefaultDevice(AudioDeviceID* id)

jack_log("GetDefaultDevice: input = %ld output = %ld", inDefault, outDefault);

// Get the device only if default input and ouput are the same
// Get the device only if default input and output are the same
if (inDefault == outDefault) {
*id = inDefault;
return noErr;
@@ -491,19 +491,35 @@ int JackCoreAudioAdapter::SetupDevices(const char* capture_driver_uid,

// Duplex
if (strcmp(capture_driver_uid, "") != 0 && strcmp(playback_driver_uid, "") != 0) {
jack_log("JackCoreAudioAdapter::Open duplex");
if (GetDeviceIDFromUID(playback_driver_uid, &fDeviceID) != noErr) {
if (GetDefaultDevice(&fDeviceID) != noErr) {
jack_error("Cannot open default device");
// Same device for capture and playback...
if (strcmp(capture_driver_uid, playback_driver_uid) == 0) {
if (GetDeviceIDFromUID(playback_driver_uid, &fDeviceID) != noErr) {
jack_log("Will take default in/out");
if (GetDefaultDevice(&fDeviceID) != noErr) {
jack_error("Cannot open default device");
return -1;
}
}
if (GetDeviceNameFromID(fDeviceID, capture_driver_name) != noErr || GetDeviceNameFromID(fDeviceID, playback_driver_name) != noErr) {
jack_error("Cannot get device name from device ID");
return -1;
}
}
if (GetDeviceNameFromID(fDeviceID, capture_driver_name) != noErr || GetDeviceNameFromID(fDeviceID, playback_driver_name) != noErr) {
jack_error("Cannot get device name from device ID");
return -1;
} else {
// Creates aggregate device
AudioDeviceID captureID, playbackID;
if (GetDeviceIDFromUID(capture_driver_uid, &captureID) != noErr)
return -1;
if (GetDeviceIDFromUID(playback_driver_uid, &playbackID) != noErr)
return -1;
if (CreateAggregateDevice(captureID, playbackID, &fDeviceID) != noErr)
return -1;
}

// Capture only
// Capture only
} else if (strcmp(capture_driver_uid, "") != 0) {
jack_log("JackCoreAudioAdapter::Open capture only");
if (GetDeviceIDFromUID(capture_driver_uid, &fDeviceID) != noErr) {
@@ -517,7 +533,7 @@ int JackCoreAudioAdapter::SetupDevices(const char* capture_driver_uid,
return -1;
}

// Playback only
// Playback only
} else if (strcmp(playback_driver_uid, "") != 0) {
jack_log("JackCoreAudioAdapter::Open playback only");
if (GetDeviceIDFromUID(playback_driver_uid, &fDeviceID) != noErr) {
@@ -531,7 +547,7 @@ int JackCoreAudioAdapter::SetupDevices(const char* capture_driver_uid,
return -1;
}

// Use default driver in duplex mode
// Use default driver in duplex mode
} else {
jack_log("JackCoreAudioAdapter::Open default driver");
if (GetDefaultDevice(&fDeviceID) != noErr) {
@@ -903,6 +919,194 @@ int JackCoreAudioAdapter::OpenAUHAL(bool capturing,
return 0;
}

OSStatus JackCoreAudioAdapter::DestroyAggregateDevice()
{
OSStatus osErr = noErr;
AudioObjectPropertyAddress pluginAOPA;
pluginAOPA.mSelector = kAudioPlugInDestroyAggregateDevice;
pluginAOPA.mScope = kAudioObjectPropertyScopeGlobal;
pluginAOPA.mElement = kAudioObjectPropertyElementMaster;
UInt32 outDataSize;
osErr = AudioObjectGetPropertyDataSize(fPluginID, &pluginAOPA, 0, NULL, &outDataSize);
if (osErr != noErr) {
jack_error("JackCoreAudioDriver::DestroyAggregateDevice : AudioObjectGetPropertyDataSize error");
printError(osErr);
return osErr;
}
osErr = AudioObjectGetPropertyData(fPluginID, &pluginAOPA, 0, NULL, &outDataSize, &fDeviceID);
if (osErr != noErr) {
jack_error("JackCoreAudioDriver::DestroyAggregateDevice : AudioObjectGetPropertyData error");
printError(osErr);
return osErr;
}
return noErr;
}

static CFStringRef GetDeviceName(AudioDeviceID id)
{
UInt32 size = sizeof(CFStringRef);
CFStringRef UIname;
OSStatus err = AudioDeviceGetProperty(id, 0, false, kAudioDevicePropertyDeviceUID, &size, &UIname);
return (err == noErr) ? UIname : NULL;
}

OSStatus JackCoreAudioAdapter::CreateAggregateDevice(AudioDeviceID captureDeviceID, AudioDeviceID playbackDeviceID, AudioDeviceID* outAggregateDevice)
{
OSStatus osErr = noErr;
UInt32 outSize;
Boolean outWritable;

//---------------------------------------------------------------------------
// Start to create a new aggregate by getting the base audio hardware plugin
//---------------------------------------------------------------------------
char capture_name[256];
char playback_name[256];
GetDeviceNameFromID(captureDeviceID, capture_name);
GetDeviceNameFromID(playbackDeviceID, playback_name);
jack_info("Separated input = '%s' and output = '%s' devices, create a private aggregate device to handle them...", capture_name, playback_name);
osErr = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyPlugInForBundleID, &outSize, &outWritable);
if (osErr != noErr)
return osErr;

AudioValueTranslation pluginAVT;

CFStringRef inBundleRef = CFSTR("com.apple.audio.CoreAudio");
pluginAVT.mInputData = &inBundleRef;
pluginAVT.mInputDataSize = sizeof(inBundleRef);
pluginAVT.mOutputData = &fPluginID;
pluginAVT.mOutputDataSize = sizeof(fPluginID);

osErr = AudioHardwareGetProperty(kAudioHardwarePropertyPlugInForBundleID, &outSize, &pluginAVT);
if (osErr != noErr)
return osErr;

//-------------------------------------------------
// Create a CFDictionary for our aggregate device
//-------------------------------------------------

CFMutableDictionaryRef aggDeviceDict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);

CFStringRef AggregateDeviceNameRef = CFSTR("JackDuplex");
CFStringRef AggregateDeviceUIDRef = CFSTR("com.grame.JackDuplex");
// add the name of the device to the dictionary
CFDictionaryAddValue(aggDeviceDict, CFSTR(kAudioAggregateDeviceNameKey), AggregateDeviceNameRef);

// add our choice of UID for the aggregate device to the dictionary
CFDictionaryAddValue(aggDeviceDict, CFSTR(kAudioAggregateDeviceUIDKey), AggregateDeviceUIDRef);
// add a "private aggregate key" to the dictionary
int value = 1;
CFNumberRef AggregateDeviceNumberRef = CFNumberCreate(NULL, kCFNumberIntType, &value);
SInt32 system;
Gestalt(gestaltSystemVersion, &system);
jack_log("JackCoreAudioDriver::CreateAggregateDevice : system version = %x limit = %x", system, 0x00001054);
// Starting with 10.5.4 systems, the AD can be internal... (better)
if (system < 0x00001054) {
jack_log("JackCoreAudioDriver::CreateAggregateDevice : public aggregate device....");
} else {
jack_log("JackCoreAudioDriver::CreateAggregateDevice : private aggregate device....");
CFDictionaryAddValue(aggDeviceDict, CFSTR(kAudioAggregateDeviceIsPrivateKey), AggregateDeviceNumberRef);
}
//-------------------------------------------------
// Create a CFMutableArray for our sub-device list
//-------------------------------------------------
CFStringRef captureDeviceUID = GetDeviceName(captureDeviceID);
CFStringRef playbackDeviceUID = GetDeviceName(playbackDeviceID);
if (captureDeviceUID == NULL || playbackDeviceUID == NULL)
return -1;
// we need to append the UID for each device to a CFMutableArray, so create one here
CFMutableArrayRef subDevicesArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);

// two sub-devices in this example, so append the sub-device's UID to the CFArray
CFArrayAppendValue(subDevicesArray, captureDeviceUID);
CFArrayAppendValue(subDevicesArray, playbackDeviceUID);

//-----------------------------------------------------------------------
// Feed the dictionary to the plugin, to create a blank aggregate device
//-----------------------------------------------------------------------
AudioObjectPropertyAddress pluginAOPA;
pluginAOPA.mSelector = kAudioPlugInCreateAggregateDevice;
pluginAOPA.mScope = kAudioObjectPropertyScopeGlobal;
pluginAOPA.mElement = kAudioObjectPropertyElementMaster;
UInt32 outDataSize;

osErr = AudioObjectGetPropertyDataSize(fPluginID, &pluginAOPA, 0, NULL, &outDataSize);
if (osErr != noErr)
return osErr;

osErr = AudioObjectGetPropertyData(fPluginID, &pluginAOPA, sizeof(aggDeviceDict), &aggDeviceDict, &outDataSize, outAggregateDevice);
if (osErr != noErr)
return osErr;

// pause for a bit to make sure that everything completed correctly
// this is to work around a bug in the HAL where a new aggregate device seems to disappear briefly after it is created
CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, false);

//-------------------------
// Set the sub-device list
//-------------------------

pluginAOPA.mSelector = kAudioAggregateDevicePropertyFullSubDeviceList;
pluginAOPA.mScope = kAudioObjectPropertyScopeGlobal;
pluginAOPA.mElement = kAudioObjectPropertyElementMaster;
outDataSize = sizeof(CFMutableArrayRef);
osErr = AudioObjectSetPropertyData(*outAggregateDevice, &pluginAOPA, 0, NULL, outDataSize, &subDevicesArray);
if (osErr != noErr)
return osErr;

// pause again to give the changes time to take effect
CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, false);

//-----------------------
// Set the master device
//-----------------------

// set the master device manually (this is the device which will act as the master clock for the aggregate device)
// pass in the UID of the device you want to use
pluginAOPA.mSelector = kAudioAggregateDevicePropertyMasterSubDevice;
pluginAOPA.mScope = kAudioObjectPropertyScopeGlobal;
pluginAOPA.mElement = kAudioObjectPropertyElementMaster;
outDataSize = sizeof(CFStringRef);
osErr = AudioObjectSetPropertyData(*outAggregateDevice, &pluginAOPA, 0, NULL, outDataSize, &captureDeviceUID); // capture is master...
if (osErr != noErr)
return osErr;

// pause again to give the changes time to take effect
CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, false);

//----------
// Clean up
//----------
CFRelease(AggregateDeviceNumberRef);

// release the CF objects we have created - we don't need them any more
CFRelease(aggDeviceDict);
CFRelease(subDevicesArray);

// release the device UID
CFRelease(captureDeviceUID);
CFRelease(playbackDeviceUID);
jack_log("New aggregate device %ld", *outAggregateDevice);
return noErr;
}

void JackCoreAudioAdapter::CloseAUHAL()
{
AudioUnitUninitialize(fAUHAL);
@@ -923,6 +1127,8 @@ int JackCoreAudioAdapter::Close()
DisposeBuffers();
CloseAUHAL();
RemoveListeners();
if (fPluginID > 0)
DestroyAggregateDevice();
return 0;
}



+ 6
- 1
macosx/coreaudio/JackCoreAudioAdapter.h View File

@@ -54,7 +54,9 @@ class JackCoreAudioAdapter : public JackAudioAdapterInterface
bool fCapturing;
bool fPlaying;

AudioDeviceID fDeviceID;
AudioDeviceID fDeviceID; // Used "duplex" device
AudioObjectID fPluginID; // Used for aggregate device

bool fState;

AudioUnitRenderActionFlags* fActionFags;
@@ -86,6 +88,9 @@ class JackCoreAudioAdapter : public JackAudioAdapterInterface
OSStatus GetDeviceNameFromID(AudioDeviceID id, char* name);

// Setup
OSStatus CreateAggregateDevice(AudioDeviceID captureDeviceID, AudioDeviceID playbackDeviceID, AudioDeviceID* outAggregateDevice);
OSStatus DestroyAggregateDevice();
int SetupDevices(const char* capture_driver_uid,
const char* playback_driver_uid,
char* capture_driver_name,


+ 137
- 23
macosx/coreaudio/JackCoreAudioDriver.cpp View File

@@ -321,7 +321,7 @@ OSStatus JackCoreAudioDriver::GetDefaultDevice(AudioDeviceID* id)

jack_log("GetDefaultDevice: input = %ld output = %ld", inDefault, outDefault);

// Get the device only if default input and ouput are the same
// Get the device only if default input and output are the same
if (inDefault == outDefault) {
*id = inDefault;
return noErr;
@@ -390,7 +390,14 @@ OSStatus JackCoreAudioDriver::GetTotalChannels(AudioDeviceID device, int& channe
}

JackCoreAudioDriver::JackCoreAudioDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table)
: JackAudioDriver(name, alias, engine, table), fJackInputData(NULL), fDriverOutputData(NULL), fPluginID(0), fState(false), fIOUsage(1.f),fComputationGrain(-1.f)
: JackAudioDriver(name, alias, engine, table),
fJackInputData(NULL),
fDriverOutputData(NULL),
fPluginID(0),
fState(false),
fHogged(false),
fIOUsage(1.f),
fComputationGrain(-1.f)
{}

JackCoreAudioDriver::~JackCoreAudioDriver()
@@ -431,10 +438,19 @@ OSStatus JackCoreAudioDriver::CreateAggregateDevice(AudioDeviceID captureDeviceI
//---------------------------------------------------------------------------
// Start to create a new aggregate by getting the base audio hardware plugin
//---------------------------------------------------------------------------
char capture_name[256];
char playback_name[256];
GetDeviceNameFromID(captureDeviceID, capture_name);
GetDeviceNameFromID(playbackDeviceID, playback_name);
jack_info("Separated input = '%s' and output = '%s' devices, create a private aggregate device to handle them...", capture_name, playback_name);
osErr = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyPlugInForBundleID, &outSize, &outWritable);
if (osErr != noErr)
if (osErr != noErr) {
jack_error("JackCoreAudioDriver::CreateAggregateDevice : AudioHardwareGetPropertyInfo kAudioHardwarePropertyPlugInForBundleID error");
printError(osErr);
return osErr;
}

AudioValueTranslation pluginAVT;

@@ -446,8 +462,11 @@ OSStatus JackCoreAudioDriver::CreateAggregateDevice(AudioDeviceID captureDeviceI
pluginAVT.mOutputDataSize = sizeof(fPluginID);

osErr = AudioHardwareGetProperty(kAudioHardwarePropertyPlugInForBundleID, &outSize, &pluginAVT);
if (osErr != noErr)
if (osErr != noErr) {
jack_error("JackCoreAudioDriver::CreateAggregateDevice : AudioHardwareGetProperty kAudioHardwarePropertyPlugInForBundleID error");
printError(osErr);
return osErr;
}

//-------------------------------------------------
// Create a CFDictionary for our aggregate device
@@ -467,7 +486,19 @@ OSStatus JackCoreAudioDriver::CreateAggregateDevice(AudioDeviceID captureDeviceI
// add a "private aggregate key" to the dictionary
int value = 1;
CFNumberRef AggregateDeviceNumberRef = CFNumberCreate(NULL, kCFNumberIntType, &value);
CFDictionaryAddValue(aggDeviceDict, CFSTR(kAudioAggregateDeviceIsPrivateKey), AggregateDeviceNumberRef);
SInt32 system;
Gestalt(gestaltSystemVersion, &system);
jack_log("JackCoreAudioDriver::CreateAggregateDevice : system version = %x limit = %x", system, 0x00001054);
// Starting with 10.5.4 systems, the AD can be internal... (better)
if (system < 0x00001054) {
jack_log("JackCoreAudioDriver::CreateAggregateDevice : public aggregate device....");
} else {
jack_log("JackCoreAudioDriver::CreateAggregateDevice : private aggregate device....");
CFDictionaryAddValue(aggDeviceDict, CFSTR(kAudioAggregateDeviceIsPrivateKey), AggregateDeviceNumberRef);
}
//-------------------------------------------------
// Create a CFMutableArray for our sub-device list
@@ -497,12 +528,18 @@ OSStatus JackCoreAudioDriver::CreateAggregateDevice(AudioDeviceID captureDeviceI
UInt32 outDataSize;

osErr = AudioObjectGetPropertyDataSize(fPluginID, &pluginAOPA, 0, NULL, &outDataSize);
if (osErr != noErr)
if (osErr != noErr) {
jack_error("JackCoreAudioDriver::CreateAggregateDevice : AudioObjectGetPropertyDataSize error");
printError(osErr);
return osErr;

}
osErr = AudioObjectGetPropertyData(fPluginID, &pluginAOPA, sizeof(aggDeviceDict), &aggDeviceDict, &outDataSize, outAggregateDevice);
if (osErr != noErr)
if (osErr != noErr) {
jack_error("JackCoreAudioDriver::CreateAggregateDevice : AudioObjectGetPropertyData error");
printError(osErr);
return osErr;
}

// pause for a bit to make sure that everything completed correctly
// this is to work around a bug in the HAL where a new aggregate device seems to disappear briefly after it is created
@@ -517,9 +554,12 @@ OSStatus JackCoreAudioDriver::CreateAggregateDevice(AudioDeviceID captureDeviceI
pluginAOPA.mElement = kAudioObjectPropertyElementMaster;
outDataSize = sizeof(CFMutableArrayRef);
osErr = AudioObjectSetPropertyData(*outAggregateDevice, &pluginAOPA, 0, NULL, outDataSize, &subDevicesArray);
if (osErr != noErr)
if (osErr != noErr) {
jack_error("JackCoreAudioDriver::CreateAggregateDevice : AudioObjectSetPropertyData for sub-device list error");
printError(osErr);
return osErr;

}
// pause again to give the changes time to take effect
CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, false);

@@ -534,9 +574,12 @@ OSStatus JackCoreAudioDriver::CreateAggregateDevice(AudioDeviceID captureDeviceI
pluginAOPA.mElement = kAudioObjectPropertyElementMaster;
outDataSize = sizeof(CFStringRef);
osErr = AudioObjectSetPropertyData(*outAggregateDevice, &pluginAOPA, 0, NULL, outDataSize, &captureDeviceUID); // capture is master...
if (osErr != noErr)
if (osErr != noErr) {
jack_error("JackCoreAudioDriver::CreateAggregateDevice : AudioObjectSetPropertyData for master device error");
printError(osErr);
return osErr;

}
// pause again to give the changes time to take effect
CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, false);

@@ -544,6 +587,7 @@ OSStatus JackCoreAudioDriver::CreateAggregateDevice(AudioDeviceID captureDeviceI
// Clean up
//----------
// release the private AD key
CFRelease(AggregateDeviceNumberRef);

// release the CF objects we have created - we don't need them any more
@@ -584,7 +628,7 @@ int JackCoreAudioDriver::SetupDevices(const char* capture_driver_uid, const char
} else {
// Creates agregate device
// Creates aggregate device
AudioDeviceID captureID, playbackID;
if (GetDeviceIDFromUID(capture_driver_uid, &captureID) != noErr)
return -1;
@@ -594,7 +638,7 @@ int JackCoreAudioDriver::SetupDevices(const char* capture_driver_uid, const char
return -1;
}

// Capture only
// Capture only
} else if (strcmp(capture_driver_uid, "") != 0) {
jack_log("JackCoreAudioDriver::Open capture only");
if (GetDeviceIDFromUID(capture_driver_uid, &fDeviceID) != noErr) {
@@ -609,7 +653,7 @@ int JackCoreAudioDriver::SetupDevices(const char* capture_driver_uid, const char
return -1;
}

// Playback only
// Playback only
} else if (strcmp(playback_driver_uid, "") != 0) {
jack_log("JackCoreAudioDriver::Open playback only");
if (GetDeviceIDFromUID(playback_driver_uid, &fDeviceID) != noErr) {
@@ -624,7 +668,7 @@ int JackCoreAudioDriver::SetupDevices(const char* capture_driver_uid, const char
return -1;
}

// Use default driver in duplex mode
// Use default driver in duplex mode
} else {
jack_log("JackCoreAudioDriver::Open default driver");
if (GetDefaultDevice(&fDeviceID) != noErr) {
@@ -636,6 +680,14 @@ int JackCoreAudioDriver::SetupDevices(const char* capture_driver_uid, const char
return -1;
}
}
if (fHogged) {
if (TakeHog()) {
jack_info("Device = %ld has been hogged", fDeviceID);
} else {
jack_error("Cannot hog device = %ld", fDeviceID);
}
}

return 0;
}
@@ -1065,7 +1117,8 @@ int JackCoreAudioDriver::Open(jack_nframes_t buffer_size,
jack_nframes_t capture_latency,
jack_nframes_t playback_latency,
int async_output_latency,
int computation_grain)
int computation_grain,
bool hogged)
{
int in_nChannels = 0;
int out_nChannels = 0;
@@ -1084,14 +1137,15 @@ int JackCoreAudioDriver::Open(jack_nframes_t buffer_size,
fPlaybackLatency = playback_latency;
fIOUsage = float(async_output_latency) / 100.f;
fComputationGrain = float(computation_grain) / 100.f;
fHogged = hogged;
SInt32 major;
SInt32 minor;
Gestalt(gestaltSystemVersionMajor, &major);
Gestalt(gestaltSystemVersionMinor, &minor);
// Starting with 10.6 systems...
if (major == 10 && minor >=6) {
// 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);
@@ -1328,6 +1382,53 @@ int JackCoreAudioDriver::SetBufferSize(jack_nframes_t buffer_size)
return 0;
}

bool JackCoreAudioDriver::TakeHogAux(AudioDeviceID deviceID, bool isInput)
{
pid_t hog_pid;
OSStatus err;

UInt32 propSize = sizeof(hog_pid);
err = AudioDeviceGetProperty(deviceID, 0, isInput, kAudioDevicePropertyHogMode, &propSize, &hog_pid);
if (err) {
jack_error("Cannot read hog state...");
printError(err);
}

if (hog_pid != getpid()) {
hog_pid = getpid();
err = AudioDeviceSetProperty(deviceID, 0, 0, isInput, kAudioDevicePropertyHogMode, propSize, &hog_pid);
if (err != noErr) {
jack_error("Can't hog device = %d because it's being hogged by another program", deviceID);
return false;
}
}
return true;
}
bool JackCoreAudioDriver::TakeHog()
{
OSStatus err = noErr;
AudioObjectID sub_device[32];
UInt32 outSize = sizeof(sub_device);
err = AudioDeviceGetProperty(fDeviceID, 0, kAudioDeviceSectionGlobal, kAudioAggregateDevicePropertyActiveSubDeviceList, &outSize, sub_device);
if (err != noErr) {
jack_log("Device does not have subdevices");
return TakeHogAux(fDeviceID, true);
} else {
int num_devices = outSize / sizeof(AudioObjectID);
jack_log("Device does has %d subdevices", num_devices);
for (int i = 0; i < num_devices; i++) {
if (!TakeHogAux(sub_device[i], true)) {
return false;
}
}
return true;
}
}

} // end of namespace


@@ -1345,7 +1446,7 @@ extern "C"
strcpy(desc->name, "coreaudio"); // size MUST be less then JACK_DRIVER_NAME_MAX + 1
strcpy(desc->desc, "Apple CoreAudio API based audio backend"); // size MUST be less then JACK_DRIVER_PARAM_DESC + 1
desc->nparams = 15;
desc->nparams = 16;
desc->params = (jack_driver_param_desc_t*)calloc(desc->nparams, sizeof(jack_driver_param_desc_t));

i = 0;
@@ -1448,16 +1549,24 @@ extern "C"
strcpy(desc->params[i].name, "list-devices");
desc->params[i].character = 'l';
desc->params[i].type = JackDriverParamBool;
desc->params[i].value.i = TRUE;
desc->params[i].value.i = FALSE;
strcpy(desc->params[i].short_desc, "Display available CoreAudio devices");
strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
i++;
strcpy(desc->params[i].name, "hog");
desc->params[i].character = 'H';
desc->params[i].type = JackDriverParamBool;
desc->params[i].value.i = FALSE;
strcpy(desc->params[i].short_desc, "Take exclusive access of the audio device");
strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
i++;
strcpy(desc->params[i].name, "async-latency");
desc->params[i].character = 'L';
desc->params[i].type = JackDriverParamUInt;
desc->params[i].value.i = 100;
strcpy(desc->params[i].short_desc, "Extra output latency in aynchronous mode (percent)");
strcpy(desc->params[i].short_desc, "Extra output latency in asynchronous mode (percent)");
strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
i++;
@@ -1488,6 +1597,7 @@ extern "C"
jack_nframes_t systemic_output_latency = 0;
int async_output_latency = 100;
int computation_grain = -1;
bool hogged = false;
for (node = params; node; node = jack_slist_next(node)) {
param = (const jack_driver_param_t *) node->data;
@@ -1554,6 +1664,10 @@ extern "C"
Jack::DisplayDeviceNames();
break;
case 'H':
hogged = true;
break;
case 'L':
async_output_latency = param->value.ui;
break;
@@ -1572,7 +1686,7 @@ extern "C"

Jack::JackCoreAudioDriver* driver = new Jack::JackCoreAudioDriver("system", "coreaudio", engine, table);
if (driver->Open(frames_per_interrupt, srate, capture, playback, chan_in, chan_out, monitor, capture_driver_uid,
playback_driver_uid, systemic_input_latency, systemic_output_latency, async_output_latency, computation_grain) == 0) {
playback_driver_uid, systemic_input_latency, systemic_output_latency, async_output_latency, computation_grain, hogged) == 0) {
return driver;
} else {
delete driver;


+ 8
- 3
macosx/coreaudio/JackCoreAudioDriver.h View File

@@ -53,13 +53,14 @@ class JackCoreAudioDriver : public JackAudioDriver
AudioBufferList* fJackInputData;
AudioBufferList* fDriverOutputData;

AudioDeviceID fDeviceID;
AudioObjectID fPluginID;
AudioDeviceID fDeviceID; // Used "duplex" device
AudioObjectID fPluginID; // Used for aggregate device

AudioUnitRenderActionFlags* fActionFags;
AudioTimeStamp* fCurrentTime;

bool fState;
bool fHogged;

// Initial state
bool fCapturing;
@@ -150,6 +151,9 @@ class JackCoreAudioDriver : public JackAudioDriver

int AddListeners();
void RemoveListeners();
bool TakeHogAux(AudioDeviceID deviceID, bool isInput);
bool TakeHog();

public:

@@ -168,7 +172,8 @@ class JackCoreAudioDriver : public JackAudioDriver
jack_nframes_t capture_latency,
jack_nframes_t playback_latency,
int async_output_latency,
int computation_grain);
int computation_grain,
bool hogged);
int Close();

int Attach();


+ 0
- 4
posix/JackSocketServerChannel.cpp View File

@@ -60,10 +60,6 @@ int JackSocketServerChannel::Open(const char* server_name, JackServer* server)
BuildPoolTable();
fServer = server;
return 0;

error:
fRequestListenSocket.Close();
return -1;
}

void JackSocketServerChannel::Close()


Loading…
Cancel
Save