ios: allow sound in silent mode (#3346)

Co-authored-by: Avently <avently@local>
This commit is contained in:
Stanislav Dmitrenko 2023-11-11 03:27:06 +08:00 committed by GitHub
parent 9cc232054c
commit ae286124aa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 41 additions and 1 deletions

View File

@ -61,6 +61,7 @@ class AudioRecorder {
await MainActor.run {
AppDelegate.keepScreenOn(false)
}
try? av.setCategory(AVAudioSession.Category.soloAmbient)
logger.error("AudioRecorder startAudioRecording error \(error.localizedDescription)")
return .error(error.localizedDescription)
}
@ -76,6 +77,7 @@ class AudioRecorder {
}
recordingTimer = nil
AppDelegate.keepScreenOn(false)
try? AVAudioSession.sharedInstance().setCategory(AVAudioSession.Category.soloAmbient)
}
private func checkPermission() async -> Bool {
@ -129,6 +131,9 @@ class AudioPlayer: NSObject, AVAudioPlayerDelegate {
AppDelegate.keepScreenOn(true)
guard let time = self.audioPlayer?.currentTime else { return }
self.onTimer?(time)
AudioPlayer.changeAudioSession(true)
} else {
AudioPlayer.changeAudioSession(false)
}
}
}
@ -157,6 +162,7 @@ class AudioPlayer: NSObject, AVAudioPlayerDelegate {
if let player = audioPlayer {
player.stop()
AppDelegate.keepScreenOn(false)
AudioPlayer.changeAudioSession(false)
}
audioPlayer = nil
if let timer = playbackTimer {
@ -165,6 +171,24 @@ class AudioPlayer: NSObject, AVAudioPlayerDelegate {
playbackTimer = nil
}
static func changeAudioSession(_ playback: Bool) {
// When there is a audio recording, setting any other category will disable sound
if AVAudioSession.sharedInstance().category == .playAndRecord {
return
}
if playback {
if AVAudioSession.sharedInstance().category != .playback {
logger.log("AudioSession: playback")
try? AVAudioSession.sharedInstance().setCategory(AVAudioSession.Category.playback, options: .duckOthers)
}
} else {
if AVAudioSession.sharedInstance().category != .soloAmbient {
logger.log("AudioSession: soloAmbient")
try? AVAudioSession.sharedInstance().setCategory(AVAudioSession.Category.soloAmbient)
}
}
}
func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {
stop()
self.onFinishPlayback?()

View File

@ -9,6 +9,7 @@
import SwiftUI
import AVKit
import SimpleXChat
import Combine
struct CIVideoView: View {
@EnvironmentObject var m: ChatModel
@ -28,6 +29,7 @@ struct CIVideoView: View {
@State private var showFullScreenPlayer = false
@State private var timeObserver: Any? = nil
@State private var fullScreenTimeObserver: Any? = nil
@State private var publisher: AnyCancellable? = nil
init(chatItem: ChatItem, image: String, duration: Int, maxWidth: CGFloat, videoWidth: Binding<CGFloat?>, scrollProxy: ScrollViewProxy?) {
self.chatItem = chatItem
@ -294,6 +296,14 @@ struct CIVideoView: View {
m.stopPreviousRecPlay = url
if let player = fullPlayer {
player.play()
var played = false
publisher = player.publisher(for: \.timeControlStatus).sink { status in
if played || status == .playing {
AppDelegate.keepScreenOn(status == .playing)
AudioPlayer.changeAudioSession(status == .playing)
}
played = status == .playing
}
fullScreenTimeObserver = NotificationCenter.default.addObserver(forName: .AVPlayerItemDidPlayToEndTime, object: player.currentItem, queue: .main) { _ in
player.seek(to: CMTime.zero)
player.play()
@ -308,6 +318,7 @@ struct CIVideoView: View {
fullScreenTimeObserver = nil
fullPlayer?.pause()
fullPlayer?.seek(to: CMTime.zero)
publisher?.cancel()
}
}
}

View File

@ -38,8 +38,13 @@ struct VideoPlayerView: UIViewRepresentable {
player.seek(to: CMTime.zero)
player.play()
}
var played = false
context.coordinator.publisher = player.publisher(for: \.timeControlStatus).sink { status in
AppDelegate.keepScreenOn(status == .playing)
if played || status == .playing {
AppDelegate.keepScreenOn(status == .playing)
AudioPlayer.changeAudioSession(status == .playing)
}
played = status == .playing
}
return controller.view
}