Browse Source

kAudioHardwarePropertyDevices property management in CoreAudio compoments (in progress).

git-svn-id: http://subversion.jackaudio.org/jack/jack2/trunk/jackmp@4641 0c269be4-1314-0410-8aa9-9f06e86f4224
tags/1.9.8
sletz 13 years ago
parent
commit
77053812a3
4 changed files with 209 additions and 14 deletions
  1. +19
    -3
      macosx/coreaudio/JackCoreAudioAdapter.cpp
  2. +2
    -0
      macosx/coreaudio/JackCoreAudioAdapter.h
  3. +182
    -8
      macosx/coreaudio/JackCoreAudioDriver.cpp
  4. +6
    -3
      macosx/coreaudio/JackCoreAudioDriver.h

+ 19
- 3
macosx/coreaudio/JackCoreAudioAdapter.cpp View File

@@ -161,6 +161,22 @@ static void printError(OSStatus err)
} }
} }


OSStatus JackCoreAudioAdapter::AudioHardwareNotificationCallback(AudioHardwarePropertyID inPropertyID, void* inClientData)
{
JackCoreAudioAdapter* driver = (JackCoreAudioAdapter*)inClientData;

switch (inPropertyID) {

case kAudioHardwarePropertyDevices: {
jack_log("JackCoreAudioAdapter::AudioHardwareNotificationCallback kAudioHardwarePropertyDevices");
DisplayDeviceNames();
break;
}
}

return noErr;
}

OSStatus JackCoreAudioAdapter::SRNotificationCallback(AudioDeviceID inDevice, OSStatus JackCoreAudioAdapter::SRNotificationCallback(AudioDeviceID inDevice,
UInt32 inChannel, UInt32 inChannel,
Boolean isInput, Boolean isInput,
@@ -222,9 +238,9 @@ int JackCoreAudioAdapter::AddListeners()
return -1; return -1;
} }


err = AudioDeviceAddPropertyListener(fDeviceID, 0, true, kAudioHardwarePropertyDevices, DeviceNotificationCallback, this);
err = AudioHardwareAddPropertyListener(kAudioHardwarePropertyDevices, AudioHardwareNotificationCallback, this);
if (err != noErr) { if (err != noErr) {
jack_error("Error calling AudioDeviceAddPropertyListener with kAudioHardwarePropertyDevices");
jack_error("Error calling AudioHardwareAddPropertyListener with kAudioHardwarePropertyDevices");
printError(err); printError(err);
return -1; return -1;
} }
@@ -263,7 +279,7 @@ int JackCoreAudioAdapter::AddListeners()
void JackCoreAudioAdapter::RemoveListeners() void JackCoreAudioAdapter::RemoveListeners()
{ {
AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioDeviceProcessorOverload, DeviceNotificationCallback); AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioDeviceProcessorOverload, DeviceNotificationCallback);
AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioHardwarePropertyDevices, DeviceNotificationCallback);
AudioHardwareRemovePropertyListener(kAudioHardwarePropertyDevices, AudioHardwareNotificationCallback);
AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioDevicePropertyNominalSampleRate, DeviceNotificationCallback); AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioDevicePropertyNominalSampleRate, DeviceNotificationCallback);
AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioDevicePropertyDeviceIsRunning, DeviceNotificationCallback); AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioDevicePropertyDeviceIsRunning, DeviceNotificationCallback);
AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioDevicePropertyStreamConfiguration, DeviceNotificationCallback); AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioDevicePropertyStreamConfiguration, DeviceNotificationCallback);


+ 2
- 0
macosx/coreaudio/JackCoreAudioAdapter.h View File

@@ -79,6 +79,8 @@ class JackCoreAudioAdapter : public JackAudioAdapterInterface
UInt32 inNumberFrames, UInt32 inNumberFrames,
AudioBufferList *ioData); AudioBufferList *ioData);


static OSStatus AudioHardwareNotificationCallback(AudioHardwarePropertyID inPropertyID,void* inClientData);

static OSStatus SRNotificationCallback(AudioDeviceID inDevice, static OSStatus SRNotificationCallback(AudioDeviceID inDevice,
UInt32 inChannel, UInt32 inChannel,
Boolean isInput, Boolean isInput,


+ 182
- 8
macosx/coreaudio/JackCoreAudioDriver.cpp View File

@@ -129,6 +129,76 @@ static void printError(OSStatus err)
} }
} }


static bool CheckAvailableDeviceName(const char* device_name, AudioDeviceID* device_id)
{
UInt32 size;
Boolean isWritable;
int i, deviceNum;
OSStatus err;

err = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices, &size, &isWritable);
if (err != noErr) {
return false;
}

