Files
element-x-ios/ElementX/Sources/Services/MediaPlayer/MediaPlayerProvider.swift
T

83 lines
2.8 KiB
Swift

//
// Copyright 2025 Element Creations Ltd.
// Copyright 2023-2025 New Vector Ltd.
//
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
// Please see LICENSE files in the repository root for full details.
//
import AVFoundation
import Foundation
class MediaPlayerProvider: MediaPlayerProviderProtocol {
private lazy var audioPlayer = AudioPlayer()
private var audioPlayerStates: [String: AudioPlayerState] = [:]
/// Held onto for the duration of the playback, an unowned player is silent.
private var soundEffectPlayer: AVAudioPlayer?
var player: AudioPlayerProtocol {
audioPlayer
}
deinit {
audioPlayerStates = [:]
}
// MARK: - AudioPlayer
func playerState(for id: AudioPlayerStateIdentifier) -> AudioPlayerState? {
guard let audioPlayerStateID = audioPlayerStateID(for: id) else {
MXLog.error("Failed to build an ID using: \(id)")
return nil
}
return audioPlayerStates[audioPlayerStateID]
}
func register(audioPlayerState: AudioPlayerState) {
guard let audioPlayerStateID = audioPlayerStateID(for: audioPlayerState.id) else {
MXLog.error("Failed to build a key to register this audioPlayerState: \(audioPlayerState)")
return
}
audioPlayerStates[audioPlayerStateID] = audioPlayerState
}
func unregister(audioPlayerState: AudioPlayerState) {
guard let audioPlayerStateID = audioPlayerStateID(for: audioPlayerState.id) else {
MXLog.error("Failed to build a key to register this audioPlayerState: \(audioPlayerState)")
return
}
audioPlayerStates[audioPlayerStateID] = nil
}
func detachAllStates(except exception: AudioPlayerState?) {
for key in audioPlayerStates.keys {
if let exception, key == audioPlayerStateID(for: exception.id) {
continue
}
audioPlayerStates[key]?.detachAudioPlayer()
}
}
/// Doesn't configure an audio session, so that it can be used alongside any existing player or session.
func play(soundEffect: SoundEffect) {
do {
let player = try AVAudioPlayer(contentsOf: soundEffect.fileURL)
soundEffectPlayer = player
player.play()
} catch {
MXLog.error("Failed playing the sound effect: \(error)")
}
}
// MARK: - Private
private func audioPlayerStateID(for identifier: AudioPlayerStateIdentifier) -> String? {
switch identifier {
case .timelineItemIdentifier(let timelineItemIdentifier):
return timelineItemIdentifier.eventID
case .recorderPreview:
return "recorderPreviewAudioPlayerState"
}
}
}