mirror of
https://github.com/bitgapp/eqMac.git
synced 2024-11-22 22:32:17 +03:00
fixes
This commit is contained in:
parent
e712cb55b1
commit
1e18a933ad
@ -30,7 +30,7 @@ let kDeviceManufacturer = "Bitgapp Ltd"
|
|||||||
let kBoxDefaultName = "eqMac Box"
|
let kBoxDefaultName = "eqMac Box"
|
||||||
|
|
||||||
let kPlugInBundleId = "com.bitgapp.eqmac.driver"
|
let kPlugInBundleId = "com.bitgapp.eqmac.driver"
|
||||||
let kBoxUID = "eqMacBox_UID"
|
let kBoxUID = "EQMBox"
|
||||||
let kDeviceUID = "EQMDevice"
|
let kDeviceUID = "EQMDevice"
|
||||||
let kDeviceModelUID = "EQMDeviceModelUID"
|
let kDeviceModelUID = "EQMDeviceModelUID"
|
||||||
|
|
||||||
|
@ -137,7 +137,11 @@ class EQMBox: EQMObject {
|
|||||||
return .integer(0)
|
return .integer(0)
|
||||||
case kAudioBoxPropertyDeviceList:
|
case kAudioBoxPropertyDeviceList:
|
||||||
// This is used to indicate which devices came from this box
|
// This is used to indicate which devices came from this box
|
||||||
return .integer(acquired ? kObjectID_Device : 0)
|
if acquired {
|
||||||
|
return .integer(kObjectID_Device)
|
||||||
|
} else {
|
||||||
|
return .null()
|
||||||
|
}
|
||||||
default: return nil
|
default: return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -113,7 +113,7 @@ class EQMDevice: EQMObject {
|
|||||||
case kAudioObjectPropertyControlList: return 6 * sizeof(AudioObjectID.self)
|
case kAudioObjectPropertyControlList: return 6 * sizeof(AudioObjectID.self)
|
||||||
case kAudioDevicePropertySafetyOffset: return sizeof(UInt32.self)
|
case kAudioDevicePropertySafetyOffset: return sizeof(UInt32.self)
|
||||||
case kAudioDevicePropertyNominalSampleRate: return sizeof(Float64.self)
|
case kAudioDevicePropertyNominalSampleRate: return sizeof(Float64.self)
|
||||||
case kAudioDevicePropertyAvailableNominalSampleRates: return 6 * sizeof(AudioValueRange.self)
|
case kAudioDevicePropertyAvailableNominalSampleRates: return UInt32(kSupportedSamplingRates.count) * sizeof(AudioValueRange.self)
|
||||||
case kAudioDevicePropertyIsHidden: return sizeof(UInt32.self)
|
case kAudioDevicePropertyIsHidden: return sizeof(UInt32.self)
|
||||||
case kAudioDevicePropertyPreferredChannelsForStereo: return 2 * sizeof(UInt32.self)
|
case kAudioDevicePropertyPreferredChannelsForStereo: return 2 * sizeof(UInt32.self)
|
||||||
case kAudioDevicePropertyPreferredChannelLayout:
|
case kAudioDevicePropertyPreferredChannelLayout:
|
||||||
@ -183,7 +183,8 @@ class EQMDevice: EQMObject {
|
|||||||
kObjectID_Volume_Output_Master,
|
kObjectID_Volume_Output_Master,
|
||||||
kObjectID_Mute_Output_Master,
|
kObjectID_Mute_Output_Master,
|
||||||
kObjectID_DataSource_Output_Master,
|
kObjectID_DataSource_Output_Master,
|
||||||
]) default: return .objectIDList([])
|
])
|
||||||
|
default: return .objectIDList([])
|
||||||
}
|
}
|
||||||
case kAudioDevicePropertyDeviceUID:
|
case kAudioDevicePropertyDeviceUID:
|
||||||
// This is a CFString that is a persistent token that can identify the same
|
// This is a CFString that is a persistent token that can identify the same
|
||||||
@ -335,7 +336,8 @@ class EQMDevice: EQMObject {
|
|||||||
mNumberChannelDescriptions: UInt32(kChannelCount),
|
mNumberChannelDescriptions: UInt32(kChannelCount),
|
||||||
mChannelDescriptions: AudioChannelDescription()
|
mChannelDescriptions: AudioChannelDescription()
|
||||||
)
|
)
|
||||||
let channelSize = MemoryLayout<AudioChannelDescription>.stride * channelDescriptions.count
|
// INFO: have to go with channelDescriptions.count - 1 as MemoryLayout<AudioChannelDescription>.stride might already contain the size for 1 channel
|
||||||
|
let channelSize = MemoryLayout<AudioChannelDescription>.stride * channelDescriptions.count - 1
|
||||||
memcpy(&channelLayout.mChannelDescriptions, &channelDescriptions, channelSize)
|
memcpy(&channelLayout.mChannelDescriptions, &channelDescriptions, channelSize)
|
||||||
return .channelLayout(channelLayout)
|
return .channelLayout(channelLayout)
|
||||||
case kAudioDevicePropertyZeroTimeStampPeriod:
|
case kAudioDevicePropertyZeroTimeStampPeriod:
|
||||||
|
@ -115,12 +115,12 @@ import CoreAudio.AudioServerPlugIn
|
|||||||
return "Unknown"
|
return "Unknown"
|
||||||
}
|
}
|
||||||
|
|
||||||
static func calculateHostTicksPerFrame () -> Float64 {
|
static func calculateHostTicksPerFrame () {
|
||||||
// calculate the host ticks per frame
|
// calculate the host ticks per frame
|
||||||
var theTimeBaseInfo = mach_timebase_info()
|
var theTimeBaseInfo = mach_timebase_info()
|
||||||
mach_timebase_info(&theTimeBaseInfo)
|
mach_timebase_info(&theTimeBaseInfo)
|
||||||
var theHostClockFrequency = Float64(theTimeBaseInfo.denom) / Float64(theTimeBaseInfo.numer)
|
var theHostClockFrequency = Float64(theTimeBaseInfo.denom) / Float64(theTimeBaseInfo.numer)
|
||||||
theHostClockFrequency *= 1000000000.0
|
theHostClockFrequency *= 1000000000.0
|
||||||
return theHostClockFrequency / EQMDevice.sampleRate
|
hostTicksPerFrame = theHostClockFrequency / EQMDevice.sampleRate
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -84,11 +84,10 @@ func EQM_Initialize (inDriver: AudioServerPlugInDriverRef, inHost: AudioServerPl
|
|||||||
if (EQMBox.name == nil) {
|
if (EQMBox.name == nil) {
|
||||||
EQMBox.name = kBoxDefaultName
|
EQMBox.name = kBoxDefaultName
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EQMDriver.calculateHostTicksPerFrame()
|
||||||
|
|
||||||
EQMBox.acquired = true
|
return noErr
|
||||||
EQMDriver.hostTicksPerFrame = EQMDriver.calculateHostTicksPerFrame()
|
|
||||||
|
|
||||||
return kAudioHardwareNoError
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func EQM_CreateDevice (inDriver: AudioServerPlugInDriverRef, inDescription: CFDictionary, inClientInfo: UnsafePointer<AudioServerPlugInClientInfo>, outDeviceObjectID: UnsafeMutablePointer<AudioObjectID>) -> OSStatus {
|
func EQM_CreateDevice (inDriver: AudioServerPlugInDriverRef, inDescription: CFDictionary, inClientInfo: UnsafePointer<AudioServerPlugInClientInfo>, outDeviceObjectID: UnsafeMutablePointer<AudioObjectID>) -> OSStatus {
|
||||||
@ -150,9 +149,9 @@ func EQM_PerformDeviceConfigurationChange (inDriver: AudioServerPlugInDriverRef,
|
|||||||
if !kSupportedSamplingRates.contains(where: { UInt64($0) == inChangeAction }) { return kAudioHardwareBadObjectError }
|
if !kSupportedSamplingRates.contains(where: { UInt64($0) == inChangeAction }) { return kAudioHardwareBadObjectError }
|
||||||
|
|
||||||
EQMDevice.sampleRate = Float64(inChangeAction)
|
EQMDevice.sampleRate = Float64(inChangeAction)
|
||||||
EQMDriver.hostTicksPerFrame = EQMDriver.calculateHostTicksPerFrame()
|
EQMDriver.calculateHostTicksPerFrame()
|
||||||
|
|
||||||
return kAudioHardwareNoError
|
return noErr
|
||||||
}
|
}
|
||||||
|
|
||||||
func EQM_AbortDeviceConfigurationChange (inDriver: AudioServerPlugInDriverRef, inDeviceObjectID: AudioObjectID, inChangeAction: UInt64, inChangeInfo: UnsafeMutableRawPointer?) -> OSStatus {
|
func EQM_AbortDeviceConfigurationChange (inDriver: AudioServerPlugInDriverRef, inDeviceObjectID: AudioObjectID, inChangeAction: UInt64, inChangeInfo: UnsafeMutableRawPointer?) -> OSStatus {
|
||||||
|
@ -19,6 +19,7 @@ protocol EQMObject: class {
|
|||||||
|
|
||||||
enum EQMObjectProperty {
|
enum EQMObjectProperty {
|
||||||
// Primitives
|
// Primitives
|
||||||
|
case null (Void? = nil)
|
||||||
case audioClassID(AudioClassID)
|
case audioClassID(AudioClassID)
|
||||||
case bool(CFBoolean)
|
case bool(CFBoolean)
|
||||||
case string(CFString)
|
case string(CFString)
|
||||||
@ -43,6 +44,7 @@ enum EQMObjectProperty {
|
|||||||
|
|
||||||
func write(to address: UnsafeMutableRawPointer?, size: UnsafeMutablePointer<UInt32>, requestedSize: UInt32?) {
|
func write(to address: UnsafeMutableRawPointer?, size: UnsafeMutablePointer<UInt32>, requestedSize: UInt32?) {
|
||||||
switch self {
|
switch self {
|
||||||
|
case .null(_): self.write(element: NSNull(), address: address, size: size)
|
||||||
case .bool(let data): self.write(element: data, address: address, size: size)
|
case .bool(let data): self.write(element: data, address: address, size: size)
|
||||||
case .string(let data): self.write(element: data, address: address, size: size)
|
case .string(let data): self.write(element: data, address: address, size: size)
|
||||||
case .float32(let data): self.write(element: data, address: address, size: size)
|
case .float32(let data): self.write(element: data, address: address, size: size)
|
||||||
@ -67,10 +69,12 @@ enum EQMObjectProperty {
|
|||||||
|
|
||||||
|
|
||||||
private func write<T>(element: T, address: UnsafeMutableRawPointer?, size: UnsafeMutablePointer<UInt32>) {
|
private func write<T>(element: T, address: UnsafeMutableRawPointer?, size: UnsafeMutablePointer<UInt32>) {
|
||||||
// Write data size
|
if T.self != NSNull.self {
|
||||||
size.pointee = UInt32(MemoryLayout.size(ofValue: element))
|
size.pointee = UInt32(MemoryLayout.size(ofValue: element))
|
||||||
// Write data
|
address?.assumingMemoryBound(to: T.self).pointee = element
|
||||||
address?.assumingMemoryBound(to: T.self).pointee = element
|
} else {
|
||||||
|
size.pointee = 0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func write<T: Any>(array arr: ContiguousArray<T>, address: UnsafeMutableRawPointer?, size: UnsafeMutablePointer<UInt32>, requestedSize: UInt32?) {
|
private func write<T: Any>(array arr: ContiguousArray<T>, address: UnsafeMutableRawPointer?, size: UnsafeMutablePointer<UInt32>, requestedSize: UInt32?) {
|
||||||
|
@ -32,18 +32,7 @@ class EQMPlugIn: EQMObject {
|
|||||||
|
|
||||||
static func isPropertySettable (objectID: AudioObjectID? = nil, address: AudioObjectPropertyAddress) -> Bool {
|
static func isPropertySettable (objectID: AudioObjectID? = nil, address: AudioObjectPropertyAddress) -> Bool {
|
||||||
switch address.mSelector {
|
switch address.mSelector {
|
||||||
case kAudioObjectPropertyBaseClass,
|
default: return false
|
||||||
kAudioObjectPropertyClass,
|
|
||||||
kAudioObjectPropertyOwner,
|
|
||||||
kAudioObjectPropertyManufacturer,
|
|
||||||
kAudioObjectPropertyOwnedObjects,
|
|
||||||
kAudioPlugInPropertyBoxList,
|
|
||||||
kAudioPlugInPropertyTranslateUIDToBox,
|
|
||||||
kAudioPlugInPropertyDeviceList,
|
|
||||||
kAudioPlugInPropertyTranslateUIDToDevice,
|
|
||||||
kAudioPlugInPropertyResourceBundle,
|
|
||||||
kAudioObjectPropertyCustomPropertyInfoList: return true
|
|
||||||
default: return false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,19 +77,35 @@ class EQMPlugIn: EQMObject {
|
|||||||
case kAudioObjectPropertyManufacturer:
|
case kAudioObjectPropertyManufacturer:
|
||||||
// This is the human readable name of the maker of the plug-in.
|
// This is the human readable name of the maker of the plug-in.
|
||||||
return .string(kDeviceManufacturer as CFString)
|
return .string(kDeviceManufacturer as CFString)
|
||||||
|
|
||||||
case kAudioObjectPropertyOwnedObjects:
|
case kAudioObjectPropertyOwnedObjects:
|
||||||
return .objectIDList([kObjectID_Box, kObjectID_Device])
|
var objects = ContiguousArray<AudioObjectID>()
|
||||||
|
objects.append(kObjectID_Box)
|
||||||
|
if EQMBox.acquired {
|
||||||
|
objects.append(kObjectID_Device)
|
||||||
|
}
|
||||||
|
return .objectIDList(objects)
|
||||||
|
|
||||||
case kAudioPlugInPropertyBoxList:
|
case kAudioPlugInPropertyBoxList:
|
||||||
return .objectIDList([kObjectID_Box])
|
return .objectIDList([kObjectID_Box])
|
||||||
|
|
||||||
case kAudioPlugInPropertyTranslateUIDToBox:
|
case kAudioPlugInPropertyTranslateUIDToBox:
|
||||||
let uid = inData?.assumingMemoryBound(to: CFString?.self).pointee
|
let uid = inData?.assumingMemoryBound(to: CFString?.self).pointee
|
||||||
|
|
||||||
if (CFStringCompare(uid, kBoxUID as CFString, .init(rawValue: 0)) == CFComparisonResult.compareEqualTo) {
|
if (CFStringCompare(uid, kBoxUID as CFString, .init(rawValue: 0)) == CFComparisonResult.compareEqualTo) {
|
||||||
return .integer(kObjectID_Box)
|
return .integer(kObjectID_Box)
|
||||||
} else {
|
} else {
|
||||||
return .integer(kAudioObjectUnknown)
|
return .integer(kAudioObjectUnknown)
|
||||||
}
|
}
|
||||||
|
|
||||||
case kAudioPlugInPropertyDeviceList:
|
case kAudioPlugInPropertyDeviceList:
|
||||||
return .objectIDList([kObjectID_Device])
|
var devices = ContiguousArray<AudioObjectID>()
|
||||||
|
|
||||||
|
if EQMBox.acquired {
|
||||||
|
devices.append(kObjectID_Device)
|
||||||
|
}
|
||||||
|
return .objectIDList(devices)
|
||||||
|
|
||||||
case kAudioPlugInPropertyTranslateUIDToDevice:
|
case kAudioPlugInPropertyTranslateUIDToDevice:
|
||||||
// This property takes the CFString passed in the qualifier and converts that
|
// This property takes the CFString passed in the qualifier and converts that
|
||||||
// to the object ID of the device it corresponds to. For this driver, there is
|
// to the object ID of the device it corresponds to. For this driver, there is
|
||||||
|
@ -72,7 +72,7 @@ class EQMStream: EQMObject {
|
|||||||
case kAudioStreamPropertyVirtualFormat,
|
case kAudioStreamPropertyVirtualFormat,
|
||||||
kAudioStreamPropertyPhysicalFormat: return sizeof(AudioStreamBasicDescription.self)
|
kAudioStreamPropertyPhysicalFormat: return sizeof(AudioStreamBasicDescription.self)
|
||||||
case kAudioStreamPropertyAvailableVirtualFormats,
|
case kAudioStreamPropertyAvailableVirtualFormats,
|
||||||
kAudioStreamPropertyAvailablePhysicalFormats: return 6 * sizeof(AudioStreamRangedDescription.self)
|
kAudioStreamPropertyAvailablePhysicalFormats: return UInt32(kSupportedSamplingRates.count) * sizeof(AudioStreamRangedDescription.self)
|
||||||
default:
|
default:
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user