deviceNum = size / sizeof(AudioDeviceID);
AudioDeviceID devices[deviceNum];

err = AudioHardwareGetProperty(kAudioHardwarePropertyDevices, &size, devices);
if (err != noErr) {
return false;
}

for (i = 0; i < deviceNum; i++) {
char device_name_aux[256];

size = 256;
err = AudioDeviceGetProperty(devices[i], 0, false, kAudioDevicePropertyDeviceName, &size, device_name_aux);
if (err != noErr) {
return false;
}

if (strcmp(device_name_aux, device_name) == 0) {
*device_id = devices[i];
return true;
}

}

return false;
}

static bool CheckAvailableDevice(AudioDeviceID device_id)
{
UInt32 size;
Boolean isWritable;
int i, deviceNum;
OSStatus err;

err = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices, &size, &isWritable);
if (err != noErr) {
return false;
}

deviceNum = size / sizeof(AudioDeviceID);
AudioDeviceID devices[deviceNum];

err = AudioHardwareGetProperty(kAudioHardwarePropertyDevices, &size, devices);
if (err != noErr) {
return false;
}

for (i = 0; i < deviceNum; i++) {
if (device_id == devices[i]) {
return true;
}

}

return false;
}


static OSStatus DisplayDeviceNames() static OSStatus DisplayDeviceNames()
{ {
UInt32 size; UInt32 size;
@@ -169,7 +239,7 @@ static OSStatus DisplayDeviceNames()
return err; return err;
} }


jack_info("Device name = \'%s\', internal name = \'%s\' (to be used as -C, -P, or -d parameter)", device_name, internal_name);
jack_info("Device ID = \'%d\' name = \'%s\', internal name = \'%s\' (to be used as -C, -P, or -d parameter)", devices[i], device_name, internal_name);
} }


return noErr; return noErr;
@@ -330,6 +400,72 @@ OSStatus JackCoreAudioDriver::BSNotificationCallback(AudioDeviceID inDevice,
return noErr; return noErr;
} }


OSStatus JackCoreAudioDriver::AudioHardwareNotificationCallback(AudioHardwarePropertyID inPropertyID, void* inClientData)
{
JackCoreAudioDriver* driver = (JackCoreAudioDriver*)inClientData;

switch (inPropertyID) {

case kAudioHardwarePropertyDevices: {
jack_log("JackCoreAudioDriver::AudioHardwareNotificationCallback kAudioHardwarePropertyDevices");
DisplayDeviceNames();

AudioDeviceID captureID, playbackID;

jack_log("JackCoreAudioDriver::AudioHardwareNotificationCallback %s %d %s %d",
driver->fCaptureUID, CheckAvailableDeviceName(driver->fCaptureUID, &captureID),
driver->fPlaybackUID, CheckAvailableDeviceName(driver->fPlaybackUID, &playbackID));
jack_log("JackCoreAudioDriver::AudioHardwareNotificationCallback %d %d", driver->fDeviceID, CheckAvailableDevice(driver->fDeviceID));
driver->CloseAUHAL();

if (CheckAvailableDevice(driver->fDeviceID) ||
(CheckAvailableDeviceName(driver->fCaptureUID, &captureID) && CheckAvailableDeviceName(driver->fPlaybackUID, &playbackID))) {

vector<int> parsed_chan_in_list;
vector<int> parsed_chan_out_list;

if (driver->OpenAUHAL(true, true, 2, 2, 2, 2,
parsed_chan_in_list,
parsed_chan_out_list,
driver->fEngineControl->fBufferSize,
driver->fEngineControl->fSampleRate) < 0) {
jack_log("JackCoreAudioDriver::OpenAUHAL fails");
return -1;
}

// Waiting for Render callback to be called (= driver has started)
driver->fState = false;
int count = 0;

OSStatus err = AudioOutputUnitStart(driver->fAUHAL);
if (err == noErr) {

while (!driver->fState && count++ < WAIT_COUNTER) {
usleep(100000);
jack_log("JackCoreAudioDriver::Start wait count = %d", count);
}

if (count < WAIT_COUNTER) {
jack_info("CoreAudio driver is running...");
return 0;
}

jack_error("CoreAudio driver cannot start...");
return -1;
}

} else {
driver->CloseAUHAL();
}

break;
}

}

return noErr;
}

