mirror of
https://gitlab.linphone.org/BC/public/linphone-iphone.git
synced 2026-01-23 14:18:07 +00:00
Add AudioRouteUtils
This commit is contained in:
parent
8e6df8867a
commit
5b3176c031
2 changed files with 201 additions and 0 deletions
|
|
@ -9,6 +9,7 @@
|
|||
/* Begin PBXBuildFile section */
|
||||
66C491F92B24D25B00CEA16D /* ConfigExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66C491F82B24D25A00CEA16D /* ConfigExtension.swift */; };
|
||||
66C491FB2B24D32600CEA16D /* CoreExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66C491FA2B24D32600CEA16D /* CoreExtension.swift */; };
|
||||
66C491FD2B24D36500CEA16D /* AudioRouteUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66C491FC2B24D36500CEA16D /* AudioRouteUtils.swift */; };
|
||||
D706BA822ADD72D100278F45 /* DeviceRotationViewModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = D706BA812ADD72D100278F45 /* DeviceRotationViewModifier.swift */; };
|
||||
D70C93DE2AC2D0F60063CA3B /* Localizable.xcstrings in Resources */ = {isa = PBXBuildFile; fileRef = D70C93DD2AC2D0F60063CA3B /* Localizable.xcstrings */; };
|
||||
D717071E2AC5922E0037746F /* ColorExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D717071D2AC5922E0037746F /* ColorExtension.swift */; };
|
||||
|
|
@ -90,6 +91,7 @@
|
|||
/* Begin PBXFileReference section */
|
||||
66C491F82B24D25A00CEA16D /* ConfigExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConfigExtension.swift; sourceTree = "<group>"; };
|
||||
66C491FA2B24D32600CEA16D /* CoreExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoreExtension.swift; sourceTree = "<group>"; };
|
||||
66C491FC2B24D36500CEA16D /* AudioRouteUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioRouteUtils.swift; sourceTree = "<group>"; };
|
||||
D706BA812ADD72D100278F45 /* DeviceRotationViewModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeviceRotationViewModifier.swift; sourceTree = "<group>"; };
|
||||
D70C93DD2AC2D0F60063CA3B /* Localizable.xcstrings */ = {isa = PBXFileReference; lastKnownFileType = text.json.xcstrings; path = Localizable.xcstrings; sourceTree = "<group>"; };
|
||||
D717071D2AC5922E0037746F /* ColorExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorExtension.swift; sourceTree = "<group>"; };
|
||||
|
|
@ -204,6 +206,7 @@
|
|||
isa = PBXGroup;
|
||||
children = (
|
||||
66C491F72B24D25A00CEA16D /* Extensions */,
|
||||
66C491FC2B24D36500CEA16D /* AudioRouteUtils.swift */,
|
||||
D7ADF5FF2AFE356400212231 /* Avatar.swift */,
|
||||
D7C48DF32AFA66F900D938CB /* EditContactController.swift */,
|
||||
D7D1698B2AE66FA500109A5C /* MagicSearchSingleton.swift */,
|
||||
|
|
@ -593,6 +596,7 @@
|
|||
D706BA822ADD72D100278F45 /* DeviceRotationViewModifier.swift in Sources */,
|
||||
D732A9132B04C7A300DB42BA /* HistoryListFragment.swift in Sources */,
|
||||
D719ABC92ABC6FD700B41C10 /* CoreContext.swift in Sources */,
|
||||
66C491FD2B24D36500CEA16D /* AudioRouteUtils.swift in Sources */,
|
||||
D7EAACCF2AD6ED8000AA6A8A /* PermissionsFragment.swift in Sources */,
|
||||
D777DBB32AE12C5900565A99 /* ContactsManager.swift in Sources */,
|
||||
D796F2002B0BB61A0041115F /* ToastViewModel.swift in Sources */,
|
||||
|
|
|
|||
197
Linphone/Utils/AudioRouteUtils.swift
Normal file
197
Linphone/Utils/AudioRouteUtils.swift
Normal file
|
|
@ -0,0 +1,197 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2023 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of linphone-android
|
||||
* (see https://www.linphone.org).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
// swiftlint:disable line_length
|
||||
|
||||
import Foundation
|
||||
import AVFoundation
|
||||
import linphonesw
|
||||
|
||||
class AudioRouteUtils {
|
||||
|
||||
static private func applyAudioRouteChange( core: Core, call: Call?, types: [AudioDevice.Kind], output: Bool = true) {
|
||||
let typesNames = types.map { String(describing: $0) }.joined(separator: "/")
|
||||
|
||||
let currentCall = core.callsNb > 0 ? (call != nil) ? call : core.currentCall != nil ? core.currentCall : core.calls[0] : nil
|
||||
if currentCall == nil {
|
||||
print("[Audio Route Helper] No call found, setting audio route on Core")
|
||||
}
|
||||
let conference = call?.conference
|
||||
let capability = output ? AudioDevice.Capabilities.CapabilityPlay : AudioDevice.Capabilities.CapabilityRecord
|
||||
|
||||
var found = false
|
||||
|
||||
core.audioDevices.forEach { (audioDevice) in
|
||||
print("[Audio Route Helper] registered core audio devices are : [\(audioDevice.deviceName)] [\(audioDevice.type)] [\(audioDevice.capabilities)] ")
|
||||
}
|
||||
|
||||
core.audioDevices.forEach { (audioDevice) in
|
||||
if !found && types.contains(audioDevice.type) && audioDevice.hasCapability(capability: capability) {
|
||||
if conference != nil && conference?.isIn == true {
|
||||
print("[Audio Route Helper] Found [\(audioDevice.type)] \(output ? "playback" : "recorder") audio device [\(audioDevice.deviceName)], routing conference audio to it")
|
||||
if output {
|
||||
conference?.outputAudioDevice = audioDevice
|
||||
} else {
|
||||
conference?.inputAudioDevice = audioDevice
|
||||
}
|
||||
} else if currentCall != nil {
|
||||
print("[Audio Route Helper] Found [\(audioDevice.type)] \(output ? "playback" : "recorder") audio device [\(audioDevice.deviceName)], routing call audio to it")
|
||||
if output {
|
||||
currentCall?.outputAudioDevice = audioDevice
|
||||
} else {
|
||||
currentCall?.inputAudioDevice = audioDevice
|
||||
}
|
||||
} else {
|
||||
print("[Audio Route Helper] Found [\(audioDevice.type)] \(output ? "playback" : "recorder") audio device [\(audioDevice.deviceName)], changing core default audio device")
|
||||
if output {
|
||||
core.outputAudioDevice = audioDevice
|
||||
} else {
|
||||
core.inputAudioDevice = audioDevice
|
||||
}
|
||||
}
|
||||
found = true
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
print("[Audio Route Helper] Couldn't find \(typesNames) audio device")
|
||||
}
|
||||
}
|
||||
|
||||
static private func changeCaptureDeviceToMatchAudioRoute(core: Core, call: Call?, types: [AudioDevice.Kind]) {
|
||||
switch types.first {
|
||||
case .Bluetooth: if isBluetoothAudioRecorderAvailable(core: core) {
|
||||
print("[Audio Route Helper] Bluetooth device is able to record audio, also change input audio device")
|
||||
applyAudioRouteChange(core: core, call: call, types: [AudioDevice.Kind.Bluetooth], output: false)
|
||||
}
|
||||
case .Headset, .Headphones: if isHeadsetAudioRecorderAvailable(core: core) {
|
||||
print("[Audio Route Helper] Headphones/headset device is able to record audio, also change input audio device")
|
||||
applyAudioRouteChange(core: core, call: call, types: [AudioDevice.Kind.Headphones, AudioDevice.Kind.Headset], output: false)
|
||||
}
|
||||
default: applyAudioRouteChange(core: core, call: call, types: [AudioDevice.Kind.Microphone], output: false)
|
||||
}
|
||||
}
|
||||
|
||||
static private func routeAudioTo(core: Core, call: Call?, types: [AudioDevice.Kind]) {
|
||||
let currentCall = call != nil ? call : core.currentCall != nil ? core.currentCall : (core.callsNb > 0 ? core.calls[0] : nil)
|
||||
if call != nil || currentCall != nil {
|
||||
let callToUse = call != nil ? call : currentCall
|
||||
applyAudioRouteChange(core: core, call: callToUse, types: types)
|
||||
changeCaptureDeviceToMatchAudioRoute(core: core, call: callToUse, types: types)
|
||||
} else {
|
||||
applyAudioRouteChange(core: core, call: call, types: types)
|
||||
changeCaptureDeviceToMatchAudioRoute(core: core, call: call, types: types)
|
||||
}
|
||||
}
|
||||
|
||||
static func routeAudioToEarpiece(core: Core, call: Call? = nil) {
|
||||
routeAudioTo(core: core, call: call, types: [AudioDevice.Kind.Microphone]) // on iOS Earpiece = Microphone
|
||||
}
|
||||
|
||||
static func routeAudioToSpeaker(core: Core, call: Call? = nil) {
|
||||
routeAudioTo(core: core, call: call, types: [AudioDevice.Kind.Speaker])
|
||||
}
|
||||
|
||||
static func routeAudioToSpeaker(core: Core) {
|
||||
routeAudioTo(core: core, call: nil, types: [AudioDevice.Kind.Speaker])
|
||||
}
|
||||
|
||||
static func routeAudioToBluetooth(core: Core, call: Call? = nil) {
|
||||
routeAudioTo(core: core, call: call, types: [AudioDevice.Kind.Bluetooth])
|
||||
}
|
||||
|
||||
static func routeAudioToHeadset(core: Core, call: Call? = nil) {
|
||||
routeAudioTo(core: core, call: call, types: [AudioDevice.Kind.Headphones, AudioDevice.Kind.Headset])
|
||||
}
|
||||
|
||||
static func isSpeakerAudioRouteCurrentlyUsed(core: Core, call: Call? = nil) -> Bool {
|
||||
|
||||
let currentCall = core.callsNb > 0 ? (call != nil) ? call : core.currentCall != nil ? core.currentCall : core.calls[0] : nil
|
||||
if currentCall == nil {
|
||||
print("[Audio Route Helper] No call found, setting audio route on Core")
|
||||
}
|
||||
|
||||
let conference = core.conference
|
||||
let audioDevice = conference != nil && conference?.isIn == true ? conference!.outputAudioDevice : currentCall != nil ? currentCall!.outputAudioDevice : core.outputAudioDevice
|
||||
print("[Audio Route Helper] Playback audio currently in use is [\(audioDevice?.deviceName ?? "n/a")] with type (\(audioDevice?.type ?? .Unknown)")
|
||||
return audioDevice?.type == AudioDevice.Kind.Speaker
|
||||
}
|
||||
|
||||
static func isBluetoothAudioRouteCurrentlyUsed(core: Core, call: Call? = nil) -> Bool {
|
||||
if core.callsNb == 0 {
|
||||
print("[Audio Route Helper] No call found, so bluetooth audio route isn't used")
|
||||
return false
|
||||
}
|
||||
let currentCall = call != nil ? call : core.currentCall != nil ? core.currentCall : core.calls[0]
|
||||
let conference = core.conference
|
||||
|
||||
let audioDevice = conference != nil && conference?.isIn == true ? conference!.outputAudioDevice : currentCall?.outputAudioDevice
|
||||
print("[Audio Route Helper] Playback audio device currently in use is [\(audioDevice?.deviceName ?? "n/a")] with type (\(audioDevice?.type ?? .Unknown)")
|
||||
return audioDevice?.type == AudioDevice.Kind.Bluetooth
|
||||
}
|
||||
|
||||
static func isBluetoothAudioRouteAvailable(core: Core) -> Bool {
|
||||
if let device = core.audioDevices.first(where: { $0.type == AudioDevice.Kind.Bluetooth && $0.hasCapability(capability: .CapabilityPlay) }) {
|
||||
print("[Audio Route Helper] Found bluetooth audio device [\(device.deviceName)]")
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
static private func isBluetoothAudioRecorderAvailable(core: Core) -> Bool {
|
||||
if let device = core.audioDevices.first(where: { $0.type == AudioDevice.Kind.Bluetooth && $0.hasCapability(capability: .CapabilityRecord) }) {
|
||||
print("[Audio Route Helper] Found bluetooth audio recorder [\(device.deviceName)]")
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
static func isHeadsetAudioRouteAvailable(core: Core) -> Bool {
|
||||
if let device = core.audioDevices.first(where: { ($0.type == AudioDevice.Kind.Headset||$0.type == AudioDevice.Kind.Headphones) && $0.hasCapability(capability: .CapabilityPlay) }) {
|
||||
print("[Audio Route Helper] Found headset/headphones audio device [\(device.deviceName)]")
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
static private func isHeadsetAudioRecorderAvailable(core: Core) -> Bool {
|
||||
if let device = core.audioDevices.first(where: { ($0.type == AudioDevice.Kind.Headset||$0.type == AudioDevice.Kind.Headphones) && $0.hasCapability(capability: .CapabilityRecord) }) {
|
||||
print("[Audio Route Helper] Found headset/headphones audio recorder [\(device.deviceName)]")
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
static func isReceiverEnabled(core: Core) -> Bool {
|
||||
if let outputDevice = core.outputAudioDevice {
|
||||
return outputDevice.type == AudioDevice.Kind.Microphone
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
static func isBluetoothAvailable(core: Core) -> Bool {
|
||||
for device in core.audioDevices {
|
||||
if device.type == AudioDevice.Kind.Bluetooth || device.type == AudioDevice.Kind.BluetoothA2DP {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
}
|
||||
// swiftlint:enable line_length
|
||||
Loading…
Add table
Reference in a new issue