mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-07-31 15:37:01 +00:00
Animated emoji sounds improvements
This commit is contained in:
parent
24e18d6f7a
commit
fb809af412
@ -111,6 +111,7 @@ private final class MediaPlayerContext {
|
||||
private var baseRate: Double
|
||||
private let fetchAutomatically: Bool
|
||||
private var playAndRecord: Bool
|
||||
private var ambient: Bool
|
||||
private var keepAudioSessionWhilePaused: Bool
|
||||
private var continuePlayingWithoutSoundOnLostAudioSession: Bool
|
||||
|
||||
@ -132,7 +133,7 @@ private final class MediaPlayerContext {
|
||||
|
||||
private var stoppedAtEnd = false
|
||||
|
||||
init(queue: Queue, audioSessionManager: ManagedAudioSession, playerStatus: Promise<MediaPlayerStatus>, audioLevelPipe: ValuePipe<Float>, postbox: Postbox, resourceReference: MediaResourceReference, tempFilePath: String?, streamable: MediaPlayerStreaming, video: Bool, preferSoftwareDecoding: Bool, playAutomatically: Bool, enableSound: Bool, baseRate: Double, fetchAutomatically: Bool, playAndRecord: Bool, keepAudioSessionWhilePaused: Bool, continuePlayingWithoutSoundOnLostAudioSession: Bool) {
|
||||
init(queue: Queue, audioSessionManager: ManagedAudioSession, playerStatus: Promise<MediaPlayerStatus>, audioLevelPipe: ValuePipe<Float>, postbox: Postbox, resourceReference: MediaResourceReference, tempFilePath: String?, streamable: MediaPlayerStreaming, video: Bool, preferSoftwareDecoding: Bool, playAutomatically: Bool, enableSound: Bool, baseRate: Double, fetchAutomatically: Bool, playAndRecord: Bool, ambient: Bool, keepAudioSessionWhilePaused: Bool, continuePlayingWithoutSoundOnLostAudioSession: Bool) {
|
||||
assert(queue.isCurrent())
|
||||
|
||||
self.queue = queue
|
||||
@ -149,6 +150,7 @@ private final class MediaPlayerContext {
|
||||
self.baseRate = baseRate
|
||||
self.fetchAutomatically = fetchAutomatically
|
||||
self.playAndRecord = playAndRecord
|
||||
self.ambient = ambient
|
||||
self.keepAudioSessionWhilePaused = keepAudioSessionWhilePaused
|
||||
self.continuePlayingWithoutSoundOnLostAudioSession = continuePlayingWithoutSoundOnLostAudioSession
|
||||
|
||||
@ -368,7 +370,7 @@ private final class MediaPlayerContext {
|
||||
self.audioRenderer = nil
|
||||
|
||||
let queue = self.queue
|
||||
renderer = MediaPlayerAudioRenderer(audioSession: .manager(self.audioSessionManager), playAndRecord: self.playAndRecord, forceAudioToSpeaker: self.forceAudioToSpeaker, baseRate: self.baseRate, audioLevelPipe: self.audioLevelPipe, updatedRate: { [weak self] in
|
||||
renderer = MediaPlayerAudioRenderer(audioSession: .manager(self.audioSessionManager), playAndRecord: self.playAndRecord, ambient: self.ambient, forceAudioToSpeaker: self.forceAudioToSpeaker, baseRate: self.baseRate, audioLevelPipe: self.audioLevelPipe, updatedRate: { [weak self] in
|
||||
queue.async {
|
||||
if let strongSelf = self {
|
||||
strongSelf.tick()
|
||||
@ -446,7 +448,7 @@ private final class MediaPlayerContext {
|
||||
self.lastStatusUpdateTimestamp = nil
|
||||
if self.enableSound {
|
||||
let queue = self.queue
|
||||
let renderer = MediaPlayerAudioRenderer(audioSession: .manager(self.audioSessionManager), playAndRecord: self.playAndRecord, forceAudioToSpeaker: self.forceAudioToSpeaker, baseRate: self.baseRate, audioLevelPipe: self.audioLevelPipe, updatedRate: { [weak self] in
|
||||
let renderer = MediaPlayerAudioRenderer(audioSession: .manager(self.audioSessionManager), playAndRecord: self.playAndRecord, ambient: self.ambient, forceAudioToSpeaker: self.forceAudioToSpeaker, baseRate: self.baseRate, audioLevelPipe: self.audioLevelPipe, updatedRate: { [weak self] in
|
||||
queue.async {
|
||||
if let strongSelf = self {
|
||||
strongSelf.tick()
|
||||
@ -998,10 +1000,10 @@ public final class MediaPlayer {
|
||||
}
|
||||
}
|
||||
|
||||
public init(audioSessionManager: ManagedAudioSession, postbox: Postbox, resourceReference: MediaResourceReference, tempFilePath: String? = nil, streamable: MediaPlayerStreaming, video: Bool, preferSoftwareDecoding: Bool, playAutomatically: Bool = false, enableSound: Bool, baseRate: Double = 1.0, fetchAutomatically: Bool, playAndRecord: Bool = false, keepAudioSessionWhilePaused: Bool = false, continuePlayingWithoutSoundOnLostAudioSession: Bool = false) {
|
||||
public init(audioSessionManager: ManagedAudioSession, postbox: Postbox, resourceReference: MediaResourceReference, tempFilePath: String? = nil, streamable: MediaPlayerStreaming, video: Bool, preferSoftwareDecoding: Bool, playAutomatically: Bool = false, enableSound: Bool, baseRate: Double = 1.0, fetchAutomatically: Bool, playAndRecord: Bool = false, ambient: Bool = false, keepAudioSessionWhilePaused: Bool = false, continuePlayingWithoutSoundOnLostAudioSession: Bool = false) {
|
||||
let audioLevelPipe = self.audioLevelPipe
|
||||
self.queue.async {
|
||||
let context = MediaPlayerContext(queue: self.queue, audioSessionManager: audioSessionManager, playerStatus: self.statusValue, audioLevelPipe: audioLevelPipe, postbox: postbox, resourceReference: resourceReference, tempFilePath: tempFilePath, streamable: streamable, video: video, preferSoftwareDecoding: preferSoftwareDecoding, playAutomatically: playAutomatically, enableSound: enableSound, baseRate: baseRate, fetchAutomatically: fetchAutomatically, playAndRecord: playAndRecord, keepAudioSessionWhilePaused: keepAudioSessionWhilePaused, continuePlayingWithoutSoundOnLostAudioSession: continuePlayingWithoutSoundOnLostAudioSession)
|
||||
let context = MediaPlayerContext(queue: self.queue, audioSessionManager: audioSessionManager, playerStatus: self.statusValue, audioLevelPipe: audioLevelPipe, postbox: postbox, resourceReference: resourceReference, tempFilePath: tempFilePath, streamable: streamable, video: video, preferSoftwareDecoding: preferSoftwareDecoding, playAutomatically: playAutomatically, enableSound: enableSound, baseRate: baseRate, fetchAutomatically: fetchAutomatically, playAndRecord: playAndRecord, ambient: ambient, keepAudioSessionWhilePaused: keepAudioSessionWhilePaused, continuePlayingWithoutSoundOnLostAudioSession: continuePlayingWithoutSoundOnLostAudioSession)
|
||||
self.contextRef = Unmanaged.passRetained(context)
|
||||
}
|
||||
}
|
||||
|
@ -239,6 +239,7 @@ private final class AudioPlayerRendererContext {
|
||||
let audioSessionDisposable = MetaDisposable()
|
||||
var audioSessionControl: ManagedAudioSessionControl?
|
||||
let playAndRecord: Bool
|
||||
let ambient: Bool
|
||||
var forceAudioToSpeaker: Bool {
|
||||
didSet {
|
||||
if self.forceAudioToSpeaker != oldValue {
|
||||
@ -249,7 +250,7 @@ private final class AudioPlayerRendererContext {
|
||||
}
|
||||
}
|
||||
|
||||
init(controlTimebase: CMTimebase, audioSession: MediaPlayerAudioSessionControl, playAndRecord: Bool, forceAudioToSpeaker: Bool, baseRate: Double, audioLevelPipe: ValuePipe<Float>, updatedRate: @escaping () -> Void, audioPaused: @escaping () -> Void) {
|
||||
init(controlTimebase: CMTimebase, audioSession: MediaPlayerAudioSessionControl, playAndRecord: Bool, ambient: Bool, forceAudioToSpeaker: Bool, baseRate: Double, audioLevelPipe: ValuePipe<Float>, updatedRate: @escaping () -> Void, audioPaused: @escaping () -> Void) {
|
||||
assert(audioPlayerRendererQueue.isCurrent())
|
||||
|
||||
self.audioSession = audioSession
|
||||
@ -262,6 +263,7 @@ private final class AudioPlayerRendererContext {
|
||||
self.audioPaused = audioPaused
|
||||
|
||||
self.playAndRecord = playAndRecord
|
||||
self.ambient = ambient
|
||||
|
||||
self.audioStreamDescription = audioRendererNativeStreamDescription()
|
||||
|
||||
@ -481,7 +483,7 @@ private final class AudioPlayerRendererContext {
|
||||
|
||||
switch self.audioSession {
|
||||
case let .manager(manager):
|
||||
self.audioSessionDisposable.set(manager.push(audioSessionType: self.playAndRecord ? .playWithPossiblePortOverride : .play, outputMode: self.forceAudioToSpeaker ? .speakerIfNoHeadphones : .system, once: true, manualActivate: { [weak self] control in
|
||||
self.audioSessionDisposable.set(manager.push(audioSessionType: self.ambient ? .ambient : (self.playAndRecord ? .playWithPossiblePortOverride : .play), outputMode: self.forceAudioToSpeaker ? .speakerIfNoHeadphones : .system, once: true, manualActivate: { [weak self] control in
|
||||
audioPlayerRendererQueue.async {
|
||||
if let strongSelf = self {
|
||||
strongSelf.audioSessionControl = control
|
||||
@ -751,7 +753,7 @@ public final class MediaPlayerAudioRenderer {
|
||||
private let audioClock: CMClock
|
||||
public let audioTimebase: CMTimebase
|
||||
|
||||
public init(audioSession: MediaPlayerAudioSessionControl, playAndRecord: Bool, forceAudioToSpeaker: Bool, baseRate: Double, audioLevelPipe: ValuePipe<Float>, updatedRate: @escaping () -> Void, audioPaused: @escaping () -> Void) {
|
||||
public init(audioSession: MediaPlayerAudioSessionControl, playAndRecord: Bool, ambient: Bool, forceAudioToSpeaker: Bool, baseRate: Double, audioLevelPipe: ValuePipe<Float>, updatedRate: @escaping () -> Void, audioPaused: @escaping () -> Void) {
|
||||
var audioClock: CMClock?
|
||||
CMAudioClockCreate(allocator: nil, clockOut: &audioClock)
|
||||
if audioClock == nil {
|
||||
@ -764,7 +766,7 @@ public final class MediaPlayerAudioRenderer {
|
||||
self.audioTimebase = audioTimebase!
|
||||
|
||||
audioPlayerRendererQueue.async {
|
||||
let context = AudioPlayerRendererContext(controlTimebase: audioTimebase!, audioSession: audioSession, playAndRecord: playAndRecord, forceAudioToSpeaker: forceAudioToSpeaker, baseRate: baseRate, audioLevelPipe: audioLevelPipe, updatedRate: updatedRate, audioPaused: audioPaused)
|
||||
let context = AudioPlayerRendererContext(controlTimebase: audioTimebase!, audioSession: audioSession, playAndRecord: playAndRecord, ambient: ambient, forceAudioToSpeaker: forceAudioToSpeaker, baseRate: baseRate, audioLevelPipe: audioLevelPipe, updatedRate: updatedRate, audioPaused: audioPaused)
|
||||
self.contextRef = Unmanaged.passRetained(context)
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ import AVFoundation
|
||||
import UIKit
|
||||
|
||||
public enum ManagedAudioSessionType: Equatable {
|
||||
case ambient
|
||||
case play
|
||||
case playWithPossiblePortOverride
|
||||
case record(speaker: Bool)
|
||||
@ -22,6 +23,8 @@ public enum ManagedAudioSessionType: Equatable {
|
||||
|
||||
private func nativeCategoryForType(_ type: ManagedAudioSessionType, headphones: Bool, outputMode: AudioSessionOutputMode) -> AVAudioSession.Category {
|
||||
switch type {
|
||||
case .ambient:
|
||||
return .ambient
|
||||
case .play:
|
||||
return .playback
|
||||
case .record, .voiceCall, .videoCall:
|
||||
@ -665,7 +668,7 @@ public final class ManagedAudioSession {
|
||||
print("ManagedAudioSession setting category for \(type) (native: \(nativeCategory))")
|
||||
var options: AVAudioSession.CategoryOptions = []
|
||||
switch type {
|
||||
case .play:
|
||||
case .play, .ambient:
|
||||
break
|
||||
case .playWithPossiblePortOverride:
|
||||
if case .playAndRecord = nativeCategory {
|
||||
|
@ -34,7 +34,7 @@ private final class PresentationCallToneRenderer {
|
||||
|
||||
self.toneRenderer = MediaPlayerAudioRenderer(audioSession: .custom({ control in
|
||||
return controlImpl?(control) ?? EmptyDisposable
|
||||
}), playAndRecord: false, forceAudioToSpeaker: false, baseRate: 1.0, audioLevelPipe: self.audioLevelPipe, updatedRate: {}, audioPaused: {})
|
||||
}), playAndRecord: false, ambient: false, forceAudioToSpeaker: false, baseRate: 1.0, audioLevelPipe: self.audioLevelPipe, updatedRate: {}, audioPaused: {})
|
||||
|
||||
controlImpl = { [weak self] control in
|
||||
queue.async {
|
||||
|
@ -1282,7 +1282,7 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
|
||||
for (emoji, file) in emojiSounds.sounds {
|
||||
if emoji.unicodeScalars.first == firstScalar {
|
||||
let mediaManager = item.context.sharedContext.mediaManager
|
||||
let mediaPlayer = MediaPlayer(audioSessionManager: mediaManager.audioSession, postbox: item.context.account.postbox, resourceReference: .standalone(resource: file.resource), streamable: .none, video: false, preferSoftwareDecoding: false, enableSound: true, fetchAutomatically: true)
|
||||
let mediaPlayer = MediaPlayer(audioSessionManager: mediaManager.audioSession, postbox: item.context.account.postbox, resourceReference: .standalone(resource: file.resource), streamable: .none, video: false, preferSoftwareDecoding: false, enableSound: true, fetchAutomatically: true, ambient: true)
|
||||
mediaPlayer.togglePlayPause()
|
||||
mediaPlayer.actionAtEnd = .action({ [weak self] in
|
||||
self?.mediaPlayer = nil
|
||||
|
@ -214,7 +214,7 @@ final class ManagedAudioRecorderContext {
|
||||
}
|
||||
return ActionDisposable {
|
||||
}
|
||||
}), playAndRecord: true, forceAudioToSpeaker: false, baseRate: 1.0, audioLevelPipe: ValuePipe<Float>(), updatedRate: {
|
||||
}), playAndRecord: true, ambient: false, forceAudioToSpeaker: false, baseRate: 1.0, audioLevelPipe: ValuePipe<Float>(), updatedRate: {
|
||||
}, audioPaused: {})
|
||||
self.toneRenderer = toneRenderer
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user