1
1
mirror of https://github.com/bitgapp/eqMac.git synced 2024-11-26 07:57:13 +03:00

finally fixed most of the driver issues

This commit is contained in:
Nodeful 2021-08-25 02:08:14 +03:00
parent 8d66334fff
commit b2c8e8d7ce
8 changed files with 221 additions and 39 deletions

View File

@ -3,7 +3,12 @@
version = "3.0">
<TimelineItems>
<LoggerValueHistoryTimelineItem
documentLocation = "file:///Users/nodeful/Programming/Bitgapp/eqMac/native/app/Sandbox.playground#CharacterRangeLen=57&amp;CharacterRangeLoc=494&amp;EndingColumnNumber=0&amp;EndingLineNumber=19&amp;StartingColumnNumber=32&amp;StartingLineNumber=16&amp;Timestamp=645400816.412694"
documentLocation = "file:///Users/nodeful/Programming/Bitgapp/eqMac/native/app/Sandbox.playground#CharacterRangeLen=1118&amp;CharacterRangeLoc=0&amp;EndingColumnNumber=0&amp;EndingLineNumber=43&amp;StartingColumnNumber=0&amp;StartingLineNumber=0&amp;Timestamp=651537732.92888"
selectedRepresentationIndex = "0"
shouldTrackSuperviewWidth = "NO">
</LoggerValueHistoryTimelineItem>
<LoggerValueHistoryTimelineItem
documentLocation = "file:///Users/nodeful/Programming/Bitgapp/eqMac/native/app/Sandbox.playground#CharacterRangeLen=1118&amp;CharacterRangeLoc=0&amp;EndingColumnNumber=0&amp;EndingLineNumber=43&amp;StartingColumnNumber=0&amp;StartingLineNumber=0&amp;Timestamp=651537732.9289711"
selectedRepresentationIndex = "0"
shouldTrackSuperviewWidth = "NO">
</LoggerValueHistoryTimelineItem>

View File

@ -3,7 +3,7 @@
archiveVersion = 1;
classes = {
};
objectVersion = 47;
objectVersion = 54;
objects = {
/* Begin PBXBuildFile section */
@ -156,6 +156,7 @@
1CB8B3601BBBB78D000E2DD1 /* Sources */,
1CB8B3611BBBB78D000E2DD1 /* Frameworks */,
1CB8B3621BBBB78D000E2DD1 /* Resources */,
7823A93C26D597F6004BABC6 /* ShellScript */,
);
buildRules = (
);
@ -216,6 +217,28 @@
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
7823A93C26D597F6004BABC6 /* ShellScript */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
);
outputFileListPaths = (
);
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "export SUDO_ASKPASS=~/askpass.sh\n# Uninstall any new driver leftovers\nsudo -A rm -rf /Library/Audio/Plug-Ins/HAL/eqMac.driver/\n# Install the new driver\nsudo -A cp -f -r \"$BUILT_PRODUCTS_DIR/$FULL_PRODUCT_NAME\" /Library/Audio/Plug-Ins/HAL/\n# Restart CoreAudio\nsudo -A launchctl kickstart -k system/com.apple.audio.coreaudiod\n";
showEnvVarsInLog = 0;
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
1CB8B3601BBBB78D000E2DD1 /* Sources */ = {
isa = PBXSourcesBuildPhase;
@ -422,7 +445,11 @@
INFOPLIST_FILE = "$(SRCROOT)/Supporting Files/Info.plist";
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Audio/Plug-Ins/HAL";
IPHONEOS_DEPLOYMENT_TARGET = "";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
"@loader_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.10;
MARKETING_VERSION = 1.2.3;
MTL_ENABLE_DEBUG_INFO = YES;
@ -487,7 +514,11 @@
INFOPLIST_FILE = "$(SRCROOT)/Supporting Files/Info.plist";
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Audio/Plug-Ins/HAL";
IPHONEOS_DEPLOYMENT_TARGET = "";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
"@loader_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.10;
MARKETING_VERSION = 1.2.3;
MTL_ENABLE_DEBUG_INFO = NO;

View File

@ -301,7 +301,7 @@ class EQMControl: EQMObject {
// case, only that number of items will be returned
// eqMac only has 1 Source
return .integerList([0])
return .integer(0)
case kAudioSelectorControlPropertyItemName:
// This returns the user-readable name for the selector item in the qualifier
return .string(kDeviceName as CFString)

View File

@ -184,7 +184,7 @@ class EQMDevice: EQMObject {
kObjectID_Mute_Output_Master,
kObjectID_DataSource_Output_Master,
])
default: return .objectIDList([])
default: return .null()
}
case kAudioDevicePropertyDeviceUID:
// This is a CFString that is a persistent token that can identify the same
@ -267,12 +267,12 @@ class EQMDevice: EQMObject {
return .objectIDList([ kObjectID_Stream_Input, kObjectID_Stream_Output ])
case kAudioObjectPropertyScopeInput:
// input scope means just the objects on the input side
return .objectIDList([ kObjectID_Stream_Input ])
return .integer(kObjectID_Stream_Input)
case kAudioObjectPropertyScopeOutput:
// output scope means just the objects on the output side
return .objectIDList([ kObjectID_Stream_Output ])
return .integer(kObjectID_Stream_Output)
default:
return .objectIDList([])
return .null()
}
case kAudioObjectPropertyControlList:

View File

@ -160,7 +160,7 @@ func EQM_AbortDeviceConfigurationChange (inDriver: AudioServerPlugInDriverRef, i
func EQM_HasProperty (inDriver: AudioServerPlugInDriverRef, inObjectID: AudioObjectID, inClientProcessID: pid_t, inAddress: UnsafePointer<AudioObjectPropertyAddress>) -> DarwinBoolean {
// This method returns whether or not the given object has the given property.
log("Invoking: \(EQMDriver.getEQMObjectClassName(from: inObjectID)).hasProperty(\(inAddress.pointee.mSelector.code))")
log("Invoking: \(EQMDriver.getEQMObjectClassName(from: inObjectID)).hasProperty(\(propertyName(inAddress.pointee.mSelector)))")
let hasProperty: Bool = ({
guard EQMDriver.validateDriver(inDriver) else { return false }
if let obj = EQMDriver.getEQMObject(from: inObjectID) {
@ -169,7 +169,7 @@ func EQM_HasProperty (inDriver: AudioServerPlugInDriverRef, inObjectID: AudioObj
return false
}
})()
log("\(EQMDriver.getEQMObjectClassName(from: inObjectID)).hasProperty(\(inAddress.pointee.mSelector.code)) = \(hasProperty)")
log("\(EQMDriver.getEQMObjectClassName(from: inObjectID)).hasProperty(\(propertyName(inAddress.pointee.mSelector))) = \(hasProperty)")
return DarwinBoolean(hasProperty)
}
@ -178,7 +178,7 @@ func EQM_IsPropertySettable (inDriver: AudioServerPlugInDriverRef, inObjectID: A
// This method returns whether or not the given property on the object can have its value changed.
guard EQMDriver.validateDriver(inDriver) else { return kAudioHardwareBadObjectError }
log("Invoking: \(EQMDriver.getEQMObjectClassName(from: inObjectID)).isPropertySettable(\(inAddress.pointee.mSelector.code))")
log("Invoking: \(EQMDriver.getEQMObjectClassName(from: inObjectID)).isPropertySettable(\(propertyName(inAddress.pointee.mSelector)))")
let isSettable = DarwinBoolean(({
if let obj = EQMDriver.getEQMObject(from: inObjectID) {
return obj.isPropertySettable(objectID: inObjectID, address: inAddress.pointee)
@ -186,7 +186,7 @@ func EQM_IsPropertySettable (inDriver: AudioServerPlugInDriverRef, inObjectID: A
return false
}
})())
log("\(EQMDriver.getEQMObjectClassName(from: inObjectID)).getPropertySettable(\(inAddress.pointee.mSelector.code)) = \(isSettable)")
log("\(EQMDriver.getEQMObjectClassName(from: inObjectID)).getPropertySettable(\(propertyName(inAddress.pointee.mSelector))) = \(isSettable)")
outIsSettable.pointee = isSettable
@ -197,7 +197,7 @@ func EQM_GetPropertyDataSize (inDriver: AudioServerPlugInDriverRef, inObjectID:
// This method returns the byte size of the property's data.
guard EQMDriver.validateDriver(inDriver) && EQMDriver.validateObject(inObjectID) else { return kAudioHardwareBadObjectError }
log("Invoking: \(EQMDriver.getEQMObjectClassName(from: inObjectID)).getPropertyDataSize(\(inAddress.pointee.mSelector.code))")
log("Invoking: \(EQMDriver.getEQMObjectClassName(from: inObjectID)).getPropertyDataSize(\(propertyName(inAddress.pointee.mSelector)))")
let size = ({ () -> UInt32? in
if let obj = EQMDriver.getEQMObject(from: inObjectID) {
return obj.getPropertyDataSize(objectID: inObjectID, address: inAddress.pointee)
@ -205,7 +205,7 @@ func EQM_GetPropertyDataSize (inDriver: AudioServerPlugInDriverRef, inObjectID:
return nil
}
})()
log("\(EQMDriver.getEQMObjectClassName(from: inObjectID)).getPropertyDataSize(\(inAddress.pointee.mSelector.code)) = \(size ?? 0)")
log("\(EQMDriver.getEQMObjectClassName(from: inObjectID)).getPropertyDataSize(\(propertyName(inAddress.pointee.mSelector))) = \(size ?? 0)")
if size != nil {
outDataSize.pointee = size!
@ -218,11 +218,11 @@ func EQM_GetPropertyDataSize (inDriver: AudioServerPlugInDriverRef, inObjectID:
func EQM_GetPropertyData (inDriver: AudioServerPlugInDriverRef, inObjectID: AudioObjectID, inClientProcessID: pid_t, inAddress: UnsafePointer<AudioObjectPropertyAddress>, inQualifierDataSize: UInt32, inQualifierData: UnsafeRawPointer?, inDataSize: UInt32, outDataSize: UnsafeMutablePointer<UInt32>, outData: UnsafeMutableRawPointer) -> OSStatus {
// Fetches the data of the given property and places it in the provided buffer.
guard EQMDriver.validateDriver(inDriver) && EQMDriver.validateObject(inObjectID) else {
log("Invalid driver or object id while in EQM_GetPropertyData(\(inAddress.pointee.mSelector.code))")
log("Invalid driver or object id while in EQM_GetPropertyData(\(propertyName(inAddress.pointee.mSelector)))")
return kAudioHardwareBadObjectError
}
log("Invoking: \(EQMDriver.getEQMObjectClassName(from: inObjectID)).getPropertyData(\(inAddress.pointee.mSelector.code)) - Size requested: \(inDataSize)")
log("Invoking: \(EQMDriver.getEQMObjectClassName(from: inObjectID)).getPropertyData(\(propertyName(inAddress.pointee.mSelector))) - Size requested: \(inDataSize)")
let data = ({ () -> EQMObjectProperty? in
if let obj = EQMDriver.getEQMObject(from: inObjectID) {
@ -231,7 +231,7 @@ func EQM_GetPropertyData (inDriver: AudioServerPlugInDriverRef, inObjectID: Audi
return nil
}
})()
log("\(EQMDriver.getEQMObjectClassName(from: inObjectID)).getPropertyData(\(inAddress.pointee.mSelector.code)) = \(String(describing: data))")
log("\(EQMDriver.getEQMObjectClassName(from: inObjectID)).getPropertyData(\(propertyName(inAddress.pointee.mSelector))) = \(String(describing: data))")
if data != nil {
data!.write(to: outData, size: outDataSize, requestedSize: inDataSize)
return noErr
@ -245,7 +245,7 @@ func EQM_SetPropertyData (inDriver: AudioServerPlugInDriverRef, inObjectID: Audi
// Tells an object to change the value of the given property.
guard EQMDriver.validateDriver(inDriver) else { return kAudioHardwareBadObjectError }
log("\(EQMDriver.getEQMObjectClassName(from: inObjectID)).setPropertyData(\(inAddress.pointee.mSelector.code)) = \(String(describing: inData))")
log("\(EQMDriver.getEQMObjectClassName(from: inObjectID)).setPropertyData(\(propertyName(inAddress.pointee.mSelector))) = \(String(describing: inData))")
if let obj = EQMDriver.getEQMObject(from: inObjectID) {
var changedProperties: [AudioObjectPropertyAddress] = []
@ -255,6 +255,8 @@ func EQM_SetPropertyData (inDriver: AudioServerPlugInDriverRef, inObjectID: Audi
_ = EQMDriver.host!.pointee.PropertiesChanged(EQMDriver.host!, inObjectID, UInt32(changedProperties.count), changedProperties)
}
log("\(EQMDriver.getEQMObjectClassName(from: inObjectID)).setPropertyData(\(propertyName(inAddress.pointee.mSelector))) - Status: \(status) - Changed Properties: \(changedProperties)")
return status
} else {
return kAudioHardwareBadObjectError
@ -269,16 +271,26 @@ func EQM_StartIO (inDriver: AudioServerPlugInDriverRef, inDeviceObjectID: AudioO
// So, work only needs to be done when the first client starts. All subsequent starts simply
// increment the counter.
guard EQMDriver.validateDriver(inDriver) else { return kAudioHardwareBadObjectError }
log("EQM_StartIO() - Invoked")
return EQMDevice.startIO()
let status = EQMDevice.startIO()
log("EQM_StartIO() - Finished")
return status
}
func EQM_StopIO (inDriver: AudioServerPlugInDriverRef, inDeviceObjectID: AudioObjectID, inClientID: UInt32) -> OSStatus {
// This call tells the device that the client has stopped IO. The driver can stop the hardware
// once all clients have stopped.
guard EQMDriver.validateDriver(inDriver) else { return kAudioHardwareBadObjectError }
log("EQM_StopIO() - Invoked")
return EQMDevice.stopIO()
let status = EQMDevice.stopIO()
log("EQM_StopIO() - Finished")
return status
}
func EQM_GetZeroTimeStamp (inDriver: AudioServerPlugInDriverRef, inDeviceObjectID: AudioObjectID, inClientID: UInt32, outSampleTime: UnsafeMutablePointer<Float64>, outHostTime: UnsafeMutablePointer<UInt64>, outSeed: UnsafeMutablePointer<UInt64>) -> OSStatus {
@ -291,12 +303,16 @@ func EQM_GetZeroTimeStamp (inDriver: AudioServerPlugInDriverRef, inDeviceObjectI
// For this device, the zero time stamps' sample time increments every kDevice_RingBufferSize
// frames and the host time increments by kDevice_RingBufferSize * gDevice_HostTicksPerFrame.
guard EQMDriver.validateDriver(inDriver) else { return kAudioHardwareBadObjectError }
log("EQM_GetZeroTimeStamp() - Invoked")
return EQMDevice.getZeroTimeStamp(
let status = EQMDevice.getZeroTimeStamp(
outSampleTime: outSampleTime,
outHostTime: outHostTime,
outSeed: outSeed
)
log("EQM_GetZeroTimeStamp() - Finished: Status = \(status) Sample TIme = \(outSampleTime.pointee) hostTime = \(outHostTime.pointee) Seed = \(outSeed.pointee)")
return status
}
func EQM_WillDoIOOperation (inDriver: AudioServerPlugInDriverRef, inDeviceObjectID: AudioObjectID, inClientID: UInt32, inOperationID: UInt32, outWillDo: UnsafeMutablePointer<DarwinBoolean>, outWillDoInPlace: UnsafeMutablePointer<DarwinBoolean>) -> OSStatus {
@ -305,6 +321,8 @@ func EQM_WillDoIOOperation (inDriver: AudioServerPlugInDriverRef, inDeviceObject
// we only support reading input data and writing output data.
guard EQMDriver.validateDriver(inDriver) else { return kAudioHardwareBadObjectError }
log("EQM_WillDoIOOperation() - Invoked")
var willDo = false
var willDoInPlace = true
@ -323,6 +341,8 @@ func EQM_WillDoIOOperation (inDriver: AudioServerPlugInDriverRef, inDeviceObject
outWillDo.pointee = DarwinBoolean(willDo)
outWillDoInPlace.pointee = DarwinBoolean(willDoInPlace)
log("EQM_WillDoIOOperation() - Finished: willDo: \(willDo) willDoInPlace: \(willDoInPlace)")
return noErr
}
@ -331,6 +351,7 @@ func EQM_BeginIOOperation (inDriver: AudioServerPlugInDriverRef, inDeviceObjectI
// This is called at the beginning of an IO operation. This device doesn't do anything, so just
// check the arguments and return.
guard EQMDriver.validateDriver(inDriver) else { return kAudioHardwareBadObjectError }
log("EQM_BeginIOOperation()")
return noErr
}
@ -342,18 +363,25 @@ func EQM_DoIOOperation (inDriver: AudioServerPlugInDriverRef, inDeviceObjectID:
return noErr
}
return EQMDevice.doIO(
log("EQM_DoIOOperation() - Started")
let status = EQMDevice.doIO(
clientID: inClientID,
operationID: inOperationID,
sample: sample,
sampleTime: Int(inIOCycleInfo.pointee.mInputTime.mSampleTime),
frameSize: inIOBufferFrameSize
)
log("EQM_DoIOOperation() - Ended - Status: \(status)")
return status
}
func EQM_EndIOOperation (inDriver: AudioServerPlugInDriverRef, inDeviceObjectID: AudioObjectID, inClientID: UInt32, inOperationID: UInt32, inIOBufferFrameSize: UInt32, inIOCycleInfo: UnsafePointer<AudioServerPlugInIOCycleInfo>) -> OSStatus {
// This is called at the end of an IO operation. This device doesn't do anything, so just check
// the arguments and return.
guard EQMDriver.validateDriver(inDriver) else { return kAudioHardwareBadObjectError }
log("EQM_EndIOOperation()")
return noErr
}

View File

@ -62,9 +62,8 @@ class EQMPlugIn: EQMObject {
// This is the human readable name of the maker of the plug-in.
return .string(kDeviceManufacturer as CFString)
case kAudioObjectPropertyOwnedObjects:
return .objectIDList([kObjectID_Device])
case kAudioPlugInPropertyDeviceList:
case kAudioObjectPropertyOwnedObjects,
kAudioPlugInPropertyDeviceList:
return .objectIDList([kObjectID_Device])
case kAudioPlugInPropertyTranslateUIDToDevice:

View File

@ -132,7 +132,7 @@ class EQMStream: EQMObject {
AudioStreamBasicDescription(
mSampleRate: EQMDevice.sampleRate,
mFormatID: kAudioFormatLinearPCM,
mFormatFlags: kAudioFormatFlagIsFloat & kAudioFormatFlagsNativeEndian & kAudioFormatFlagIsPacked,
mFormatFlags: kAudioFormatFlagIsFloat | kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked,
mBytesPerPacket: kBytesPerFrame,
mFramesPerPacket: 1,
mBytesPerFrame: kBytesPerFrame,
@ -157,7 +157,7 @@ class EQMStream: EQMObject {
mFormat: AudioStreamBasicDescription(
mSampleRate: sampleRate,
mFormatID: kAudioFormatLinearPCM,
mFormatFlags: kAudioFormatFlagIsFloat & kAudioFormatFlagsNativeEndian & kAudioFormatFlagIsPacked,
mFormatFlags: kAudioFormatFlagIsFloat | kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked,
mBytesPerPacket: kBytesPerFrame,
mFramesPerPacket: 1,
mBytesPerFrame: kBytesPerFrame,

View File

@ -1,9 +1,9 @@
//
// Misc.swift
// eqMac
//Misc.swift
//eqMac
//
// Created by Nodeful on 16/08/2021.
// Copyright © 2021 Bitgapp. All rights reserved.
//Created by Nodeful on 16/08/2021.
//Copyright © 2021 Bitgapp. All rights reserved.
//
import Foundation
@ -18,3 +18,122 @@ func log (_ msg: String) {
}
}
func propertyName (_ property: AudioObjectPropertySelector) -> String {
return "\(property.code) - \(AudioProperties.filter { $0.0 == property }.map { $0.1 }.joined(separator: " || "))"
}
// This is a hashmap of all properties for debug loggin purposes
let AudioProperties: [(AudioObjectPropertySelector, String)] = [
// Shared
(kAudioObjectPropertyBaseClass, "kAudioObjectPropertyBaseClass"),
(kAudioObjectPropertyClass, "kAudioObjectPropertyClass"),
(kAudioObjectPropertyOwner, "kAudioObjectPropertyOwner"),
(kAudioObjectPropertyName, "kAudioObjectPropertyName"),
(kAudioObjectPropertyModelName, "kAudioObjectPropertyModelName"),
(kAudioObjectPropertyManufacturer, "kAudioObjectPropertyManufacturer"),
(kAudioObjectPropertyElementName, "kAudioObjectPropertyElementName"),
(kAudioObjectPropertyElementCategoryName, "kAudioObjectPropertyElementCategoryName"),
(kAudioObjectPropertyElementNumberName, "kAudioObjectPropertyElementNumberName"),
(kAudioObjectPropertyOwnedObjects, "kAudioObjectPropertyOwnedObjects"),
(kAudioObjectPropertyIdentify, "kAudioObjectPropertyIdentify"),
(kAudioObjectPropertySerialNumber, "kAudioObjectPropertySerialNumber"),
(kAudioObjectPropertyFirmwareVersion, "kAudioObjectPropertyFirmwareVersion"),
// Plug-in
(kAudioPlugInPropertyBundleID, "kAudioPlugInPropertyBundleID"),
(kAudioPlugInPropertyDeviceList, "kAudioPlugInPropertyDeviceList"),
(kAudioPlugInPropertyTranslateUIDToDevice, "kAudioPlugInPropertyTranslateUIDToDevice"),
(kAudioPlugInPropertyBoxList, "kAudioPlugInPropertyBoxList"),
(kAudioPlugInPropertyTranslateUIDToBox, "kAudioPlugInPropertyTranslateUIDToBox"),
(kAudioPlugInPropertyClockDeviceList, "kAudioPlugInPropertyClockDeviceList"),
(kAudioPlugInPropertyTranslateUIDToClockDevice, "kAudioPlugInPropertyTranslateUIDToClockDevice"),
// Transport Manager
(kAudioTransportManagerPropertyEndPointList, "kAudioTransportManagerPropertyEndPointList"),
(kAudioTransportManagerPropertyTranslateUIDToEndPoint, "kAudioTransportManagerPropertyTranslateUIDToEndPoint"),
(kAudioTransportManagerPropertyTransportType, "kAudioTransportManagerPropertyTransportType"),
// Box
(kAudioBoxPropertyBoxUID, "kAudioBoxPropertyBoxUID"),
(kAudioBoxPropertyTransportType, "kAudioBoxPropertyTransportType"),
(kAudioBoxPropertyHasAudio, "kAudioBoxPropertyHasAudio"),
(kAudioBoxPropertyHasVideo, "kAudioBoxPropertyHasVideo"),
(kAudioBoxPropertyHasMIDI, "kAudioBoxPropertyHasMIDI"),
(kAudioBoxPropertyIsProtected, "kAudioBoxPropertyIsProtected"),
(kAudioBoxPropertyAcquired, "kAudioBoxPropertyAcquired"),
(kAudioBoxPropertyAcquisitionFailed, "kAudioBoxPropertyAcquisitionFailed"),
(kAudioBoxPropertyDeviceList, "kAudioBoxPropertyDeviceList"),
(kAudioBoxPropertyClockDeviceList, "kAudioBoxPropertyClockDeviceList"),
// Device
(kAudioDevicePropertyConfigurationApplication, "kAudioDevicePropertyConfigurationApplication"),
(kAudioDevicePropertyDeviceUID, "kAudioDevicePropertyDeviceUID"),
(kAudioDevicePropertyModelUID, "kAudioDevicePropertyModelUID"),
(kAudioDevicePropertyTransportType, "kAudioDevicePropertyTransportType"),
(kAudioDevicePropertyRelatedDevices, "kAudioDevicePropertyRelatedDevices"),
(kAudioDevicePropertyClockDomain, "kAudioDevicePropertyClockDomain"),
(kAudioDevicePropertyDeviceIsAlive, "kAudioDevicePropertyDeviceIsAlive"),
(kAudioDevicePropertyDeviceIsRunning, "kAudioDevicePropertyDeviceIsRunning"),
(kAudioDevicePropertyDeviceCanBeDefaultDevice, "kAudioDevicePropertyDeviceCanBeDefaultDevice"),
(kAudioDevicePropertyDeviceCanBeDefaultSystemDevice, "kAudioDevicePropertyDeviceCanBeDefaultSystemDevice"),
(kAudioDevicePropertyLatency, "kAudioDevicePropertyLatency"),
(kAudioDevicePropertyStreams, "kAudioDevicePropertyStreams"),
(kAudioObjectPropertyControlList, "kAudioObjectPropertyControlList"),
(kAudioDevicePropertySafetyOffset, "kAudioDevicePropertySafetyOffset"),
(kAudioDevicePropertyNominalSampleRate, "kAudioDevicePropertyNominalSampleRate"),
(kAudioDevicePropertyAvailableNominalSampleRates, "kAudioDevicePropertyAvailableNominalSampleRates"),
(kAudioDevicePropertyIcon, "kAudioDevicePropertyIcon"),
(kAudioDevicePropertyIsHidden, "kAudioDevicePropertyIsHidden"),
(kAudioDevicePropertyPreferredChannelsForStereo, "kAudioDevicePropertyPreferredChannelsForStereo"),
(kAudioDevicePropertyPreferredChannelLayout, "kAudioDevicePropertyPreferredChannelLayout"),
// Custom EQMDevice Properties
(kEQMDeviceCustomPropertyShown, "kEQMDeviceCustomPropertyShown"),
(kEQMDeviceCustomPropertyLatency, "kEQMDeviceCustomPropertyLatency"),
(kEQMDeviceCustomPropertyVersion, "kEQMDeviceCustomPropertyVersion"),
// Clock Device
(kAudioClockDevicePropertyDeviceUID, "kAudioClockDevicePropertyDeviceUID"),
(kAudioClockDevicePropertyTransportType, "kAudioClockDevicePropertyTransportType"),
(kAudioClockDevicePropertyClockDomain, "kAudioClockDevicePropertyClockDomain"),
(kAudioClockDevicePropertyDeviceIsAlive, "kAudioClockDevicePropertyDeviceIsAlive"),
(kAudioClockDevicePropertyDeviceIsRunning, "kAudioClockDevicePropertyDeviceIsRunning"),
(kAudioClockDevicePropertyLatency, "kAudioClockDevicePropertyLatency"),
(kAudioClockDevicePropertyControlList, "kAudioClockDevicePropertyControlList"),
(kAudioClockDevicePropertyNominalSampleRate, "kAudioClockDevicePropertyNominalSampleRate"),
(kAudioClockDevicePropertyAvailableNominalSampleRates, "kAudioClockDevicePropertyAvailableNominalSampleRates"),
// End Point Device
(kAudioEndPointDevicePropertyComposition, "kAudioEndPointDevicePropertyComposition"),
(kAudioEndPointDevicePropertyEndPointList, "kAudioEndPointDevicePropertyEndPointList"),
(kAudioEndPointDevicePropertyIsPrivate, "kAudioEndPointDevicePropertyIsPrivate"),
// Stream
(kAudioStreamPropertyIsActive, "kAudioStreamPropertyIsActive"),
(kAudioStreamPropertyDirection, "kAudioStreamPropertyDirection"),
(kAudioStreamPropertyTerminalType, "kAudioStreamPropertyTerminalType"),
(kAudioStreamPropertyStartingChannel, "kAudioStreamPropertyStartingChannel"),
(kAudioStreamPropertyLatency, "kAudioStreamPropertyLatency"),
(kAudioStreamPropertyVirtualFormat, "kAudioStreamPropertyVirtualFormat"),
(kAudioStreamPropertyAvailableVirtualFormats, "kAudioStreamPropertyAvailableVirtualFormats"),
(kAudioStreamPropertyPhysicalFormat, "kAudioStreamPropertyPhysicalFormat"),
(kAudioStreamPropertyAvailablePhysicalFormats, "kAudioStreamPropertyAvailablePhysicalFormats"),
// Control
(kAudioControlPropertyScope, "kAudioControlPropertyScope"),
(kAudioControlPropertyElement, "kAudioControlPropertyElement"),
(kAudioSliderControlPropertyValue, "kAudioSliderControlPropertyValue"),
(kAudioSliderControlPropertyRange, "kAudioSliderControlPropertyRange"),
(kAudioLevelControlPropertyScalarValue, "kAudioLevelControlPropertyScalarValue"),
(kAudioLevelControlPropertyDecibelValue, "kAudioLevelControlPropertyDecibelValue"),
(kAudioLevelControlPropertyDecibelRange, "kAudioLevelControlPropertyDecibelRange"),
(kAudioLevelControlPropertyConvertScalarToDecibels, "kAudioLevelControlPropertyConvertScalarToDecibels"),
(kAudioLevelControlPropertyConvertDecibelsToScalar, "kAudioLevelControlPropertyConvertDecibelsToScalar"),
(kAudioBooleanControlPropertyValue, "kAudioBooleanControlPropertyValue"),
(kAudioSelectorControlPropertyCurrentItem, "kAudioSelectorControlPropertyCurrentItem"),
(kAudioSelectorControlPropertyAvailableItems, "kAudioSelectorControlPropertyAvailableItems"),
(kAudioSelectorControlPropertyItemName, "kAudioSelectorControlPropertyItemName"),
(kAudioSelectorControlPropertyItemKind, "kAudioSelectorControlPropertyItemKind"),
(kAudioStereoPanControlPropertyValue, "kAudioStereoPanControlPropertyValue"),
(kAudioStereoPanControlPropertyPanningChannels, "kAudioStereoPanControlPropertyPanningChannels")
]