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