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,
UInt32 inChannel,
Boolean isInput,
@@ -222,9 +238,9 @@ int JackCoreAudioAdapter::AddListeners()
return -1;
}

err = AudioDeviceAddPropertyListener(fDeviceID, 0, true, kAudioHardwarePropertyDevices, DeviceNotificationCallback, this);
err = AudioHardwareAddPropertyListener(kAudioHardwarePropertyDevices, AudioHardwareNotificationCallback, this);
if (err != noErr) {
jack_error("Error calling AudioDeviceAddPropertyListener with kAudioHardwarePropertyDevices");
jack_error("Error calling AudioHardwareAddPropertyListener with kAudioHardwarePropertyDevices");
printError(err);
return -1;
}
@@ -263,7 +279,7 @@ int JackCoreAudioAdapter::AddListeners()
void JackCoreAudioAdapter::RemoveListeners()
{
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, kAudioDevicePropertyDeviceIsRunning, 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,
AudioBufferList *ioData);

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

static OSStatus SRNotificationCallback(AudioDeviceID inDevice,
UInt32 inChannel,
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()
{
UInt32 size;
@@ -169,7 +239,7 @@ static OSStatus DisplayDeviceNames()
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;
@@ -330,6 +400,72 @@ OSStatus JackCoreAudioDriver::BSNotificationCallback(AudioDeviceID inDevice,
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)
OSStatus JackCoreAudioDriver::DeviceNotificationCallback(AudioDeviceID inDevice,
UInt32 inChannel,
@@ -350,6 +486,24 @@ OSStatus JackCoreAudioDriver::DeviceNotificationCallback(AudioDeviceID inDevice,
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: {
jack_error("JackCoreAudioDriver::DeviceNotificationCallback kAudioDeviceProcessorOverload");
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) {
return -1;
}
}

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

// Capture only
} 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) {
return -1;
}

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

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

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

err = AudioDeviceAddPropertyListener(fDeviceID, 0, true, kAudioHardwarePropertyDevices, DeviceNotificationCallback, this);
err = AudioHardwareAddPropertyListener(kAudioHardwarePropertyDevices, AudioHardwareNotificationCallback, this);
if (err != noErr) {
jack_error("Error calling AudioDeviceAddPropertyListener with kAudioHardwarePropertyDevices");
jack_error("Error calling AudioHardwareAddPropertyListener with kAudioHardwarePropertyDevices");
printError(err);
return -1;
}
@@ -1665,6 +1826,20 @@ int JackCoreAudioDriver::AddListeners()
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);
if (err != noErr) {
jack_error("Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyStreamConfiguration");
@@ -1694,9 +1869,11 @@ int JackCoreAudioDriver::AddListeners()
void JackCoreAudioDriver::RemoveListeners()
{
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, kAudioDevicePropertyDeviceIsRunning, DeviceNotificationCallback);
AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioDevicePropertyDeviceIsAlive, DeviceNotificationCallback);
AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioDevicePropertyDeviceHasChanged, DeviceNotificationCallback);
AudioDeviceRemovePropertyListener(fDeviceID, 0, true, 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 playback_driver_name[256];

// Keep initial state
strcpy(fCaptureUID, capture_driver_uid);
strcpy(fPlaybackUID, playback_driver_uid);
fCaptureLatency = capture_latency;
fPlaybackLatency = playback_latency;
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
AudioObjectID fPluginID; // Used for aggregate device
AudioUnitRenderActionFlags* fActionFags;
const AudioTimeStamp* fCurrentTime;

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

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

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


Loading…
Cancel
Save