1
1
mirror of https://github.com/bitgapp/eqMac.git synced 2024-11-22 13:07:26 +03:00
This commit is contained in:
Nodeful 2021-08-23 02:16:36 +03:00
parent e712cb55b1
commit 1e18a933ad
8 changed files with 46 additions and 32 deletions

View File

@ -30,7 +30,7 @@ let kDeviceManufacturer = "Bitgapp Ltd"
let kBoxDefaultName = "eqMac Box"
let kPlugInBundleId = "com.bitgapp.eqmac.driver"
let kBoxUID = "eqMacBox_UID"
let kBoxUID = "EQMBox"
let kDeviceUID = "EQMDevice"
let kDeviceModelUID = "EQMDeviceModelUID"

View File

@ -137,7 +137,11 @@ class EQMBox: EQMObject {
return .integer(0)
case kAudioBoxPropertyDeviceList:
// 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
}
}

View File

@ -113,7 +113,7 @@ class EQMDevice: EQMObject {
case kAudioObjectPropertyControlList: return 6 * sizeof(AudioObjectID.self)
case kAudioDevicePropertySafetyOffset: return sizeof(UInt32.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 kAudioDevicePropertyPreferredChannelsForStereo: return 2 * sizeof(UInt32.self)
case kAudioDevicePropertyPreferredChannelLayout:
@ -183,7 +183,8 @@ class EQMDevice: EQMObject {
kObjectID_Volume_Output_Master,
kObjectID_Mute_Output_Master,
kObjectID_DataSource_Output_Master,
]) default: return .objectIDList([])
])
default: return .objectIDList([])
}
case kAudioDevicePropertyDeviceUID:
// This is a CFString that is a persistent token that can identify the same
@ -335,7 +336,8 @@ class EQMDevice: EQMObject {
mNumberChannelDescriptions: UInt32(kChannelCount),
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)
return .channelLayout(channelLayout)
case kAudioDevicePropertyZeroTimeStampPeriod:

View File

@ -115,12 +115,12 @@ import CoreAudio.AudioServerPlugIn
return "Unknown"
}
static func calculateHostTicksPerFrame () -> Float64 {
static func calculateHostTicksPerFrame () {
// calculate the host ticks per frame
var theTimeBaseInfo = mach_timebase_info()
mach_timebase_info(&theTimeBaseInfo)
var theHostClockFrequency = Float64(theTimeBaseInfo.denom) / Float64(theTimeBaseInfo.numer)
theHostClockFrequency *= 1000000000.0
return theHostClockFrequency / EQMDevice.sampleRate
hostTicksPerFrame = theHostClockFrequency / EQMDevice.sampleRate
}
}

View File

@ -84,11 +84,10 @@ func EQM_Initialize (inDriver: AudioServerPlugInDriverRef, inHost: AudioServerPl
if (EQMBox.name == nil) {
EQMBox.name = kBoxDefaultName
}
EQMDriver.calculateHostTicksPerFrame()
EQMBox.acquired = true
EQMDriver.hostTicksPerFrame = EQMDriver.calculateHostTicksPerFrame()
return kAudioHardwareNoError
return noErr
}
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 }
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 {

View File

@ -19,6 +19,7 @@ protocol EQMObject: class {
enum EQMObjectProperty {
// Primitives
case null (Void? = nil)
case audioClassID(AudioClassID)
case bool(CFBoolean)
case string(CFString)
@ -43,6 +44,7 @@ enum EQMObjectProperty {
func write(to address: UnsafeMutableRawPointer?, size: UnsafeMutablePointer<UInt32>, requestedSize: UInt32?) {
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 .string(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>) {
// Write data size
size.pointee = UInt32(MemoryLayout.size(ofValue: element))
// Write data
address?.assumingMemoryBound(to: T.self).pointee = element
if T.self != NSNull.self {
size.pointee = UInt32(MemoryLayout.size(ofValue: 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?) {

View File

@ -32,18 +32,7 @@ class EQMPlugIn: EQMObject {
static func isPropertySettable (objectID: AudioObjectID? = nil, address: AudioObjectPropertyAddress) -> Bool {
switch address.mSelector {
case kAudioObjectPropertyBaseClass,
kAudioObjectPropertyClass,
kAudioObjectPropertyOwner,
kAudioObjectPropertyManufacturer,
kAudioObjectPropertyOwnedObjects,
kAudioPlugInPropertyBoxList,
kAudioPlugInPropertyTranslateUIDToBox,
kAudioPlugInPropertyDeviceList,
kAudioPlugInPropertyTranslateUIDToDevice,
kAudioPlugInPropertyResourceBundle,
kAudioObjectPropertyCustomPropertyInfoList: return true
default: return false
default: return false
}
}
@ -88,19 +77,35 @@ class EQMPlugIn: EQMObject {
case kAudioObjectPropertyManufacturer:
// This is the human readable name of the maker of the plug-in.
return .string(kDeviceManufacturer as CFString)
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:
return .objectIDList([kObjectID_Box])
case kAudioPlugInPropertyTranslateUIDToBox:
let uid = inData?.assumingMemoryBound(to: CFString?.self).pointee
if (CFStringCompare(uid, kBoxUID as CFString, .init(rawValue: 0)) == CFComparisonResult.compareEqualTo) {
return .integer(kObjectID_Box)
} else {
return .integer(kAudioObjectUnknown)
}
case kAudioPlugInPropertyDeviceList:
return .objectIDList([kObjectID_Device])
var devices = ContiguousArray<AudioObjectID>()
if EQMBox.acquired {
devices.append(kObjectID_Device)
}
return .objectIDList(devices)
case kAudioPlugInPropertyTranslateUIDToDevice:
// 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

View File

@ -72,7 +72,7 @@ class EQMStream: EQMObject {
case kAudioStreamPropertyVirtualFormat,
kAudioStreamPropertyPhysicalFormat: return sizeof(AudioStreamBasicDescription.self)
case kAudioStreamPropertyAvailableVirtualFormats,
kAudioStreamPropertyAvailablePhysicalFormats: return 6 * sizeof(AudioStreamRangedDescription.self)
kAudioStreamPropertyAvailablePhysicalFormats: return UInt32(kSupportedSamplingRates.count) * sizeof(AudioStreamRangedDescription.self)
default:
return nil
}