// // RecordPlayerService.swift // AutoCatCore // // Created by Selim Mustafaev on 31.03.2025. // Copyright © 2025 Selim Mustafaev. All rights reserved. // import AVFoundation public final class RecordPlayerService: NSObject { var player: AVAudioPlayer? var record: AudioRecordDto? var onStop: ((AudioRecordDto, Error?) -> Void)? func playNewRecord(record: AudioRecordDto, onStop: ((AudioRecordDto, Error?) -> Void)?) throws { let url = try FileManager.default.url(for: record.path, in: Constants.audioRecordsFolder) player = try AVAudioPlayer(contentsOf: url) player?.delegate = self self.record = record self.onStop = onStop try activateSession() player?.play() } func activateSession() throws { try AVAudioSession.sharedInstance().setCategory( .playback, mode: .default, options: [.duckOthers] ) try AVAudioSession.sharedInstance().setActive(true) } func deactivateSession() throws { try AVAudioSession.sharedInstance().setActive( false, options: .notifyOthersOnDeactivation ) } } extension RecordPlayerService: RecordPlayerServiceProtocol { public func play(record: AudioRecordDto, onStop: ((AudioRecordDto, Error?) -> Void)?) throws { guard let player, self.record?.id == record.id else { try playNewRecord(record: record, onStop: onStop) return } if player.isPlaying { player.pause() try deactivateSession() } else { try activateSession() player.play() } } public func pause() { player?.pause() } public var currentPlayingId: String? { guard player?.isPlaying == true else { return nil } return record?.id } } extension RecordPlayerService: AVAudioPlayerDelegate { public func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) { guard let record else { return } onStop?(record, nil) reset() } public func audioPlayerDecodeErrorDidOccur(_ player: AVAudioPlayer, error: (any Error)?) { guard let record else { return } onStop?(record, error) reset() } func reset() { onStop = nil player = nil record = nil try? deactivateSession() } }