201 lines
6.6 KiB
Swift
201 lines
6.6 KiB
Swift
//
|
|
// CallingBellFeature.swift
|
|
// TUICallKit
|
|
//
|
|
// Created by vincepzhang on 2022/12/30.
|
|
//
|
|
|
|
import Foundation
|
|
import AVFAudio
|
|
import TUICallEngine
|
|
|
|
#if canImport(TXLiteAVSDK_TRTC)
|
|
import TXLiteAVSDK_TRTC
|
|
#elseif canImport(TXLiteAVSDK_Professional)
|
|
import TXLiteAVSDK_Professional
|
|
#endif
|
|
|
|
let CALLKIT_AUDIO_DIAL_ID: Int32 = 48
|
|
|
|
class CallingBellFeature: NSObject, AVAudioPlayerDelegate {
|
|
|
|
enum CallingBellType {
|
|
case CallingBellTypeHangup
|
|
case CallingBellTypeCalled
|
|
case CallingBellTypeDial
|
|
}
|
|
|
|
var player: AVAudioPlayer?
|
|
var loop: Bool = true
|
|
private var needPlayRingtone: Bool = false
|
|
let selfUserCallStatusObserver = Observer()
|
|
|
|
override init() {
|
|
super.init()
|
|
registerNotifications()
|
|
registerObserveState()
|
|
}
|
|
|
|
deinit {
|
|
NotificationCenter.default.removeObserver(self)
|
|
TUICallState.instance.selfUser.value.callStatus.removeObserver(selfUserCallStatusObserver)
|
|
}
|
|
|
|
func registerObserveState() {
|
|
TUICallState.instance.selfUser.value.callStatus.addObserver(selfUserCallStatusObserver, closure: { newValue, _ in
|
|
let callStatus = TUICallState.instance.selfUser.value.callStatus.value
|
|
let callRole = TUICallState.instance.selfUser.value.callRole.value
|
|
|
|
if callStatus == TUICallStatus.waiting {
|
|
if callRole == TUICallRole.called {
|
|
self.startMusicBasedOnAppState(type: .CallingBellTypeCalled)
|
|
} else if callRole == TUICallRole.call {
|
|
self.startPlayMusic(type: .CallingBellTypeDial)
|
|
}
|
|
} else {
|
|
self.stopPlayMusic()
|
|
}
|
|
})
|
|
}
|
|
|
|
func startMusicBasedOnAppState(type: CallingBellType) {
|
|
if UIApplication.shared.applicationState != .background {
|
|
self.setAudioSessionWith(category: .soloAmbient)
|
|
self.startPlayMusic(type: type)
|
|
} else {
|
|
self.needPlayRingtone = true;
|
|
}
|
|
}
|
|
|
|
func registerNotifications() {
|
|
if #available(iOS 13.0, *) {
|
|
NotificationCenter.default.addObserver(self, selector: #selector(appDidBecomeActive),
|
|
name: UIScene.didActivateNotification,
|
|
object: nil)
|
|
} else {
|
|
NotificationCenter.default.addObserver(self, selector: #selector(appDidBecomeActive),
|
|
name: UIApplication.didBecomeActiveNotification,
|
|
object: nil)
|
|
}
|
|
}
|
|
|
|
@objc func appDidBecomeActive() {
|
|
if needPlayRingtone {
|
|
let _ = startPlayMusic(type: .CallingBellTypeCalled)
|
|
needPlayRingtone = false;
|
|
}
|
|
}
|
|
|
|
func startPlayMusic(type: CallingBellType) {
|
|
guard let bundle = TUICallKitCommon.getTUICallKitBundle() else { return }
|
|
switch type {
|
|
case .CallingBellTypeHangup:
|
|
let path = bundle.bundlePath + "/AudioFile" + "/phone_hangup.mp3"
|
|
let url = URL(fileURLWithPath: path)
|
|
return startPlayMusicBySystemPlayer(url: url, loop: false)
|
|
case .CallingBellTypeCalled:
|
|
if TUICallState.instance.enableMuteMode {
|
|
return
|
|
}
|
|
var path = bundle.bundlePath + "/AudioFile" + "/phone_ringing.mp3"
|
|
|
|
|
|
if let value = UserDefaults.standard.object(forKey: TUI_CALLING_BELL_KEY) as? String {
|
|
path = value
|
|
}
|
|
|
|
let url = URL(fileURLWithPath: path)
|
|
return startPlayMusicBySystemPlayer(url: url)
|
|
case .CallingBellTypeDial:
|
|
let path = bundle.bundlePath + "/AudioFile" + "/phone_dialing.m4a"
|
|
startPlayMusicByTRTCPlayer(path: path, id: CALLKIT_AUDIO_DIAL_ID)
|
|
return
|
|
}
|
|
}
|
|
|
|
func stopPlayMusic() {
|
|
setAudioSessionWith(category: .playAndRecord)
|
|
|
|
if TUICallState.instance.selfUser.value.callRole.value == .call {
|
|
stopPlayMusicByTRTCPlayer(id: CALLKIT_AUDIO_DIAL_ID)
|
|
return
|
|
}
|
|
stopPlayMusicBySystemPlayer()
|
|
needPlayRingtone = false;
|
|
}
|
|
|
|
// MARK: TRTC Audio Player
|
|
private func startPlayMusicByTRTCPlayer(path: String, id: Int32) {
|
|
let audioDevice: TUIAudioPlaybackDevice = TUICallState.instance.mediaType.value == .audio ? .earpiece : .speakerphone
|
|
CallEngineManager.instance.setAudioPlaybackDevice(device: audioDevice)
|
|
|
|
let param = TXAudioMusicParam()
|
|
param.id = id
|
|
param.isShortFile = true
|
|
param.path = path
|
|
|
|
let audioEffectManager = TUICallEngine.createInstance().getTRTCCloudInstance().getAudioEffectManager()
|
|
audioEffectManager.startPlayMusic(param, onStart: nil, onProgress: nil)
|
|
audioEffectManager.setMusicPlayoutVolume(id, volume: 100)
|
|
}
|
|
|
|
private func stopPlayMusicByTRTCPlayer(id: Int32) {
|
|
let audioEffectManager = TUICallEngine.createInstance().getTRTCCloudInstance().getAudioEffectManager()
|
|
audioEffectManager.stopPlayMusic(id)
|
|
}
|
|
|
|
// MARK: System AVAudio Player
|
|
private func startPlayMusicBySystemPlayer(url: URL, loop: Bool = true) {
|
|
self.loop = loop
|
|
|
|
if player != nil {
|
|
stopPlayMusicBySystemPlayer()
|
|
}
|
|
|
|
do {
|
|
player = try AVAudioPlayer(contentsOf: url)
|
|
} catch let error as NSError {
|
|
print("Error: \(error.localizedDescription)")
|
|
return
|
|
}
|
|
|
|
guard let prepare = player?.prepareToPlay(), prepare else {
|
|
return
|
|
}
|
|
|
|
player?.delegate = self
|
|
player?.play()
|
|
}
|
|
|
|
private func stopPlayMusicBySystemPlayer() {
|
|
player?.stop()
|
|
player = nil
|
|
}
|
|
|
|
// MARK: AVAudioPlayerDelegate
|
|
func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {
|
|
if loop {
|
|
player.play()
|
|
} else {
|
|
stopPlayMusicBySystemPlayer()
|
|
}
|
|
}
|
|
|
|
func audioPlayerDecodeErrorDidOccur(_ player: AVAudioPlayer, error: Error?) {
|
|
if error != nil {
|
|
stopPlayMusicBySystemPlayer()
|
|
}
|
|
}
|
|
|
|
private func setAudioSessionWith(category: AVAudioSession.Category) {
|
|
let audioSession = AVAudioSession.sharedInstance()
|
|
do {
|
|
try audioSession.setCategory(category, options: [.allowBluetooth, .allowBluetoothA2DP, .mixWithOthers])
|
|
try audioSession.setActive(true)
|
|
} catch {
|
|
print("Error setting up audio session: \(error)")
|
|
}
|
|
}
|
|
|
|
}
|