public func push(audioSessionType: ManagedAudioSessionType, outputMode: AudioSessionOutputMode = .system, once: Bool = false, manualActivate: @escaping (ManagedAudioSessionControl) -> Void, deactivate: @escaping () -> Signal<Void, NoError>, headsetConnectionStatusChanged: @escaping (Bool) -> Void = { _ in }, availableOutputsChanged: @escaping ([AudioSessionOutput], AudioSessionOutput?) -> Void = { _, _ in }) -> Disposable {
let id = OSAtomicIncrement32(&self.nextId)
let queue = self.queue
queue.async {
self.holders.append(HolderRecord(id: id, audioSessionType: audioSessionType, control: ManagedAudioSessionControl(setupImpl: { [weak self] synchronous in
let f: () -> Void = {
if let strongSelf = self {
for holder in strongSelf.holders {
if holder.id == id && holder.active {
strongSelf.setup(type: audioSessionType, outputMode: holder.outputMode, activateNow: false)
break
}
}
}
}
if synchronous {
queue.sync(f)
} else {
queue.async(f)
}
}, activateImpl: { [weak self] completion in
if let strongSelf = self {
strongSelf.queue.async {
for holder in strongSelf.holders {
if holder.id == id && holder.active {
strongSelf.activate()
completion.f(AudioSessionActivationState(isHeadsetConnected: strongSelf.isHeadsetPluggedInValue))
break
}
}
}
}
}, setOutputModeImpl: { [weak self] value in
if let strongSelf = self {
strongSelf.queue.async {
for holder in strongSelf.holders {
if holder.id == id {
if holder.outputMode != value {
holder.outputMode = value
}
if holder.active {
strongSelf.updateOutputMode(value)
}
}
}
}
}
}, setupAndActivateImpl: { [weak self] synchronous, completion in
queue.async {
let f: () -> Void = {
if let strongSelf = self {
for holder in strongSelf.holders {
if holder.id == id && holder.active {
strongSelf.setup(type: audioSessionType, outputMode: holder.outputMode, activateNow: true)
completion.f(AudioSessionActivationState(isHeadsetConnected: strongSelf.isHeadsetPluggedInValue))
break
}
}
}
}
if synchronous {
queue.sync(f)
} else {
queue.async(f)
}
}
}), activate: { [weak self] state in
manualActivate(state)
queue.async {
if let strongSelf = self {
strongSelf.updateCurrentAudioRouteInfo()
availableOutputsChanged(strongSelf.availableOutputsValue, strongSelf.currentOutputValue)
}
}
}, deactivate: deactivate, headsetConnectionStatusChanged: headsetConnectionStatusChanged, availableOutputsChanged: availableOutputsChanged, once: once, outputMode: outputMode))
self.updateHolders()
}
return ActionDisposable { [weak self] in
if let strongSelf = self {
strongSelf.queue.async {
strongSelf.removeDeactivatedHolder(id: id)
}
}
}
}
class
HolderRecord
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
let id: Int32
let audioSessionType: ManagedAudioSessionType
let control: ManagedAudioSessionControl
let activate: (ManagedAudioSessionControl) -> Void
let deactivate: () -> Signal<Void, NoError>
let headsetConnectionStatusChanged: (Bool) -> Void
let availableOutputsChanged: ([AudioSessionOutput], AudioSessionOutput?) -> Void
let once: Bool
var outputMode: AudioSessionOutputMode
var active: Bool = false
var deactivatingDisposable: Disposable? = nil
init(id: Int32, audioSessionType: ManagedAudioSessionType, control: ManagedAudioSessionControl, activate: @escaping (ManagedAudioSessionControl) -> Void, deactivate: @escaping () -> Signal<Void, NoError>, headsetConnectionStatusChanged: @escaping (Bool) -> Void, availableOutputsChanged: @escaping ([AudioSessionOutput], AudioSessionOutput?) -> Void, once: Bool, outputMode: AudioSessionOutputMode) {
self.id = id
self.audioSessionType = audioSessionType
self.control = control
self.activate = activate
self.deactivate = deactivate
self.headsetConnectionStatusChanged = headsetConnectionStatusChanged
self.availableOutputsChanged = availableOutputsChanged
self.once = once
self.outputMode = outputMode
}