mirror of https://github.com/oxen-io/session-ios
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
84 lines
3.1 KiB
Swift
84 lines
3.1 KiB
Swift
//
|
|
// Copyright (c) 2020 Open Whisper Systems. All rights reserved.
|
|
//
|
|
|
|
import Foundation
|
|
import AVFoundation
|
|
|
|
public struct AudioSource: Hashable {
|
|
|
|
public let localizedName: String
|
|
public let portDescription: AVAudioSessionPortDescription?
|
|
|
|
// The built-in loud speaker / aka speakerphone
|
|
public let isBuiltInSpeaker: Bool
|
|
|
|
// The built-in quiet speaker, aka the normal phone handset receiver earpiece
|
|
public let isBuiltInEarPiece: Bool
|
|
|
|
public init(localizedName: String, isBuiltInSpeaker: Bool, isBuiltInEarPiece: Bool, portDescription: AVAudioSessionPortDescription? = nil) {
|
|
self.localizedName = localizedName
|
|
self.isBuiltInSpeaker = isBuiltInSpeaker
|
|
self.isBuiltInEarPiece = isBuiltInEarPiece
|
|
self.portDescription = portDescription
|
|
}
|
|
|
|
public init(portDescription: AVAudioSessionPortDescription) {
|
|
|
|
let isBuiltInEarPiece = portDescription.portType == AVAudioSession.Port.builtInMic
|
|
|
|
// portDescription.portName works well for BT linked devices, but if we are using
|
|
// the built in mic, we have "iPhone Microphone" which is a little awkward.
|
|
// In that case, instead we prefer just the model name e.g. "iPhone" or "iPad"
|
|
let localizedName = isBuiltInEarPiece ? UIDevice.current.localizedModel : portDescription.portName
|
|
|
|
self.init(localizedName: localizedName,
|
|
isBuiltInSpeaker: false,
|
|
isBuiltInEarPiece: isBuiltInEarPiece,
|
|
portDescription: portDescription)
|
|
}
|
|
|
|
// Speakerphone is handled separately from the other audio routes as it doesn't appear as an "input"
|
|
public static var builtInSpeaker: AudioSource {
|
|
return self.init(localizedName: NSLocalizedString("AUDIO_ROUTE_BUILT_IN_SPEAKER", comment: "action sheet button title to enable built in speaker during a call"),
|
|
isBuiltInSpeaker: true,
|
|
isBuiltInEarPiece: false)
|
|
}
|
|
|
|
// MARK: Hashable
|
|
|
|
public static func ==(lhs: AudioSource, rhs: AudioSource) -> Bool {
|
|
// Simply comparing the `portDescription` vs the `portDescription.uid`
|
|
// caused multiple instances of the built in mic to turn up in a set.
|
|
if lhs.isBuiltInSpeaker && rhs.isBuiltInSpeaker {
|
|
return true
|
|
}
|
|
|
|
if lhs.isBuiltInSpeaker || rhs.isBuiltInSpeaker {
|
|
return false
|
|
}
|
|
|
|
guard let lhsPortDescription = lhs.portDescription else {
|
|
owsFailDebug("only the built in speaker should lack a port description")
|
|
return false
|
|
}
|
|
|
|
guard let rhsPortDescription = rhs.portDescription else {
|
|
owsFailDebug("only the built in speaker should lack a port description")
|
|
return false
|
|
}
|
|
|
|
return lhsPortDescription.uid == rhsPortDescription.uid
|
|
}
|
|
|
|
public func hash(into hasher: inout Hasher) {
|
|
guard let portDescription = self.portDescription else {
|
|
assert(self.isBuiltInSpeaker)
|
|
hasher.combine("Built In Speaker")
|
|
return
|
|
}
|
|
|
|
hasher.combine(portDescription.uid)
|
|
}
|
|
}
|