From e15c976316feef72ff9bcabce38e0a078f9505db Mon Sep 17 00:00:00 2001
From: 杨锴 <841720330@qq.com>
Date: 星期四, 12 九月 2024 18:18:03 +0800
Subject: [PATCH] fix API

---
 XQMuse/Root/PayMusicView/PayMusicVC.swift |  272 +++++++++++++++++++++++++++++++++++++++---------------
 1 files changed, 195 insertions(+), 77 deletions(-)

diff --git a/XQMuse/Root/PayMusicView/PayMusicVC.swift b/XQMuse/Root/PayMusicView/PayMusicVC.swift
index b403aeb..687e2c5 100644
--- a/XQMuse/Root/PayMusicView/PayMusicVC.swift
+++ b/XQMuse/Root/PayMusicView/PayMusicVC.swift
@@ -11,12 +11,34 @@
 import MediaPlayer
 import RxRelay
 
-class PayMusicVC: BaseVC {
+@objc enum PlayMusicState:Int{
+				case playing = 1
+				case paurse = 2
+				case end = 3
+				case next = 4
+}
+
+@objc protocol PayMusicDelegate{
+				func playState(_ state:PlayMusicState)
+				@objc optional	 func playListen(currentInterval:TimeInterval,totalInterval:TimeInterval)
+}
+
+class PayMusicVC: BaseVC{
 
 				private var coverImage:UIImageView!
 				private var label_name:UILabel!
 				private var btn_handle:UIButton!
+				private var btn_handleClose:UIButton!
 				private var audioPlayer:AudioPlayer!
+				private var isAniLoop:Bool = false
+				private var meditationModel:MeditationModel?{
+								didSet{
+												if let m = meditationModel{
+																coverImage.sd_setImage(with: URL(string: m.coverUrl),placeholderImage: UIImage(named: "login_top_bg"))
+																label_name.text = m.meditationTitle
+												}
+								}
+				}
 
 				private init() {
 								super.init(nibName: nil, bundle: nil)
@@ -29,6 +51,10 @@
     override func viewDidLoad() {
         super.viewDidLoad()
 								audioPlayer = AudioPlayer.getSharedInstance()
+
+								let tap = UITapGestureRecognizer(target: self, action: #selector(showDetailAction))
+								coverImage.isUserInteractionEnabled = true
+								coverImage.addGestureRecognizer(tap)
     }
 
 				override func setUI() {
@@ -58,38 +84,57 @@
 
 								btn_handle = UIButton(type: .custom)
 								btn_handle.setImage(UIImage(named: "icon_play_purse"), for: .normal)
+								btn_handle.setImage(UIImage(named: "icon_play_small"), for: .selected)
 								btn_handle.addTarget(self, action: #selector(tapHandleAction), for: .touchUpInside)
 								view.addSubview(btn_handle)
-								btn_handle.snp.makeConstraints { make in
+
+								btn_handleClose = UIButton(type: .custom)
+								btn_handleClose.setImage(UIImage(named: "icon_play_close"), for: .normal)
+								btn_handleClose.addTarget(self, action: #selector(closeAction), for: .touchUpInside)
+								view.addSubview(btn_handleClose)
+
+								let statckView = UIStackView(arrangedSubviews: [btn_handle,btn_handleClose])
+								statckView.axis = .horizontal
+								statckView.distribution = .equalSpacing
+								statckView.spacing = 18
+								view.addSubview(statckView)
+								statckView.snp.makeConstraints { make in
 												make.right.equalToSuperview().offset(-24.5)
 												make.centerY.equalToSuperview()
-												make.width.height.equalTo(28)
 								}
 				}
 
-				static func show(){
-								 let vc = PayMusicVC()
-								 let tabBarHeight = JQ_currentViewController().navigationController?.tabBarController?.tabBar.height ?? 0
-								JQ_currentViewController().navigationController?.tabBarController?.addChild(vc)
-								JQ_currentViewController().navigationController?.tabBarController?.view.addSubview(vc.view)
-								vc.view.snp.makeConstraints { make in
-												make.left.equalTo(18.5)
-												make.right.equalTo(-18.5)
-												make.height.equalTo(46.5)
-												make.bottom.equalToSuperview().offset(-(tabBarHeight))
+				static func show(model:MeditationModel){
+								if let tabBarVC = JQ_currentViewController().navigationController?.tabBarController as? BaseTabBarVC{
+												if !tabBarVC.children.contains(where: {$0 is PayMusicVC}){
+																let vc = PayMusicVC()
+																vc.view.isHidden = true
+																vc.meditationModel = model
+																let tabBarHeight = JQ_currentViewController().navigationController?.tabBarController?.tabBar.height ?? 0
+																JQ_currentViewController().navigationController?.tabBarController?.addChild(vc)
+																JQ_currentViewController().navigationController?.tabBarController?.view.addSubview(vc.view)
+																vc.view.snp.makeConstraints { make in
+																				make.left.equalTo(18.5)
+																				make.right.equalTo(-18.5)
+																				make.height.equalTo(46.5)
+																				make.bottom.equalToSuperview().offset(-(tabBarHeight))
+																}
+																vc.startRunloopAni()
+												}
 								}
-								vc.startRunloopAni()
-
-								var testURL = [URL]()
-								testURL.append(URL(string: "https://downsc.chinaz.net/files/download/sound1/201206/1638.mp3")!)
-								testURL.append(URL(string: "https://downsc.chinaz.net/Files/DownLoad/sound1/201906/11582.mp3")!)
-								testURL.append(URL(string: "https://www.cambridgeenglish.org/images/153149-movers-sample-listening-test-vol2.mp3")!)
-								vc.audioPlayer.playAt(firstPlayIndex: 2, urls: testURL)
-
 				}
 
+				@objc func showDetailAction(){
+								if let id = meditationModel?.id{
+												let vc = HomeItemDetailVC(id: id)
+												vc.hidesBottomBarWhenPushed = true
+												JQ_currentNavigationController().pushViewController(vc)
+								}
+
+				}
 
 				private func startRunloopAni(){
+								isAniLoop = true
 								// 创建旋转动画
 								let rotationAnimation = CABasicAnimation(keyPath: "transform.rotation.z")
 								rotationAnimation.fromValue = 0
@@ -97,25 +142,51 @@
 								rotationAnimation.duration = 5 // 动画持续时间
 								rotationAnimation.repeatCount = .greatestFiniteMagnitude // 无限重复
 								coverImage.layer.add(rotationAnimation, forKey: nil)
+				}
 
+				private func stopRunloopAni(){
+								isAniLoop = false
+								coverImage.layer.removeAllAnimations()
 				}
 
 				@objc func tapHandleAction(_ btn:UIButton){
+								btn.isSelected = !btn.isSelected
 
+								if btn.isSelected{
+												self.audioPlayer.bgmPlayer?.pause()
+												self.audioPlayer.masterPlayer?.pause()
+												self.stopRunloopAni()
+								}else{
+												self.audioPlayer.bgmPlayer?.play()
+												self.audioPlayer.masterPlayer?.play()
+												self.startRunloopAni()
+								}
+				}
 
+				@objc func closeAction(_ btn:UIButton){
+								CommonAlertView.show(title: "提示", content: "是否关闭当前播放音频?") { state in
+												if state{
+																self.audioPlayer.clean()
+																self.view.removeFromSuperview()
+																self.removeFromParent()
+												}
+								}
 				}
 }
 
 class AudioPlayer {
-				private var player:AVPlayer?
-				private var BGMplayer:AVPlayer?
-				private var playIndex:Int = 0 //播放的角标
+				private(set) var bgmPlayer:AVPlayer? // 背景音
+				private(set) var scenePlayer:AVPlayer? //场景音
+				private(set) var masterPlayer:AVPlayer? //大师音
+				private(set) var playIndex:Int = 0 //播放的角标
 				private var cacheDirectory:URL!
 				private let session = URLSession.shared
 				private var urls = [URL]()
 				private var timer:Timer?
-				private(set) var times = BehaviorRelay<Int?>(value: nil)
+				private(set) var times = BehaviorRelay<Int?>(value: nil) //倒计时定时器
 				private static var _sharedInstance: AudioPlayer?
+				private(set) var meditationModel:MeditationModel?
+				weak var delegate:PayMusicDelegate?
 
 				class func getSharedInstance() -> AudioPlayer {
 								guard let instance = _sharedInstance else {
@@ -138,43 +209,81 @@
 								_sharedInstance = nil
 				}
 
-				func playAt(firstPlayIndex:Int,urls:[URL]){
-								self.playIndex = firstPlayIndex
+				func clean(){
+								self.bgmPlayer?.pause()
+								self.masterPlayer?.pause()
+								self.meditationModel = nil
+								self.timer = nil
+								AudioPlayer.destroy()
+				}
 
-								autoreleasepool{
+				func playBGMAt(firstPlayIndex:Int,model:MeditationModel,delegate:PayMusicDelegate?){
+								self.delegate = delegate
+								self.playIndex = firstPlayIndex
+								self.meditationModel = model
+
+								let urls = model.backgroundUrl.components(separatedBy: ",").map { str in
+												return URL(string: str)!
+								}
+
+								let masterUrl = URL(string: model.tutorAudioUrl)
+
+								autoreleasepool{[unowned self] () in
 												for url in urls {
-																checkCacheAudio(from: url) { _, url in
+																self.checkCacheAudio(from: url) {[unowned self] _, url in
 																				self.urls.append(url)
 																}
 												}
-												player = AVPlayer(url: self.urls[firstPlayIndex])
-												player?.play()
+												self.bgmPlayer = AVPlayer(url: self.urls[firstPlayIndex])
+												self.bgmPlayer?.play()
+
+
+												if masterUrl != nil{
+																self.masterPlayer = AVPlayer(url: masterUrl!)
+																self.masterPlayer?.play()
+												}
 								}
 
-								self.player!.addPeriodicTimeObserver(forInterval: CMTimeMake(value: 1, timescale: 1), queue: DispatchQueue.main) { [unowned self](time) in
+								self.bgmPlayer!.addPeriodicTimeObserver(forInterval: CMTimeMake(value: 1, timescale: 1), queue: DispatchQueue.main) { [weak self](time) in
+												guard let weakSelf = self else { return }
+												weakSelf.delegate?.playState(.playing)
+
 												//当前正在播放的时间
 												let loadTime = CMTimeGetSeconds(time)
 												//视频总时间
-												let totalTime = CMTimeGetSeconds((self.player?.currentItem?.duration)!)
+												let totalTime = CMTimeGetSeconds((weakSelf.bgmPlayer?.currentItem?.duration)!)
 
-												var dic = [String:Any]()
-												dic[MPMediaItemPropertyTitle] = "测试"
-												dic[MPMediaItemPropertyArtist] = "心泉·疗愈"
-												dic[MPMediaItemPropertyDiscNumber] = 1
-												dic[MPNowPlayingInfoPropertyElapsedPlaybackTime] = loadTime
-												dic[MPNowPlayingInfoPropertyPlaybackRate] = 1
-												// 获取时长。item.duration.seconds 不凑效
-												let asset = self.player?.currentItem?.asset
-												dic[MPMediaItemPropertyPlaybackDuration] = CMTimeGetSeconds(asset!.duration)
-																				dic[MPMediaItemPropertyArtwork] = MPMediaItemArtwork(boundsSize: CGSize(width: 50, height: 50), requestHandler: { s in
-																								return UIImage(named: "home_top_bg")!
-																				})
-												MPNowPlayingInfoCenter.default().nowPlayingInfo = dic
+
+												if loadTime >= totalTime{
+																if weakSelf.playIndex <= urls.count - 1{
+																				weakSelf.next()
+																				weakSelf.delegate?.playState(.next)
+																}else{
+																				weakSelf.delegate?.playState(.end)
+																}
+												}
+
+												weakSelf.delegate?.playListen?(currentInterval: loadTime, totalInterval: totalTime)
+
+												if let m = weakSelf.meditationModel{
+																var dic = [String:Any]()
+																dic[MPMediaItemPropertyTitle] = m
+																dic[MPMediaItemPropertyArtist] = "心泉·疗愈"
+																dic[MPMediaItemPropertyDiscNumber] = 1
+																dic[MPNowPlayingInfoPropertyElapsedPlaybackTime] = loadTime
+																dic[MPNowPlayingInfoPropertyPlaybackRate] = 1
+																// 获取时长。item.duration.seconds 不凑效
+																let asset = weakSelf.bgmPlayer?.currentItem?.asset
+																dic[MPMediaItemPropertyPlaybackDuration] = CMTimeGetSeconds(asset!.duration)
+																dic[MPMediaItemPropertyArtwork] = MPMediaItemArtwork(boundsSize: CGSize(width: 50, height: 50), requestHandler: { s in
+																				return UIImage(named: "home_top_bg")!
+																})
+																MPNowPlayingInfoCenter.default().nowPlayingInfo = dic
+												}
 								}
 
-
 								//播放完成
-								NotificationCenter.default.addObserver(self, selector: #selector(playbackEnd), name:NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: nil)
+//								NotificationCenter.default.addObserver(self, selector: #selector(playbackEnd), name:NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: nil)
 
 								setLockScreen()
 
@@ -188,60 +297,69 @@
 								}
 				}
 
-				func playBGMAt(_ url:String){
+				/// 播放场景音乐
+				func playSceneAt(_ url:String){
 								guard let URL = URL(string: url) else { return }
-								BGMplayer?.pause()
+								scenePlayer?.pause()
 
-								if BGMplayer == nil{
-												BGMplayer = AVPlayer(url: URL)
+								if scenePlayer == nil{
+												scenePlayer = AVPlayer(url: URL)
 								}else{
-												BGMplayer?.replaceCurrentItem(with: AVPlayerItem(url: URL))
+												scenePlayer?.replaceCurrentItem(with: AVPlayerItem(url: URL))
 								}
 								DispatchQueue.main.asyncAfter(delay: 3.0) {
-												self.BGMplayer?.play()
-												self.BGMplayer?.volume = Float(UserDefaultSettingViewModel.getSetting()?.volume ?? 0.5)
+												self.scenePlayer?.play()
+												self.scenePlayer?.volume = Float(UserDefaultSettingViewModel.getSetting()?.volume ?? 0.5)
 								}
 
-
 								//播放完成
-								NotificationCenter.default.addObserver(self, selector: #selector(playBGMbackEnd), name:NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: nil)
+//								NotificationCenter.default.addObserver(self, selector: #selector(playBGMbackEnd), name:NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: nil)
 				}
 
-				func dellocBGM(){
-								BGMplayer?.pause()
-								BGMplayer = nil
+				func dellocScene(){
+								scenePlayer?.pause()
+								scenePlayer = nil
 				}
 
-				func pauseBGM(){
-								BGMplayer?.pause()
+				func pauseScene(){
+								scenePlayer?.pause()
 				}
 
-				func playBGM(){
-								BGMplayer?.play()
+				func playScene(){
+								scenePlayer?.play()
 				}
 
 				func next(){
 								playIndex += 1
 								let index = min((urls.count - 1), playIndex)
-								player?.replaceCurrentItem(with: AVPlayerItem(url: urls[index]))
-								player?.play()
+								bgmPlayer?.replaceCurrentItem(with: AVPlayerItem(url: urls[index]))
+								bgmPlayer?.play()
 				}
 
-				@objc private func playbackEnd(){
-
-				}
-
+//				@objc private func playbackEnd(){
+//								if bgmPlayer?.actionAtItemEnd == AVPlayer.ActionAtItemEnd.pause && playIndex <= urls.count - 1{
+//												next()
+//												self.delegate?.playState(.next)
+//								}else{
+//												print("背景音乐播放完毕")
+//												self.delegate?.playState(.end)
+//								}
+//
+//								if masterPlayer?.actionAtItemEnd == AVPlayer.ActionAtItemEnd.pause{
+//												print("导师播放完毕")
+//								}
+//				}
 
 				@objc private func playBGMbackEnd(){
-								self.BGMplayer?.seek(to: CMTimeMake(value: 0, timescale: 1))
-								self.BGMplayer?.play()
+								self.scenePlayer?.seek(to: CMTimeMake(value: 0, timescale: 1))
+								self.scenePlayer?.play()
 				}
 
 				func previous(){
 								playIndex -= 1
 								let index = max(0, playIndex)
-								player?.replaceCurrentItem(with: AVPlayerItem(url: urls[index]))
-								player?.play()
+								bgmPlayer?.replaceCurrentItem(with: AVPlayerItem(url: urls[index]))
+								bgmPlayer?.play()
 				}
 
 				func setLockScreen(){
@@ -255,7 +373,7 @@
 																return .commandFailed
 												}
 
-												self.player?.seek(to: CMTime(seconds: event.positionTime, preferredTimescale: 1),
+												self.bgmPlayer?.seek(to: CMTime(seconds: event.positionTime, preferredTimescale: 1),
 																										toleranceBefore: CMTime(seconds: 0, preferredTimescale: 1),
 																										toleranceAfter: CMTime(seconds: 0, preferredTimescale: 1))
 
@@ -265,13 +383,13 @@
 
 								// 播放
 								center.playCommand.addTarget {[unowned self] event in
-												self.player?.play()
+												self.bgmPlayer?.play()
 												return .success
 								}
 
 								// 暂停
 								center.pauseCommand.addTarget {[unowned self] event in
-												self.player?.pause()
+												self.bgmPlayer?.pause()
 												return .success
 								}
 

--
Gitblit v1.7.1