Skip to content

Commit 865c583

Browse files
committed
moved driver, workspace and shared code changes from Pro
1 parent 5908e44 commit 865c583

11 files changed

Lines changed: 166 additions & 70 deletions

File tree

native/driver/Driver.xcodeproj/project.pbxproj

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
7838E36726C9CFA10039D466 /* Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7838E36626C9CFA10039D466 /* Helpers.swift */; };
2121
784763FA26EF760B00CF9394 /* EQMClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = 784763F926EF760B00CF9394 /* EQMClient.swift */; };
2222
784763FD26EF764B00CF9394 /* VolumeConverter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 784763FC26EF764B00CF9394 /* VolumeConverter.swift */; };
23+
787E04EB26FF2D66003CD682 /* Mutex.swift in Sources */ = {isa = PBXBuildFile; fileRef = 787E04EA26FF2D66003CD682 /* Mutex.swift */; };
2324
78A8049E26C4866D0021981C /* EQMDriverBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = 78A8049D26C4866D0021981C /* EQMDriverBridge.m */; };
2425
78A804D726C4903E0021981C /* EQMDriver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 78A804D626C4903E0021981C /* EQMDriver.swift */; };
2526
78A804DD26C563860021981C /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 78A804DC26C563860021981C /* Constants.swift */; };
@@ -46,6 +47,7 @@
4647
7838E36626C9CFA10039D466 /* Helpers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Helpers.swift; sourceTree = "<group>"; };
4748
784763F926EF760B00CF9394 /* EQMClient.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = EQMClient.swift; path = ../shared/EQMClient.swift; sourceTree = "<group>"; };
4849
784763FC26EF764B00CF9394 /* VolumeConverter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = VolumeConverter.swift; path = ../shared/VolumeConverter.swift; sourceTree = "<group>"; };
50+
787E04EA26FF2D66003CD682 /* Mutex.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Mutex.swift; path = ../shared/Mutex.swift; sourceTree = "<group>"; };
4951
78A8049D26C4866D0021981C /* EQMDriverBridge.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = EQMDriverBridge.m; sourceTree = "<group>"; };
5052
78A804A026C486820021981C /* EQMDriverBridge.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = EQMDriverBridge.h; sourceTree = "<group>"; };
5153
78A804D526C4903E0021981C /* EQMDriver-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "EQMDriver-Bridging-Header.h"; sourceTree = "<group>"; };
@@ -123,6 +125,7 @@
123125
children = (
124126
7838E36326C9CC430039D466 /* ArrayExtensions.swift */,
125127
7838E34F26C897560039D466 /* AudioObjectPropertySelectorExtensions.swift */,
128+
787E04EA26FF2D66003CD682 /* Mutex.swift */,
126129
7838E35126C897560039D466 /* NumericTypesConversions.swift */,
127130
7838E34E26C897560039D466 /* SharedConstants.swift */,
128131
7838E35026C897560039D466 /* StringExtensions.swift */,
@@ -228,7 +231,7 @@
228231
7823A93C26D597F6004BABC6 /* ShellScript */ = {
229232
isa = PBXShellScriptBuildPhase;
230233
alwaysOutOfDate = 1;
231-
buildActionMask = 2147483647;
234+
buildActionMask = 12;
232235
files = (
233236
);
234237
inputFileListPaths = (
@@ -256,6 +259,7 @@
256259
784763FD26EF764B00CF9394 /* VolumeConverter.swift in Sources */,
257260
78A804D726C4903E0021981C /* EQMDriver.swift in Sources */,
258261
7838E36726C9CFA10039D466 /* Helpers.swift in Sources */,
262+
787E04EB26FF2D66003CD682 /* Mutex.swift in Sources */,
259263
7838E35426C897560039D466 /* StringExtensions.swift in Sources */,
260264
7838E35F26C8A4190039D466 /* Utilities.swift in Sources */,
261265
7838E35326C897560039D466 /* AudioObjectPropertySelectorExtensions.swift in Sources */,

native/driver/Source/Constants.swift

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,6 @@ let kDeviceModelUID = "EQMDeviceModelUID"
3434
let kDefaultSampleRate: Float64 = kEQMDeviceSupportedSampleRates[0]
3535
let kDefaultOutputVolume: Float32 = 1.0
3636

37-
let kMinVolumeDB: Float32 = -96
38-
let kMaxVolumeDB: Float32 = 0
39-
4037
extension HRESULT {
4138
// Success
4239
static let ok = HRESULT(bitPattern: 0x00000000)

native/driver/Source/EQMClients.swift

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,41 +10,55 @@ import Foundation
1010
import CoreAudio.AudioServerPlugIn
1111

1212
class EQMClients {
13+
private static let mutex = Mutex()
1314
static var clients: [UInt32: EQMClient] = [:]
1415

1516
static func add (_ client: EQMClient) {
17+
mutex.lock()
1618
clients[client.clientId] = client
19+
mutex.unlock()
1720
}
1821

1922
static func remove (_ client: EQMClient) {
23+
mutex.lock()
2024
clients.removeValue(forKey: client.clientId)
25+
mutex.unlock()
2126
}
2227

23-
static func get (by clientId: UInt32) -> EQMClient? {
24-
return clients[clientId]
28+
static func get (clientId: UInt32) -> EQMClient? {
29+
mutex.lock()
30+
let client = clients[clientId]
31+
mutex.unlock()
32+
return client
2533
}
2634

27-
static func get (by processId: pid_t) -> EQMClient? {
28-
return clients.values.first { $0.processId == processId }
35+
static func get (processId: pid_t) -> EQMClient? {
36+
mutex.lock()
37+
let client = clients.values.first { $0.processId == processId }
38+
mutex.unlock()
39+
return client
2940
}
3041

31-
static func get (by bundleId: String) -> [EQMClient] {
32-
return clients.values.filter { client in
42+
static func get (bundleId: String) -> [EQMClient] {
43+
mutex.lock()
44+
let matchingClients = clients.values.filter { client in
3345
return client.bundleId == bundleId
3446
}
47+
mutex.unlock()
48+
return matchingClients
3549
}
3650

37-
static func get (by client: EQMClient) -> EQMClient? {
38-
if let byClient = get(by: client.clientId) {
51+
static func get (client: EQMClient) -> EQMClient? {
52+
if let byClient = get(clientId: client.clientId) {
3953
return byClient
4054
}
4155

42-
if let byProcessId = get(by: client.processId) {
56+
if let byProcessId = get(processId: client.processId) {
4357
return byProcessId
4458
}
4559

4660
if let bundleId = client.bundleId {
47-
let bundles = get(by: bundleId)
61+
let bundles = get(bundleId: bundleId)
4862
return bundles[0]
4963
}
5064

native/driver/Source/EQMDevice.swift

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,10 @@ import CoreAudio.AudioServerPlugIn
1111
import Atomics
1212

1313
class EQMDevice: EQMObject {
14-
static let id = AudioObjectID(kDeviceUID)!
1514
static var name = kEQMDeviceDefaultName
1615
static var sampleRate = kDefaultSampleRate
1716
static var running = false
18-
static var shown = false
17+
static var shown = true
1918
static var latency: UInt32 = 0
2019
static var ioCounter = ManagedAtomic<UInt64>(0)
2120
static var anchorHostTime: UInt64 = 0
@@ -24,7 +23,7 @@ class EQMDevice: EQMObject {
2423
static let ioMutex = Mutex()
2524

2625
static let ringBufferSize: UInt32 = 16384
27-
static var ringBuffer = UnsafeMutablePointer<Float32>.allocate(capacity: Int(ringBufferSize * kChannelCount))
26+
static var ringBuffer = UnsafeMutablePointer<Float32>.allocate(capacity: Int(ringBufferSize * 4 * kChannelCount))
2827

2928
static func getDescription (for samplingRate: Float64) -> AudioStreamBasicDescription {
3029
return AudioStreamBasicDescription(
@@ -63,14 +62,14 @@ class EQMDevice: EQMObject {
6362
kAudioDevicePropertyIcon,
6463
kAudioDevicePropertyStreams,
6564
kAudioObjectPropertyCustomPropertyInfoList,
65+
kAudioDevicePropertyDeviceCanBeDefaultSystemDevice,
6666
EQMDeviceCustom.properties.shown,
6767
EQMDeviceCustom.properties.version,
6868
EQMDeviceCustom.properties.latency,
6969
EQMDeviceCustom.properties.name:
7070
return true
7171

7272
case kAudioDevicePropertyDeviceCanBeDefaultDevice,
73-
kAudioDevicePropertyDeviceCanBeDefaultSystemDevice,
7473
kAudioDevicePropertyLatency,
7574
kAudioDevicePropertySafetyOffset,
7675
kAudioDevicePropertyPreferredChannelsForStereo,
@@ -143,7 +142,8 @@ class EQMDevice: EQMObject {
143142
case kAudioDevicePropertyZeroTimeStampPeriod: return sizeof(UInt32.self)
144143
case kAudioDevicePropertyIcon: return sizeof(CFURL.self)
145144

146-
case kAudioObjectPropertyCustomPropertyInfoList: return sizeof(AudioServerPlugInCustomPropertyInfo.self) * EQMDeviceCustom.properties.count
145+
case kAudioObjectPropertyCustomPropertyInfoList:
146+
return sizeof(AudioServerPlugInCustomPropertyInfo.self) * EQMDeviceCustom.properties.count
147147
case EQMDeviceCustom.properties.latency: return sizeof(CFNumber.self)
148148
case EQMDeviceCustom.properties.shown: return sizeof(CFBoolean.self)
149149
case EQMDeviceCustom.properties.version: return sizeof(CFString.self)
@@ -261,7 +261,7 @@ class EQMDevice: EQMObject {
261261
// default device. This is the device that is used to play interface sounds and
262262
// other incidental or UI-related sounds on. Most devices should allow this
263263
// although devices with lots of latency may not want to.
264-
return .integer(shown ? 1 : 0)
264+
return .integer(1)
265265
case kAudioDevicePropertyLatency:
266266
// This property returns the presentation latency of the device. For this,
267267
// device, the value is 0 due to the fact that it always vends silence.
@@ -439,6 +439,22 @@ class EQMDevice: EQMObject {
439439
let shownRef = data.load(as: CFBoolean.self)
440440

441441
shown = CFBooleanGetValue(shownRef)
442+
443+
changedProperties.append(
444+
AudioObjectPropertyAddress(
445+
mSelector: kAudioDevicePropertyDeviceCanBeDefaultDevice,
446+
mScope: kAudioObjectPropertyScopeOutput,
447+
mElement: kAudioObjectPropertyElementMaster
448+
)
449+
)
450+
451+
changedProperties.append(
452+
AudioObjectPropertyAddress(
453+
mSelector: kAudioDevicePropertyDeviceCanBeDefaultSystemDevice,
454+
mScope: kAudioObjectPropertyScopeGlobal,
455+
mElement: kAudioObjectPropertyElementMaster
456+
)
457+
)
442458
return noErr
443459

444460
case EQMDeviceCustom.properties.latency:
@@ -452,6 +468,14 @@ class EQMDevice: EQMObject {
452468
if latency != newLatency {
453469
latency = UInt32(newLatency)
454470
}
471+
472+
changedProperties.append(
473+
AudioObjectPropertyAddress(
474+
mSelector: kAudioDevicePropertyLatency,
475+
mScope: kAudioObjectPropertyScopeOutput,
476+
mElement: kAudioObjectPropertyElementMaster
477+
)
478+
)
455479
return noErr
456480
case EQMDeviceCustom.properties.name:
457481
// Only allow eqMac app to set this property
@@ -493,7 +517,7 @@ class EQMDevice: EQMObject {
493517
timestampCount = 0
494518
anchorSampleTime = 0
495519
anchorHostTime = mach_absolute_time()
496-
ringBuffer = UnsafeMutablePointer<Float32>.allocate(capacity: Int(ringBufferSize * kChannelCount))
520+
ringBuffer = UnsafeMutablePointer<Float32>.allocate(capacity: Int(ringBufferSize * 4 * kChannelCount))
497521
} else {
498522
// IO already running so increment the counter
499523
ioCounter.wrappingIncrement(ordering: .relaxed)
@@ -548,7 +572,7 @@ class EQMDevice: EQMObject {
548572
return noErr
549573
}
550574

551-
static func doIO (clientID: UInt32, operationID: UInt32, sample: UnsafeMutablePointer<Float32>, cycleInfo: AudioServerPlugInIOCycleInfo, frameSize: UInt32) -> OSStatus {
575+
static func doIO (client: EQMClient?, operationID: UInt32, sample: UnsafeMutablePointer<Float32>, cycleInfo: AudioServerPlugInIOCycleInfo, frameSize: UInt32) -> OSStatus {
552576

553577
ioMutex.lock()
554578

@@ -597,7 +621,7 @@ class EQMDevice: EQMObject {
597621
}
598622

599623
// Clean up buffer
600-
let cleanFromFrame = sampleTime + Int(frame) - 16384
624+
let cleanFromFrame = sampleTime + Int(frame) - Int(ringBufferSize)
601625
let remainder = cleanFromFrame % Int(ringBufferSize)
602626
let cleanFrame = remainder * Int(kChannelCount) + Int(channel)
603627
ringBuffer[cleanFrame] = 0

native/driver/Source/EQMInterface.swift

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -107,9 +107,7 @@ func EQM_AddDeviceClient (inDriver: AudioServerPlugInDriverRef, inDeviceObjectID
107107
// successfully.
108108
guard EQMDriver.validateDriver(inDriver) else { return kAudioHardwareBadObjectError }
109109

110-
EQMDriver.mutex.lock()
111110
EQMClients.add(EQMClient(from: inClientInfo.pointee))
112-
EQMDriver.mutex.unlock()
113111

114112
return noErr
115113
}
@@ -121,9 +119,7 @@ func EQM_RemoveDeviceClient (inDriver: AudioServerPlugInDriverRef, inDeviceObjec
121119
// successfully.
122120
guard EQMDriver.validateDriver(inDriver) else { return kAudioHardwareBadObjectError }
123121

124-
EQMDriver.mutex.lock()
125122
EQMClients.remove(EQMClient(from: inClientInfo.pointee))
126-
EQMDriver.mutex.unlock()
127123

128124
return noErr
129125
}
@@ -321,7 +317,7 @@ func EQM_SetPropertyData (
321317
if let obj = EQMDriver.getEQMObject(from: inObjectID) {
322318
var changedProperties: [AudioObjectPropertyAddress] = []
323319
let status = obj.setPropertyData(
324-
client: EQMClients.get(by: inClientProcessID),
320+
client: EQMClients.get(processId: inClientProcessID),
325321
objectID: inObjectID,
326322
address: address,
327323
data: inData,
@@ -457,16 +453,14 @@ func EQM_DoIOOperation (
457453
// This is called to actuall perform a given operation.
458454
guard EQMDriver.validateDriver(inDriver) else { return kAudioHardwareBadObjectError }
459455

460-
guard inStreamObjectID == kObjectID_Stream_Input || inStreamObjectID == kObjectID_Stream_Output else {
461-
return kAudioHardwareBadObjectError
462-
}
463-
464456
guard let sample = ioMainBuffer?.assumingMemoryBound(to: Float32.self) else {
465457
return noErr
466458
}
467459

460+
let client = EQMClients.get(clientId: inClientID)
461+
468462
let status = EQMDevice.doIO(
469-
clientID: inClientID,
463+
client: client,
470464
operationID: inOperationID,
471465
sample: sample,
472466
cycleInfo: inIOCycleInfo.pointee,

native/driver/Source/EQMObject.swift

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,13 @@ enum EQMObjectProperty {
3030
case url(CFURL)
3131
case scope(AudioObjectPropertyScope)
3232
case element(AudioObjectPropertyElement)
33-
33+
case cfPropertyList(CFPropertyList)
34+
3435
// Structs
3536
case streamDescription(AudioStreamBasicDescription)
3637
case channelLayout(AudioChannelLayout)
3738
case valueRange(AudioValueRange)
38-
39+
3940
// Arrays
4041
case objectIDList(ContiguousArray<AudioObjectID>)
4142
case customPropertyInfoList(ContiguousArray<AudioServerPlugInCustomPropertyInfo>)
@@ -63,7 +64,9 @@ enum EQMObjectProperty {
6364
.audioClassID(let data),
6465
.audioObjectID(let data):
6566
return self.write(element: data, address: address, size: size, requestedSize: requestedSize)
66-
67+
case .cfPropertyList(let data):
68+
return self.write(element: data, address: address, size: size, requestedSize: requestedSize)
69+
6770
case .streamDescription(let data):
6871
return self.write(element: data, address: address, size: size, requestedSize: requestedSize)
6972
case .channelLayout(let data):
@@ -90,11 +93,10 @@ enum EQMObjectProperty {
9093
size.pointee = 0
9194
return noErr
9295
}
93-
9496
let outSize = sizeof(T.self)
9597

9698
guard requestedSize == outSize else {
97-
// log("​🚫​ Requested Size: \(requestedSize) != Out Size: \(outSize) (\(T.self))")
99+
log("​🚫​ Requested Size: \(requestedSize) != Out Size: \(outSize) (\(T.self))")
98100
return kAudioHardwareBadPropertySizeError
99101
}
100102

@@ -110,7 +112,7 @@ enum EQMObjectProperty {
110112

111113
let requestedCount = Int(requestedSize / elementSize)
112114
array = ContiguousArray(array[0..<requestedCount])
113-
// log("Data Count: \(arr.count) - Data Size: \(UInt32(arr.count) * elementSize) - Requested Size: \(requestedSize) - Resulting Count: \(array.count) - Resulting Size: \(UInt32(array.count) * elementSize)")
115+
log("Data Count: \(arr.count) - Data Size: \(UInt32(arr.count) * elementSize) - Requested Size: \(requestedSize) - Resulting Count: \(array.count) - Resulting Size: \(UInt32(array.count) * elementSize)")
114116

115117
let totalSize = UInt32(array.count) * elementSize
116118

native/driver/Source/Helpers.swift

Lines changed: 0 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -9,37 +9,6 @@
99
import Foundation
1010
import CoreAudio.AudioServerPlugIn
1111

12-
class Mutex {
13-
var mutex = pthread_mutex_t()
14-
15-
init () {
16-
var attributes = pthread_mutexattr_t()
17-
guard pthread_mutexattr_init(&attributes) == 0 else {
18-
preconditionFailure()
19-
}
20-
21-
pthread_mutexattr_settype(&attributes, PTHREAD_MUTEX_NORMAL)
22-
23-
guard pthread_mutex_init(&mutex, &attributes) == 0 else {
24-
preconditionFailure()
25-
}
26-
27-
pthread_mutexattr_destroy(&attributes)
28-
}
29-
30-
func lock () {
31-
pthread_mutex_lock(&mutex)
32-
}
33-
34-
func unlock () {
35-
pthread_mutex_unlock(&mutex)
36-
}
37-
38-
deinit {
39-
pthread_mutex_destroy(&mutex)
40-
}
41-
}
42-
4312
// MARK: - Pure Functions
4413
func log (_ msg: String) {
4514
if DEBUG {

native/eqMac.xcworkspace/xcshareddata/swiftpm/Package.resolved

Lines changed: 9 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)