Commit 77053812 authored by sletz's avatar sletz
Browse files

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
parent 0b948126
......@@ -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);
......
......@@ -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,
......
......@@ -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;
......
......@@ -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,
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment