Music_Player3/MusicPlayer/MP/Common/Tool(工具封装)/MP_PlayerManager.swift
2024-05-11 09:48:37 +08:00

295 lines
10 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// MP_PlayerManager.swift
// MusicPlayer
//
// Created by Mr.Zhou on 2024/5/10.
//
import UIKit
import AVFoundation
import MediaPlayer
import AVKit
///
enum MP_PlayerStateType:Int {
///
case Null = 0
///
case Playing = 1
///
case Pause = 2
}
///
enum MP_PlayerPlayType:Int {
///
case normal = 0
///
case random = 1
///
case single = 2
}
///
typealias MP_PlayTimerStartAction = () -> Void
///()
typealias MP_PlayTimerRunAction = (_ currentTime:TimeInterval, _ duration:TimeInterval) -> Void
///
typealias MP_PlayTimerEndAction = () -> Void
///
typealias MP_PlayTimerPauseAction = () -> Void
///
typealias MP_PlayTimerResumeAction = () -> Void
///
typealias MP_PlayTimerStopAction = () -> Void
///
typealias MP_PlayTimerEditEndAction = () -> Void
///
class MP_PlayerManager{
///
static let shared = MP_PlayerManager()
///
private var player:AVPlayer = AVPlayer()
///load
var loadPlayer:MPPositive_PlayerLoadViewModel!
//
private var playState:MP_PlayerStateType = .Null
///
private var startActionBlock:MP_PlayTimerStartAction!
///
private var runActionBlock:MP_PlayTimerRunAction!
private init() {
//
NotificationCenter.default.addObserver(self, selector: #selector(playerDidFinishPlaying(_ :)), name: .AVPlayerItemDidPlayToEndTime, object: player.currentItem)
NotificationCenter.notificationKey.add(observer: self, selector: #selector(userSwitchCurrentVideoAction(_ :)), notificationName: .positive_player_reload)
}
deinit {
NotificationCenter.default.removeObserver(self)
}
///
func getPlayState() -> MP_PlayerStateType {
return playState
}
///
/// - Parameters:
/// - startAction:
/// - runAction:
/// - endAction:
func play(startAction:MP_PlayTimerStartAction? = nil, runAction:MP_PlayTimerRunAction? = nil) {
//
switch playState {
case .Null://
break
case .Playing://
player.pause()
case .Pause://
break
}
//
if startAction != nil {
startActionBlock = startAction
}
if runAction != nil {
runActionBlock = runAction
}
//PlayerItem
player.replaceCurrentItem(with: loadPlayer.currentVideo.resourcePlayerItem)
//0
player.seek(to: .zero)
//
let interval:CMTime = .init(seconds: 1, preferredTimescale: .init(1))
//线
player.addPeriodicTimeObserver(forInterval: interval, queue: .main, using: { [weak self] (time) in
guard let self = self else { return }
//
let currentDuration = CMTimeGetSeconds(time)
//current0
if currentDuration == 0 {
if startActionBlock != nil {
startActionBlock!()
}
}
//
let maxDuration = getMusicDuration()
if maxDuration.isNaN == false {
//
if currentDuration <= maxDuration {
//
if runActionBlock != nil {
runActionBlock!(currentDuration, maxDuration)
}
}
}
})
//
player.play()
playState = .Playing
//
// let set = Set(loadPlayer.listViewVideos.filter({$0.index != loadPlayer.currentVideo.index}))
// set.forEach { item in
// if item.canBePreloaded() == false {
// item.preloadPlayerItem()
// }
// }
}
///
private func getMusicDuration() -> TimeInterval {
return CMTimeGetSeconds(player.currentItem?.duration ?? .zero)
}
//MARK: -
//
@objc private func playerDidFinishPlaying(_ sender:Notification) {
//
guard playState == .Playing else {
return
}
//
nextEvent()
}
//MARK: -
///
private func pause() {
//
guard playState == .Playing else {
//
print("Player is not in playing")
return
}
//
player.pause()
//
playState = .Pause
}
///
/// - Parameter pauseAction:
func pause(_ pauseAction:MP_PlayTimerPauseAction? = nil) {
//
guard playState == .Playing else {
//
print("Player is not in playing")
return
}
if pauseAction != nil {
pauseAction!()
}
//
player.pause()
//
playState = .Pause
}
//MARK: -
///
/// - Parameter resumeAction:
func resume(_ resumeAction:MP_PlayTimerResumeAction? = nil) {
//
guard playState == .Pause else {
//
print("Player is not paused")
return
}
if resumeAction != nil {
resumeAction!()
}
//
player.play()
//
playState = .Playing
}
///
private func resume() {
//
guard playState == .Pause else {
//
print("Player is not paused")
return
}
//
player.play()
//
playState = .Playing
}
//MARK: -
//
private func stop() {
//
guard playState != .Null else {
//
print("Player is not started")
return
}
player.pause()
playState = .Null
}
//MARK: - /
///
func previousEvent() {
//
let targetIndex = loadPlayer.listViewVideos.firstIndex(of: loadPlayer.currentVideo)
if targetIndex == 0 {
//
let last = loadPlayer.songVideos.last
loadPlayer.improveData(last?.videoId ?? "")
}else {
//,ID
let song = loadPlayer.songVideos.first(where: {$0.index == (loadPlayer.currentVideo.index-1)})
loadPlayer.improveData(song?.videoId ?? "")
}
}
///
func nextEvent() {
//
let targetIndex = loadPlayer.listViewVideos.firstIndex(of: loadPlayer.currentVideo)
if targetIndex == (loadPlayer.listViewVideos.count - 1) {
//
let first = loadPlayer.songVideos.first
loadPlayer.improveData(first?.videoId ?? "")
}else {
//,ID
let song = loadPlayer.songVideos.first(where: {$0.index == (loadPlayer.currentVideo.index+1)})
loadPlayer.improveData(song?.videoId ?? "")
}
}
///
@objc private func userSwitchCurrentVideoAction(_ sender:Notification) {
if loadPlayer.currentVideo != nil {
//
play(startAction: startActionBlock,runAction: runActionBlock)
}else {
//
}
}
///
func setEditPorgressStatu() {
guard playState != .Null else {
return
}
//
pause()
}
/// setEditPorgressStatu()使
/// - Parameters:
/// - progress: 0-1
func setEditProgressEnd(_ progress:Float, endAction:MP_PlayTimerEditEndAction? = nil) {
guard playState != .Null else {
return
}
guard progress >= 0, progress <= 1 else {
return
}
//
let timePoint:Double = Double(progress)*getMusicDuration()
//
let time:CMTime = .init(seconds: timePoint, preferredTimescale: CMTimeScale(NSEC_PER_SEC))
//
player.seek(to: time)
//
resume()
if endAction != nil {
endAction!()
}
}
}