// A better implementation would possibly try to recover in case of hardware device change (see HALLAB HLFilePlayerWindowControllerAudioDevicePropertyListenerProc code) // A better implementation would possibly try to recover in case of hardware device change (see HALLAB HLFilePlayerWindowControllerAudioDevicePropertyListenerProc code)
OSStatus JackCoreAudioDriver::DeviceNotificationCallback(AudioDeviceID inDevice, OSStatus JackCoreAudioDriver::DeviceNotificationCallback(AudioDeviceID inDevice,
UInt32 inChannel, UInt32 inChannel,
@@ -350,6 +486,24 @@ OSStatus JackCoreAudioDriver::DeviceNotificationCallback(AudioDeviceID inDevice,
break; break;
} }


case kAudioDevicePropertyDeviceIsAlive: {
UInt32 isalive = 0;
UInt32 outsize = sizeof(UInt32);
if (AudioDeviceGetProperty(driver->fDeviceID, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyDeviceIsAlive, &outsize, &isalive) == noErr) {
jack_log("JackCoreAudioDriver::DeviceNotificationCallback kAudioDevicePropertyDeviceIsAlive = %d", isalive);
}
break;
}

case kAudioDevicePropertyDeviceHasChanged: {
UInt32 hachanged = 0;
UInt32 outsize = sizeof(UInt32);
if (AudioDeviceGetProperty(driver->fDeviceID, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyDeviceHasChanged, &outsize, &hachanged) == noErr) {
jack_log("JackCoreAudioDriver::DeviceNotificationCallback kAudioDevicePropertyDeviceHasChanged = %d", hachanged);
}
break;
}

case kAudioDeviceProcessorOverload: { case kAudioDeviceProcessorOverload: {
jack_error("JackCoreAudioDriver::DeviceNotificationCallback kAudioDeviceProcessorOverload"); jack_error("JackCoreAudioDriver::DeviceNotificationCallback kAudioDeviceProcessorOverload");
jack_time_t cur_time = GetMicroSeconds(); jack_time_t cur_time = GetMicroSeconds();
@@ -1057,7 +1211,10 @@ int JackCoreAudioDriver::SetupDevices(const char* capture_driver_uid,
if (CreateAggregateDevice(captureID, playbackID, samplerate, &fDeviceID) != noErr) { if (CreateAggregateDevice(captureID, playbackID, samplerate, &fDeviceID) != noErr) {
return -1; return -1;
} }
}

GetDeviceNameFromID(captureID, fCaptureUID);
GetDeviceNameFromID(playbackID, fPlaybackUID);
}


// Capture only // Capture only
} else if (strcmp(capture_driver_uid, "") != 0) { } else if (strcmp(capture_driver_uid, "") != 0) {
@@ -1117,6 +1274,9 @@ int JackCoreAudioDriver::SetupDevices(const char* capture_driver_uid,
if (CreateAggregateDevice(captureID, playbackID, samplerate, &fDeviceID) != noErr) { if (CreateAggregateDevice(captureID, playbackID, samplerate, &fDeviceID) != noErr) {
return -1; return -1;
} }

GetDeviceNameFromID(captureID, fCaptureUID);
GetDeviceNameFromID(playbackID, fPlaybackUID);
} }
} }


@@ -1628,6 +1788,7 @@ void JackCoreAudioDriver::DisposeBuffers()


void JackCoreAudioDriver::CloseAUHAL() void JackCoreAudioDriver::CloseAUHAL()
{ {
AudioOutputUnitStop(fAUHAL);
AudioUnitUninitialize(fAUHAL); AudioUnitUninitialize(fAUHAL);
CloseComponent(fAUHAL); CloseComponent(fAUHAL);
} }
@@ -1644,9 +1805,9 @@ int JackCoreAudioDriver::AddListeners()
return -1; return -1;
} }


err = AudioDeviceAddPropertyListener(fDeviceID, 0, true, kAudioHardwarePropertyDevices, DeviceNotificationCallback, this);
err = AudioHardwareAddPropertyListener(kAudioHardwarePropertyDevices, AudioHardwareNotificationCallback, this);
if (err != noErr) { if (err != noErr) {
jack_error("Error calling AudioDeviceAddPropertyListener with kAudioHardwarePropertyDevices");
jack_error("Error calling AudioHardwareAddPropertyListener with kAudioHardwarePropertyDevices");
printError(err); printError(err);
return -1; return -1;
} }
@@ -1665,6 +1826,20 @@ int JackCoreAudioDriver::AddListeners()
return -1; return -1;
} }


err = AudioDeviceAddPropertyListener(fDeviceID, 0, true, kAudioDevicePropertyDeviceIsAlive, DeviceNotificationCallback, this);
if (err != noErr) {
jack_error("Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyDeviceIsAlive");
printError(err);
return -1;
}

err = AudioDeviceAddPropertyListener(fDeviceID, 0, true, kAudioDevicePropertyDeviceHasChanged, DeviceNotificationCallback, this);
if (err != noErr) {
jack_error("Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyDeviceHasChanged");
printError(err);
return -1;
}

err = AudioDeviceAddPropertyListener(fDeviceID, 0, true, kAudioDevicePropertyStreamConfiguration, DeviceNotificationCallback, this); err = AudioDeviceAddPropertyListener(fDeviceID, 0, true, kAudioDevicePropertyStreamConfiguration, DeviceNotificationCallback, this);
if (err != noErr) { if (err != noErr) {
jack_error("Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyStreamConfiguration"); jack_error("Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyStreamConfiguration");
@@ -1694,9 +1869,11 @@ int JackCoreAudioDriver::AddListeners()
void JackCoreAudioDriver::RemoveListeners() void JackCoreAudioDriver::RemoveListeners()
{ {
AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioDeviceProcessorOverload, DeviceNotificationCallback); AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioDeviceProcessorOverload, DeviceNotificationCallback);
AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioHardwarePropertyDevices, DeviceNotificationCallback);
AudioHardwareRemovePropertyListener(kAudioHardwarePropertyDevices, AudioHardwareNotificationCallback);
AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioDevicePropertyNominalSampleRate, DeviceNotificationCallback); AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioDevicePropertyNominalSampleRate, DeviceNotificationCallback);
AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioDevicePropertyDeviceIsRunning, DeviceNotificationCallback); AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioDevicePropertyDeviceIsRunning, DeviceNotificationCallback);
AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioDevicePropertyDeviceIsAlive, DeviceNotificationCallback);
AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioDevicePropertyDeviceHasChanged, DeviceNotificationCallback);
AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioDevicePropertyStreamConfiguration, DeviceNotificationCallback); AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioDevicePropertyStreamConfiguration, DeviceNotificationCallback);
AudioDeviceRemovePropertyListener(fDeviceID, 0, false, kAudioDevicePropertyStreamConfiguration, DeviceNotificationCallback); AudioDeviceRemovePropertyListener(fDeviceID, 0, false, kAudioDevicePropertyStreamConfiguration, DeviceNotificationCallback);
} }
@@ -1724,9 +1901,6 @@ int JackCoreAudioDriver::Open(jack_nframes_t buffer_size,
char capture_driver_name[256]; char capture_driver_name[256];
char playback_driver_name[256]; char playback_driver_name[256];


// Keep initial state
strcpy(fCaptureUID, capture_driver_uid);
strcpy(fPlaybackUID, playback_driver_uid);
fCaptureLatency = capture_latency; fCaptureLatency = capture_latency;
fPlaybackLatency = playback_latency; fPlaybackLatency = playback_latency;
fIOUsage = float(async_output_latency) / 100.f; fIOUsage = float(async_output_latency) / 100.f;


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

@@ -62,7 +62,7 @@ class JackCoreAudioDriver : public JackAudioDriver


AudioDeviceID fDeviceID; // Used "duplex" device AudioDeviceID fDeviceID; // Used "duplex" device
AudioObjectID fPluginID; // Used for aggregate device AudioObjectID fPluginID; // Used for aggregate device
AudioUnitRenderActionFlags* fActionFags; AudioUnitRenderActionFlags* fActionFags;
const AudioTimeStamp* fCurrentTime; const AudioTimeStamp* fCurrentTime;


@@ -75,14 +75,17 @@ class JackCoreAudioDriver : public JackAudioDriver
float fIOUsage; float fIOUsage;
float fComputationGrain; float fComputationGrain;
bool fClockDriftCompensate; bool fClockDriftCompensate;

static OSStatus Render(void *inRefCon, static OSStatus Render(void *inRefCon,
AudioUnitRenderActionFlags *ioActionFlags, AudioUnitRenderActionFlags *ioActionFlags,
const AudioTimeStamp *inTimeStamp, const AudioTimeStamp *inTimeStamp,
UInt32 inBusNumber, UInt32 inBusNumber,
UInt32 inNumberFrames, UInt32 inNumberFrames,
AudioBufferList *ioData); AudioBufferList *ioData);

static OSStatus AudioHardwareNotificationCallback(AudioHardwarePropertyID inPropertyID,void* inClientData);
static OSStatus DeviceNotificationCallback(AudioDeviceID inDevice, static OSStatus DeviceNotificationCallback(AudioDeviceID inDevice,
UInt32 inChannel, UInt32 inChannel,
Boolean isInput, Boolean isInput,


Loading…
Cancel
Save