Browse Source

4.3a改造: 音乐播放和下载音乐,音乐管理重构完毕

kln 1 week ago
parent
commit
cf136ff04d

+ 5 - 5
AIPlayRingtones/AppPage/APAudioToRingVC/APAudioToRingVC+Upload.swift

@@ -10,7 +10,7 @@ extension APAudioToRingVC {
     func creatFileView() -> ASRTRFileView {
         let fileView = ASRTRFileView { [weak self] in
             guard let self = self else { return }
-            TSBusinessAudioPlayer.shared.stop()
+            ASMediaPlayerController.main.stopPlayback()
             selectAudioFile()
         } clickPlayComplete: { [weak self] in
             guard let self = self else { return }
@@ -21,13 +21,13 @@ extension APAudioToRingVC {
     
     
     func clickPlay() {
-        if TSBusinessAudioPlayer.shared.isLoading{
+        if ASMediaPlayerController.main.isBuffering{
             return
         }
-        if TSBusinessAudioPlayer.shared.isPlaying{
-            TSBusinessAudioPlayer.shared.stop()
+        if ASMediaPlayerController.main.isActive{
+            ASMediaPlayerController.main.stopPlayback()
         }else{
-            TSBusinessAudioPlayer.shared.playUrlString("",localURL:viewModel.ringFilePath,indexPath: nil)
+            ASMediaPlayerController.main.startPlayback(localPath:viewModel.ringFilePath)
         }
     }
 }

+ 1 - 1
AIPlayRingtones/AppPage/APAudioToRingVC/APAudioToRingVC.swift

@@ -86,7 +86,7 @@ class APAudioToRingVC: ASBaseViewController {
     
     override func viewWillDisappear(_ animated: Bool) {
         super.viewWillDisappear(animated)
-        TSBusinessAudioPlayer.shared.stop()
+        ASMediaPlayerController.main.stopPlayback()
     }
     deinit {
         cancellable.removeAll()

+ 3 - 3
AIPlayRingtones/AppPage/APAudioToRingVC/View/ASRTRFileView.swift

@@ -150,9 +150,9 @@ class ASRTRFileView: ASBaseView {
             uploadView.isHidden = !playView.isHidden
             
             if let filePath = filePath {
-                if let info = TSBusinessAudioPlayer.getAudioFileInfo(path: filePath.path()){
-                    playView.ringView.nameLab.text = info.songName
-                    playView.ringView.timeLab.text = Float(info.durationInSeconds ?? 0).timeMMSS
+                if let info = ASMediaPlayerController.analyzeMediaFile(at: filePath.path()){
+                    playView.ringView.nameLab.text = info.title
+                    playView.ringView.timeLab.text = Float(info.duration ?? 0).timeMMSS
                 }
             }
         }

+ 17 - 17
AIPlayRingtones/AppPage/APMyRingVC/ASMyRingCell.swift

@@ -191,27 +191,25 @@ extension ASMyRingCell {
 
         //处理播放进度
         if playSelf{
-            logPrint("\(self.indexPath.item),playSelf")
             setPlayerStateChangedHandle()
         }else{
-            changePlayerState(state: .stop)
+            changePlayerState(state: .stopped)
         }
     }
 
     func setPlayerStateChangedHandle(){
-        
-        TSBusinessAudioPlayer.shared.stateChangedHandle = { [weak self] playerState in
+        ASMediaPlayerController.main.onStatusChange = { [weak self] playerState in
             guard let self = self else { return }
             logPrint("\(self.indexPath.item),stateChangedHandle self=\(self)")
             
             if playSelf {
                 self.changePlayerState(state: playerState)
             }else{
-                self.changePlayerState(state: .stop)
+                self.changePlayerState(state: .stopped)
             }
 
         }
-        self.changePlayerState(state: TSBusinessAudioPlayer.shared.currentPlayerState)
+        self.changePlayerState(state: ASMediaPlayerController.main.currentStatus)
     }
 
 }
@@ -240,24 +238,24 @@ extension ASMyRingCell {
 extension ASMyRingCell {
     func clickPlay() {
         if playSelf{
-            if TSBusinessAudioPlayer.shared.isLoading{
+            if ASMediaPlayerController.main.isBuffering{
                 return
             }
-            if TSBusinessAudioPlayer.shared.isPlaying{
-                TSBusinessAudioPlayer.shared.stop()
+            if ASMediaPlayerController.main.isActive{
+                ASMediaPlayerController.main.stopPlayback()
             }else{
-                TSBusinessAudioPlayer.shared.playUrlString(modelUrlString,localURL: modelLocalURL,indexPath: indexPath)
+                ASMediaPlayerController.main.startPlayback(of:modelUrlString,localPath: modelLocalURL,index: indexPath)
             }
             
         }else{
-            TSBusinessAudioPlayer.shared.stop()//让上一个对象停止播放
+            ASMediaPlayerController.main.stopPlayback()//让上一个对象停止播放
             setPlayerStateChangedHandle()//更换监听
-            TSBusinessAudioPlayer.shared.playUrlString(modelUrlString,localURL: modelLocalURL,indexPath: indexPath)
+            ASMediaPlayerController.main.startPlayback(of:modelUrlString,localPath: modelLocalURL,index: indexPath)
         }
     }
     
 
-    func changePlayerState(state:TSBusinessAudioPlayer.PlayerState){
+    func changePlayerState(state:ASMediaPlayerController.PlaybackStatus){
         ringView.handelAudioPlayerStateChange(state: state)
     }
     
@@ -281,7 +279,7 @@ extension ASMyRingCell {
             exampleView.isHidden = model.modelType != .example
             vipView.isHidden = true
             
-            self.changePlayerState(state: TSBusinessAudioPlayer.shared.currentPlayerState)
+            self.changePlayerState(state: ASMediaPlayerController.main.currentStatus)
             
         case .failed:
             generateView.isHidden = false
@@ -290,7 +288,9 @@ extension ASMyRingCell {
     }
 
     var playSelf:Bool{
-        return TSBusinessAudioPlayer.shared.isPlayURLString(string: modelUrlString,localURL: modelLocalURL,indexPath: indexPath)
+        let b = ASMediaPlayerController.main.isCurrentMedia(url: modelUrlString,localPath: modelLocalURL,index: indexPath)
+        logPrint("\(self.indexPath.item),playSelf =\(b)")
+        return b
     }
 
     var modelUrlString:String{
@@ -314,7 +314,7 @@ extension ASMyRingCell {
             setShareBand(infoModel: model)
         }
     
-        TSBusinessAudioPlayer.shared.stop()
+        ASMediaPlayerController.main.stopPlayback()
     }
     
     func setShareBand(infoModel:ASActionInfoModel){
@@ -327,7 +327,7 @@ extension ASMyRingCell {
         if let fileURL = infoModel.localURL {
             _ = kshareBand(needVip: needVip, vc: targetVC, fileURL: fileURL, fileName: fileName)
         }else{
-            ASDownloadManager.getDownLoadRing(urlString: urlString){ url,downLoad in
+            ASMediaDownloader.fetchMediaResource(remoteURL: urlString){ url,downLoad in
                 if let path = url {
                     _ = kshareBand(needVip: needVip, vc: targetVC, fileURL: path, fileName: fileName)
                 }

+ 2 - 2
AIPlayRingtones/AppPage/APMyRingVC/ASMyRingVC.swift

@@ -98,7 +98,7 @@ class APMyRingVC: ASBaseViewController {
     
     override func viewWillDisappear(_ animated: Bool) {
         super.viewWillDisappear(animated)
-        TSBusinessAudioPlayer.shared.stop()
+        ASMediaPlayerController.main.stopPlayback()
     }
 
     override func dealThings() {
@@ -214,7 +214,7 @@ extension APMyRingVC: SwipeCollectionViewCellDelegate {
 
                     dbHistory.deleteListModel(id: model.id)
                     updateListView()
-                    TSBusinessAudioPlayer.shared.stop()
+                    ASMediaPlayerController.main.stopPlayback()
                 }
             }) {
                 

+ 11 - 11
AIPlayRingtones/AppPage/ASRingGeneratorVC/ASRingGeneratorVC.swift

@@ -27,7 +27,7 @@ class ASRingGeneratorVC: ASRingGeneratorBaseVC {
     }
     
     lazy var generateInView : ASGeneratorView = createGeneratorView()
-    lazy var audioPlayer = TSBusinessAudioPlayer.shared
+    lazy var mediaPlayer = ASMediaPlayerController.main
     var uuidString:String = UUID().uuidString
 
     lazy var ringView: ASRingToneCellView = {
@@ -106,9 +106,9 @@ class ASRingGeneratorVC: ASRingGeneratorBaseVC {
             kShowToastDataMissing()
             return
         }
-        audioPlayer.stop()
+        mediaPlayer.stopPlayback()
 
-        ASDownloadManager.getDownLoadRing(urlString: model.response.musicUrl){ url,downLoad in
+        ASMediaDownloader.fetchMediaResource(remoteURL: model.response.musicUrl){ url,downLoad in
             if let path = url {
                 _ = kshareBand(needVip: model.response.vip, vc: self, fileURL: path, fileName: model.response.title)
             }
@@ -119,26 +119,26 @@ class ASRingGeneratorVC: ASRingGeneratorBaseVC {
         
         guard let infoModel = infoModel else { return }
         
-        if  TSBusinessAudioPlayer.shared.isPlayURLString(string: infoModel.response.musicUrl) {
-            if TSBusinessAudioPlayer.shared.isLoading{
+        if  mediaPlayer.isCurrentMedia(url:infoModel.response.musicUrl) {
+            if mediaPlayer.isBuffering{
                 return
             }
-            if TSBusinessAudioPlayer.shared.isPlaying{
-                TSBusinessAudioPlayer.shared.stop()
+            if mediaPlayer.isActive{
+                mediaPlayer.stopPlayback()
             }else{
-                audioPlayer.playUrlString(infoModel.response.musicUrl)
+                mediaPlayer.startPlayback(of:infoModel.response.musicUrl)
             }
         }else {
-            TSBusinessAudioPlayer.shared.stop()//让上一个对象停止播放
+            mediaPlayer.stopPlayback()//让上一个对象停止播放
             ringView.monitorPlayStateDefaultHandle()//更换监听
-            audioPlayer.playUrlString(infoModel.response.musicUrl)
+            mediaPlayer.startPlayback(of:infoModel.response.musicUrl)
         }
 
     }
     
     override func viewWillDisappear(_ animated: Bool) {
         super.viewWillDisappear(animated)
-        audioPlayer.stop()
+        mediaPlayer.stopPlayback()
     }
     
     override func dealThings() {

+ 119 - 119
AIPlayRingtones/Common/ASBusinessFileManager.swift

@@ -5,122 +5,122 @@
 //  Created by mini on 2025/5/18.
 //
 
-
-class ASBusinessFileManager {
-    
-    /// 获取 Video 下载后保存的的文件件路径
-    static var saveRingPathURL:URL = {
-        let saveRingPathURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!.appendingPathComponent("ring")
-        return saveRingPathURL
-    }()
-    
-    static var saveCacheAllPathURL:URL = {
-        let saveRingPathURL = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first!.appendingPathComponent("cacheAll")
-        return saveRingPathURL
-    }()
-    
-    public static func generateFileName(
-        urlString: String,
-        fileEx:String? = nil,
-    missingEx:String? = nil
-    )->String?{
-        guard let url = URL(string: urlString) else{
-            return nil
-        }
-        
-        var fileName = url.path.md5
-
-        // 使用 URL 的 MD5 哈希值作为缓存文件名,附加 URL 的后缀名
-        var fileExtension = ""
-        if let fileEx = fileEx {
-            fileExtension = fileEx
-        }else{
-            var missingExStr = ""
-            if let missingEx = missingEx {
-                missingExStr = missingEx
-            }
-            fileExtension = url.pathExtension.isEmpty ? missingExStr : url.pathExtension
-        }
-
-        if fileExtension.count > 0 {
-            fileName = url.path.md5 + ".\(fileExtension)"
-        }
-         
-        return fileName
-    }
-    
-    //获取 urlstring 本地的缓存 url path
-    public static func getLocalURL(
-        urlString: String,
-        fileEx:String? = nil,
-    missingEx:String? = nil)->URL?{
-        
-        guard let fileName = generateFileName(urlString: urlString,fileEx:fileEx,missingEx: missingEx) else{
-            return nil
-        }
-        
-        //检查文件是否已存在于缓存中
-        let ringFileURL = saveRingPathURL.appendingPathComponent(fileName)
-        if FileManager.default.fileExists(atPath: ringFileURL.path) {
-            print("文件已存在于缓存中: \(ringFileURL)")
-            return ringFileURL
-        }
-        
-        let cachedFileURL = saveCacheAllPathURL.appendingPathComponent(fileName)
-        if FileManager.default.fileExists(atPath: cachedFileURL.path) {
-            print("文件已存在于缓存中: \(cachedFileURL)")
-            return cachedFileURL
-        }
-        
-        return nil
-    }
-    
-
-}
-
-//缓存路径
-extension ASBusinessFileManager {
-    
-    //检查 url 对不对
-    public static func generateLocalURL(
-        from urlString: String,
-        fileEx:String? = nil,
-        missingEx:String? = nil,
-        frontPathURL:URL,
-        completion:((String?, Error?) -> Void)? = nil
-    )->URL?
-    {
-        guard let url = URL(string: urlString) else{
-            completion?(nil, NSError(domain: "url null", code: 0))
-            return nil
-        }
-        
-        if !urlString.contains("http") && urlString.contains("/"){
-            completion?(urlString.fillCachePath, nil)
-            return nil
-        }
-        
-        let fileManager = FileManager.default
-        let cacheAllDirectory = frontPathURL
-        
-        // 创建 `cacheAll` 文件夹(如果不存在)
-        if !fileManager.fileExists(atPath: cacheAllDirectory.path) {
-            do {
-                try fileManager.createDirectory(at: cacheAllDirectory, withIntermediateDirectories: true, attributes: nil)
-            } catch {
-                completion?(nil, error)
-                return nil
-            }
-        }
-        
-        
-        guard let fileName = generateFileName(urlString: urlString,fileEx:fileEx,missingEx: missingEx) else{
-            completion?(nil, NSError(domain: "url error", code: 0))
-            return nil
-        }
-        
-        let cachedFileURL = cacheAllDirectory.appendingPathComponent(fileName)
-        return cachedFileURL
-    }
-    
-}
+//
+//class ASBusinessFileManager {
+//    
+//    /// 获取 Video 下载后保存的的文件件路径
+//    static var saveRingPathURL:URL = {
+//        let saveRingPathURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!.appendingPathComponent("ring")
+//        return saveRingPathURL
+//    }()
+//    
+//    static var saveCacheAllPathURL:URL = {
+//        let saveRingPathURL = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first!.appendingPathComponent("cacheAll")
+//        return saveRingPathURL
+//    }()
+//    
+//    public static func generateFileName(
+//        urlString: String,
+//        fileEx:String? = nil,
+//    missingEx:String? = nil
+//    )->String?{
+//        guard let url = URL(string: urlString) else{
+//            return nil
+//        }
+//        
+//        var fileName = url.path.md5
+//
+//        // 使用 URL 的 MD5 哈希值作为缓存文件名,附加 URL 的后缀名
+//        var fileExtension = ""
+//        if let fileEx = fileEx {
+//            fileExtension = fileEx
+//        }else{
+//            var missingExStr = ""
+//            if let missingEx = missingEx {
+//                missingExStr = missingEx
+//            }
+//            fileExtension = url.pathExtension.isEmpty ? missingExStr : url.pathExtension
+//        }
+//
+//        if fileExtension.count > 0 {
+//            fileName = url.path.md5 + ".\(fileExtension)"
+//        }
+//         
+//        return fileName
+//    }
+//    
+//    //获取 urlstring 本地的缓存 url path
+//    public static func getLocalURL(
+//        urlString: String,
+//        fileEx:String? = nil,
+//    missingEx:String? = nil)->URL?{
+//        
+//        guard let fileName = generateFileName(urlString: urlString,fileEx:fileEx,missingEx: missingEx) else{
+//            return nil
+//        }
+//        
+//        //检查文件是否已存在于缓存中
+//        let ringFileURL = saveRingPathURL.appendingPathComponent(fileName)
+//        if FileManager.default.fileExists(atPath: ringFileURL.path) {
+//            print("文件已存在于缓存中: \(ringFileURL)")
+//            return ringFileURL
+//        }
+//        
+//        let cachedFileURL = saveCacheAllPathURL.appendingPathComponent(fileName)
+//        if FileManager.default.fileExists(atPath: cachedFileURL.path) {
+//            print("文件已存在于缓存中: \(cachedFileURL)")
+//            return cachedFileURL
+//        }
+//        
+//        return nil
+//    }
+//    
+//
+//}
+//
+////缓存路径
+//extension ASBusinessFileManager {
+//    
+//    //检查 url 对不对
+//    public static func generateLocalURL(
+//        from urlString: String,
+//        fileEx:String? = nil,
+//        missingEx:String? = nil,
+//        frontPathURL:URL,
+//        completion:((String?, Error?) -> Void)? = nil
+//    )->URL?
+//    {
+//        guard let url = URL(string: urlString) else{
+//            completion?(nil, NSError(domain: "url null", code: 0))
+//            return nil
+//        }
+//        
+//        if !urlString.contains("http") && urlString.contains("/"){
+//            completion?(urlString.fillCachePath, nil)
+//            return nil
+//        }
+//        
+//        let fileManager = FileManager.default
+//        let cacheAllDirectory = frontPathURL
+//        
+//        // 创建 `cacheAll` 文件夹(如果不存在)
+//        if !fileManager.fileExists(atPath: cacheAllDirectory.path) {
+//            do {
+//                try fileManager.createDirectory(at: cacheAllDirectory, withIntermediateDirectories: true, attributes: nil)
+//            } catch {
+//                completion?(nil, error)
+//                return nil
+//            }
+//        }
+//        
+//        
+//        guard let fileName = generateFileName(urlString: urlString,fileEx:fileEx,missingEx: missingEx) else{
+//            completion?(nil, NSError(domain: "url error", code: 0))
+//            return nil
+//        }
+//        
+//        let cachedFileURL = cacheAllDirectory.appendingPathComponent(fileName)
+//        return cachedFileURL
+//    }
+//    
+//}

+ 38 - 38
AIPlayRingtones/Common/ASDownloadManager/ASDownloadManager.swift

@@ -5,41 +5,41 @@
 //  Created by mini on 2025/5/18.
 //
 
-import AVFoundation
-import Alamofire
-
-class ASDownloadManager {
-    
-    static func getDownLoadRing(urlString:String,progressHandler: ((Double) -> Void)? = nil,complete:@escaping (URL?,Bool)->Void){
-        if let path = ASBusinessFileManager.getLocalURL(urlString: urlString,fileEx:nil,missingEx: "mp3") {
-            complete(path,false)
-        }else{
-            _ = ASDownloadManager.downloadRing(urlString:urlString,missingEx: "mp3",progressHandler: progressHandler) { url, error in
-                if let path = url {
-                    complete(path,true)
-                }else{
-                    complete(nil,true)
-                }
-            }
-        }
-    }
-    
-    static func downloadRing(
-        urlString: String,
-        fileEx:String? = nil,
-    missingEx:String? = nil,
-        progressHandler: ((Double) -> Void)? = nil,
-        completion: @escaping (URL?, Error?) -> Void
-    ) -> DownloadRequest? {
-        
-        if let fileName = ASBusinessFileManager.getLocalURL(urlString: urlString,fileEx:fileEx,missingEx:missingEx){
-            completion(fileName,nil)
-            return nil
-        }
-        guard let savePath = ASBusinessFileManager.generateLocalURL(from: urlString, fileEx: fileEx, missingEx: missingEx,frontPathURL: ASBusinessFileManager.saveRingPathURL,completion: { string, error in
-            completion(nil,error)
-        })else { return nil }
-        
-        return TSNetworkShared.downloadFile(urlString: urlString,to: savePath, progressHandler:progressHandler,completion: completion)
-    }
-}
+//import AVFoundation
+//import Alamofire
+//
+//class ASDownloadManager {
+//    
+//    static func getDownLoadRing(urlString:String,progressHandler: ((Double) -> Void)? = nil,complete:@escaping (URL?,Bool)->Void){
+//        if let path = ASBusinessFileManager.getLocalURL(urlString: urlString,fileEx:nil,missingEx: "mp3") {
+//            complete(path,false)
+//        }else{
+//            _ = ASDownloadManager.downloadRing(urlString:urlString,missingEx: "mp3",progressHandler: progressHandler) { url, error in
+//                if let path = url {
+//                    complete(path,true)
+//                }else{
+//                    complete(nil,true)
+//                }
+//            }
+//        }
+//    }
+//    
+//    static func downloadRing(
+//        urlString: String,
+//        fileEx:String? = nil,
+//    missingEx:String? = nil,
+//        progressHandler: ((Double) -> Void)? = nil,
+//        completion: @escaping (URL?, Error?) -> Void
+//    ) -> DownloadRequest? {
+//        
+//        if let fileName = ASBusinessFileManager.getLocalURL(urlString: urlString,fileEx:fileEx,missingEx:missingEx){
+//            completion(fileName,nil)
+//            return nil
+//        }
+//        guard let savePath = ASBusinessFileManager.generateLocalURL(from: urlString, fileEx: fileEx, missingEx: missingEx,frontPathURL: ASBusinessFileManager.saveRingPathURL,completion: { string, error in
+//            completion(nil,error)
+//        })else { return nil }
+//        
+//        return TSNetworkShared.downloadFile(urlString: urlString,to: savePath, progressHandler:progressHandler,completion: completion)
+//    }
+//}

+ 3 - 5
AIPlayRingtones/Common/TSAudioPlayer/ASMediaPlayerController.swift

@@ -92,7 +92,7 @@ class ASMediaPlayerController {
     }
     
     func startPlayback(
-        of urlString: String?,
+        of urlString: String? = nil,
         localPath: URL? = nil,
         shouldLoop: Bool = false,
         index: IndexPath? = nil
@@ -141,7 +141,7 @@ class ASMediaPlayerController {
         } else {
             self.updateStatus(.buffering(0.0))
             
-            _ = ASMediaDownloader.fetchMediaResource(
+            ASMediaDownloader.fetchMediaResource(
                 remoteURL: mediaURL,
                 progressUpdate: { progress in
                     print("下载进度: \(progress)")
@@ -201,9 +201,7 @@ class ASMediaPlayerController {
             print("播放状态更新: \(status)")
         }
         currentStatus = status
-        DispatchQueue.main.async {
-            self.onStatusChange?(status)
-        }
+        self.onStatusChange?(status)
     }
     
     deinit {

+ 486 - 486
AIPlayRingtones/Common/TSAudioPlayer/TSBusinessAudioPlayer.swift

@@ -5,489 +5,489 @@
 //  Created by 100Years on 2025/3/7.
 //
 
-import AVFoundation
-class TSBusinessAudioPlayer {
-    
-    static let shared = TSBusinessAudioPlayer()
-    
-    enum PlayerState:Equatable {
-        case play
-        case pause
-        case stop
-        case loading(Float)
-        case volume(Float)
-        case currentTime(Double)
-    }
-    
-    private var audioPlayer: TSAudioPlayer?
-    
-    var stateChangedHandle:((PlayerState) -> Void)?
-    var currentTimeChangedHandle:((Double,Double) -> Void)?
-    
-    var currentPlayerState:PlayerState = .stop
-    var duration:Double{
-        if let audioPlayer = audioPlayer {
-            return audioPlayer.duration
-        }
-        return 0.0
-    }
-
-    var isPlaying:Bool{
-        if let audioPlayer = audioPlayer {
-            return audioPlayer.isPlaying
-        }
-        return false
-    }
-    
-    var isLoading:Bool{
-        switch currentPlayerState {
-        case .loading(let float):
-            return float < 1.0 ? true : false
-        default:
-            return false
-        }
-    }
-    
-    var currentTime:Double{
-        if let audioPlayer = audioPlayer {
-            return audioPlayer.currentTime
-        }
-        return 0.0
-    }
-    
-    /// 跳转到指定时间
-    /// - Parameter time: 目标时间(秒)
-    func seek(to time: Double) {
-        audioPlayer?.seek(to: time)
-    }
-    
-    var playProgress:Double{
-        let playProgress = currentTime / duration
-//        logPrint("TSAudioPlayer playProgress = \(playProgress)")
-        return playProgress
-    }
-    
-    //播放器是否可用
-    var playerUsable:Bool {
-        if let audioPlayer = audioPlayer {
-            return audioPlayer.playerUsable
-        }
-        return false
-    }
-    var currentURLString:String = ""
-    var currentLocalURL:URL? = nil
-    var currentIndexPath:IndexPath? = nil
-    
-    //加载音乐可能 2-3 秒有结果,停止加载后播放.
-    private var isStopPlayingAfterLoading:Bool = false
-
-    func isPlayURLString(string:String,localURL:URL? = nil,indexPath:IndexPath? = nil) -> Bool {
-
-        if currentURLString == string {
-            
-            if let currentIndexPath = currentIndexPath,
-               let indexPath = indexPath,
-               indexPath != currentIndexPath
-            {
-                return false
-            }else if let currentLocalURL = currentLocalURL,
-                let localURL = localURL,
-                currentLocalURL != localURL
-             {
-                 return false
-             }else{
-                return true
-            }
-        }
-        return false
-    }
-    
-    func loadLoactionURL(url:URL){
-        self.audioPlayer = TSAudioPlayer(url: url)
-    }
-
-    func playUrlString(_ urlString:String?,localURL:URL? = nil,loop:Bool = false,indexPath:IndexPath? = nil) {
-        self.stop()
-        if let urlString = urlString {
-            
-            self.currentURLString = urlString
-            self.currentLocalURL = localURL
-            self.currentIndexPath = indexPath
-
-            let palyFile:(URL)->Void = { [weak self] url in
-                guard let self = self else { return }
-                logPrint("TSAudioPlayer 正在播放url:\(currentURLString)")
-                logPrint("TSAudioPlayer 正在播放path:\(url)")
-                self.audioPlayer = TSAudioPlayer(url: url)
-                self.audioPlayer?.setLoop(loop)
-                
-                if self.audioPlayer?.volume == 0 {
-                    setVolume(volume: 1.0)
-                }
-                
-                self.audioPlayer?.currentTimeChanged = { [weak self] currentTime,duration in
-                    guard let self = self else { return }
-                    currentTimeChangedHandle?(currentTime,duration)
-                    changePlayerState(.currentTime(currentTime))
-                }
-                
-                self.play()
-                logPrint(self.audioPlayer?.duration)
-                
-                self.audioPlayer?.audioPlayerDidFinishHandle = { [weak self] flag in
-                    guard let self = self else { return }
-                    if flag == true, self.audioPlayer?.isLooping == false{
-                        stop()
-                    }
-                }
-            }
-            
-            isStopPlayingAfterLoading = false
-            
-            if let path = self.currentLocalURL,ASFileManager.fileExists(at: path){
-                palyFile(path) //播放
-                
-            }else{
-                self.changePlayerState(.loading(0.0))
-                
-                _ = ASDownloadManager.getDownLoadRing(urlString: urlString, progressHandler: { progress in
-                    logPrint("ASDownloadManager.etDownLoadRing progress = \(progress)")
-                }, complete: {[weak self] url, success in
-                    
-                    guard let self = self else { return }
-                    
-                    self.changePlayerState(.loading(1.0))
-                
-                    if isStopPlayingAfterLoading == true || currentURLString != urlString{
-                        isStopPlayingAfterLoading = false
-                        return
-                    }
-                    
-                    if let url = url {
-                        palyFile(url) //播放
-                    }else{
-                        //暂停
-                        self.stop()
-                    }
-                })
-            }
-        }
-    }
-    
-
-    func play() {
-        self.audioPlayer?.play()
-        changePlayerState(.play)
-    }
-    
-    func stop() {
-        self.audioPlayer?.currentTimeChanged = nil
-        isStopPlayingAfterLoading = true
-        currentURLString = ""
-        self.audioPlayer?.stop()
-        changePlayerState(.stop)
-    }
-    
-    func pause() {
-        isStopPlayingAfterLoading = true
-        self.audioPlayer?.pause()
-        changePlayerState(.pause)
-    }
-    
-    func setVolume(volume:Float){
-        self.audioPlayer?.volume = volume
-        changePlayerState(.volume(volume))
-    }
-    
-
-    func changeAudioSwitch()->Float {
-        let volume:Float = self.audioPlayer?.volume == 0.0 ? 1.0 : 0.0
-        setVolume(volume: volume)
-        return volume
-    }
-    
-    func changePlayerState(_ state:PlayerState){
-
-        if case .currentTime(let time) = state {} else {
-            logPrint("TSAudioPlayer changePlayerState=\(state)")
-        }
-        currentPlayerState = state
-        kExecuteOnMainThread{
-            self.stateChangedHandle?(state)
-//            NotificationCenter.default.post(name: .kBusinessAudioStateChange, object: nil, userInfo: ["PlayerState": state])
-        }
-    }
-     
-    deinit {
-        logPrint("TSAudioPlayer TSBusinessAudioPlayer deinit")
-    }
-}
-
-
-extension TSBusinessAudioPlayer{
-    struct AudioFileInfo {
-        let sizeInBytes: UInt64?    // 文件大小(字节)
-        let durationInSeconds: Double?  // 音频时长(秒)
-        let songName: String?  // 音频时长(秒)
-    }
-
-    static func getAudioFileInfo(path: String) -> AudioFileInfo? {
-        // 1. 检查URL有效性
-        guard let url = URL(string: path) else {
-            print("getAudioFileInfo 无效的URL字符串")
-            return nil
-        }
-        
-        // 2. 检查文件是否存在(仅限本地文件)
-        guard FileManager.default.fileExists(atPath: url.path) else {
-            print("getAudioFileInfo 文件不存在或不是本地路径")
-            return nil
-        }
-        
-        // 3. 获取文件大小
-        let fileSize: UInt64? = {
-            do {
-                let attributes = try FileManager.default.attributesOfItem(atPath: url.path)
-                return attributes[.size] as? UInt64
-            } catch {
-                print("获取文件大小失败: \(error.localizedDescription)")
-                return nil
-            }
-        }()
-        
-        // 4. 获取音频时长
-        let duration: Double? = {
-            return getAudioDurationWithAudioFile(url: url)
-        }()
-        
-        // 5. 获取音频名称
-        let songName: String? = {
-            return getSongNameFromLocalFile(fileURL: url)
-        }()
-        
-        return AudioFileInfo(sizeInBytes: fileSize, durationInSeconds: duration,songName: songName)
-    }
-    
-    /// 同步获取音频时长(可能阻塞线程!)
-    /// 使用 AudioFile 同步获取音频时长
-    static func getAudioDurationWithAudioFile(url: URL) -> TimeInterval? {
-        var audioFile: AudioFileID?
-        let status = AudioFileOpenURL(url as CFURL, .readPermission, 0, &audioFile)
-        
-        guard status == noErr, let file = audioFile else {
-            print("⚠️ 打开音频文件失败: \(status)")
-            return nil
-        }
-        
-        // 获取音频时长(单位:秒)
-        var duration: Float64 = 0
-        var propertySize = UInt32(MemoryLayout.size(ofValue: duration))
-        let durationStatus = AudioFileGetProperty(
-            file,
-            kAudioFilePropertyEstimatedDuration,
-            &propertySize,
-            &duration
-        )
-        
-        AudioFileClose(file)
-        
-        return durationStatus == noErr ? duration : nil
-    }
-    
-    //获取音频的名称
-    static func getSongNameFromLocalFile(fileURL: URL) -> String? {
-        // 1. 检查文件是否存在
-        guard FileManager.default.fileExists(atPath: fileURL.path) else {
-            print("文件不存在")
-            return nil
-        }
-        
-        // 2. 创建 AVAsset 对象(代表音频文件)
-        let asset = AVAsset(url: fileURL)
-        
-        // 3. 同步读取元数据(适用于本地文件)
-        var songName: String? = nil
-        let metadataFormats = asset.availableMetadataFormats
-        
-        for format in metadataFormats {
-            let metadata = asset.metadata(forFormat: format)
-            
-            // 4. 遍历元数据项,查找歌曲标题
-            for item in metadata {
-                if item.commonKey == .commonKeyTitle, // 标准键:标题
-                   let value = item.value as? String { // 确保值是字符串
-                    songName = value
-                    break
-                }
-                
-                // 额外检查 ID3 标签(某些 MP3 文件可能用非标准键)
-                if item.key as? String == "TIT2", // ID3v2 标题键
-                   let value = item.value as? String {
-                    songName = value
-                    break
-                }
-            }
-            
-            if songName != nil { break }
-        }
-        
-        // 5. 返回结果(若未找到,则尝试从文件名推断)
-        return songName ?? fileURL.deletingPathExtension().lastPathComponent
-    }
-}
-
-class TSAudioPlayer: NSObject {
-    private var player: AVPlayer?
-    private var timeObserverToken: Any?
-    var isLooping: Bool = false
-    
-    override init() {
-        super.init()
-    }
-    
-    var isPlaying: Bool {
-//        return player?.rate != 0 && player?.error == nil
-        
-        if let player = player {
-            if #available(iOS 10.0, *) {
-                return player.timeControlStatus == .playing
-            } else {
-                return player.rate > 0
-            }
-        }
-        return false
-    }
-    
-    var duration: Double {
-        if let currentItem = player?.currentItem {
-            return CMTimeGetSeconds(currentItem.asset.duration)
-        }
-        return 0.0
-    }
-    
-    var volume: Float {
-        get {
-            return player?.volume ?? 0.0
-        }
-        set {
-            player?.volume = max(0.0, min(newValue, 1.0))
-        }
-    }
-    
-    var currentTime: Double {
-        if let currentItem = player?.currentItem {
-            return CMTimeGetSeconds(currentItem.currentTime())
-        }
-        return 0.0
-    }
-    
-    var playerUsable: Bool {
-        return player != nil
-    }
-    
-    var currentTimeChanged: ((Double,Double) -> Void)?
-    var audioPlayerDidFinishHandle: ((Bool) -> Void)?
-    
-    /// 初始化播放器
-    /// - Parameter url: 音频文件的 URL
-    init?(url: URL) {
-        super.init()
-        
-        let playerItem = AVPlayerItem(url: url)
-        player = AVPlayer(playerItem: playerItem)
-        
-        // 监听播放完成事件
-        NotificationCenter.default.addObserver(
-            self,
-            selector: #selector(playerDidFinishPlaying),
-            name: .AVPlayerItemDidPlayToEndTime,
-            object: playerItem
-        )
-        
-        // 设置音频会话
-        do {
-            let audioSession = AVAudioSession.sharedInstance()
-            try audioSession.setCategory(.playback)
-            try audioSession.setActive(true)
-        } catch {
-            print("TSAudioPlayer 音频会话设置失败: \(error.localizedDescription)")
-            return nil
-        }
-    }
-    
-    deinit {
-        stop()
-    }
-    
-    /// 开始播放音频
-    func play() {
-        guard let player = player else { return }
-        
-        let outputVolume = AVAudioSession.sharedInstance().outputVolume
-        print("TSAudioPlayer outputVolume: \(outputVolume)")
-        
-        if outputVolume == 0.0 {
-            print("Please turn up the volume".localized)
-        }
-        
-        player.play()
-        
-        // 监听播放进度
-        addTimeObserver()
-    }
-    
-    /// 暂停播放音频
-    func pause() {
-        player?.pause()
-    }
-    
-    /// 停止并销毁播放器
-    func stop() {
-        player?.pause()
-        player?.replaceCurrentItem(with: nil)
-        player = nil
-        removeTimeObserver()
-    }
-    
-    /// 设置是否重复播放
-    /// - Parameter loop: 是否循环播放
-    func setLoop(_ loop: Bool) {
-        isLooping = loop
-    }
-    
-    /// 跳转到指定时间
-    /// - Parameter time: 目标时间(秒)
-    func seek(to time: Double) {
-        if let player = player {
-            let targetTime = CMTimeMakeWithSeconds(time, preferredTimescale: 600)
-            player.seek(to: targetTime)
-        }
-    }
-    
-    /// 监听播放完成
-    @objc private func playerDidFinishPlaying() {
-        if isLooping {
-            seek(to: 0.0)
-            play()
-        }
-        audioPlayerDidFinishHandle?(true)
-    }
-    
-    /// 添加时间观察者
-    private func addTimeObserver() {
-        let interval = CMTime(seconds: 0.1, preferredTimescale: CMTimeScale(NSEC_PER_SEC))
-        timeObserverToken = player?.addPeriodicTimeObserver(forInterval: interval, queue: .main) { [weak self] time in
-            guard let self = self else { return }
-            let currentTime = CMTimeGetSeconds(time)
-            self.currentTimeChanged?(currentTime,duration)
-        }
-    }
-    
-    /// 移除时间观察者
-    private func removeTimeObserver() {
-        if let token = timeObserverToken {
-            player?.removeTimeObserver(token)
-            timeObserverToken = nil
-        }
-    }
-}
+//import AVFoundation
+//class TSBusinessAudioPlayer {
+//    
+//    static let shared = TSBusinessAudioPlayer()
+//    
+//    enum PlayerState:Equatable {
+//        case play
+//        case pause
+//        case stop
+//        case loading(Float)
+//        case volume(Float)
+//        case currentTime(Double)
+//    }
+//    
+//    private var audioPlayer: TSAudioPlayer?
+//    
+//    var stateChangedHandle:((PlayerState) -> Void)?
+//    var currentTimeChangedHandle:((Double,Double) -> Void)?
+//    
+//    var currentPlayerState:PlayerState = .stop
+//    var duration:Double{
+//        if let audioPlayer = audioPlayer {
+//            return audioPlayer.duration
+//        }
+//        return 0.0
+//    }
+//
+//    var isPlaying:Bool{
+//        if let audioPlayer = audioPlayer {
+//            return audioPlayer.isPlaying
+//        }
+//        return false
+//    }
+//    
+//    var isLoading:Bool{
+//        switch currentPlayerState {
+//        case .loading(let float):
+//            return float < 1.0 ? true : false
+//        default:
+//            return false
+//        }
+//    }
+//    
+//    var currentTime:Double{
+//        if let audioPlayer = audioPlayer {
+//            return audioPlayer.currentTime
+//        }
+//        return 0.0
+//    }
+//    
+//    /// 跳转到指定时间
+//    /// - Parameter time: 目标时间(秒)
+//    func seek(to time: Double) {
+//        audioPlayer?.seek(to: time)
+//    }
+//    
+//    var playProgress:Double{
+//        let playProgress = currentTime / duration
+////        logPrint("TSAudioPlayer playProgress = \(playProgress)")
+//        return playProgress
+//    }
+//    
+//    //播放器是否可用
+//    var playerUsable:Bool {
+//        if let audioPlayer = audioPlayer {
+//            return audioPlayer.playerUsable
+//        }
+//        return false
+//    }
+//    var currentURLString:String = ""
+//    var currentLocalURL:URL? = nil
+//    var currentIndexPath:IndexPath? = nil
+//    
+//    //加载音乐可能 2-3 秒有结果,停止加载后播放.
+//    private var isStopPlayingAfterLoading:Bool = false
+//
+//    func isPlayURLString(string:String,localURL:URL? = nil,indexPath:IndexPath? = nil) -> Bool {
+//
+//        if currentURLString == string {
+//            
+//            if let currentIndexPath = currentIndexPath,
+//               let indexPath = indexPath,
+//               indexPath != currentIndexPath
+//            {
+//                return false
+//            }else if let currentLocalURL = currentLocalURL,
+//                let localURL = localURL,
+//                currentLocalURL != localURL
+//             {
+//                 return false
+//             }else{
+//                return true
+//            }
+//        }
+//        return false
+//    }
+//    
+//    func loadLoactionURL(url:URL){
+//        self.audioPlayer = TSAudioPlayer(url: url)
+//    }
+//
+//    func playUrlString(_ urlString:String?,localURL:URL? = nil,loop:Bool = false,indexPath:IndexPath? = nil) {
+//        self.stop()
+//        if let urlString = urlString {
+//            
+//            self.currentURLString = urlString
+//            self.currentLocalURL = localURL
+//            self.currentIndexPath = indexPath
+//
+//            let palyFile:(URL)->Void = { [weak self] url in
+//                guard let self = self else { return }
+//                logPrint("TSAudioPlayer 正在播放url:\(currentURLString)")
+//                logPrint("TSAudioPlayer 正在播放path:\(url)")
+//                self.audioPlayer = TSAudioPlayer(url: url)
+//                self.audioPlayer?.setLoop(loop)
+//                
+//                if self.audioPlayer?.volume == 0 {
+//                    setVolume(volume: 1.0)
+//                }
+//                
+//                self.audioPlayer?.currentTimeChanged = { [weak self] currentTime,duration in
+//                    guard let self = self else { return }
+//                    currentTimeChangedHandle?(currentTime,duration)
+//                    changePlayerState(.currentTime(currentTime))
+//                }
+//                
+//                self.play()
+//                logPrint(self.audioPlayer?.duration)
+//                
+//                self.audioPlayer?.audioPlayerDidFinishHandle = { [weak self] flag in
+//                    guard let self = self else { return }
+//                    if flag == true, self.audioPlayer?.isLooping == false{
+//                        stop()
+//                    }
+//                }
+//            }
+//            
+//            isStopPlayingAfterLoading = false
+//            
+//            if let path = self.currentLocalURL,ASFileManager.fileExists(at: path){
+//                palyFile(path) //播放
+//                
+//            }else{
+//                self.changePlayerState(.loading(0.0))
+//                
+//                _ = ASDownloadManager.getDownLoadRing(urlString: urlString, progressHandler: { progress in
+//                    logPrint("ASDownloadManager.etDownLoadRing progress = \(progress)")
+//                }, complete: {[weak self] url, success in
+//                    
+//                    guard let self = self else { return }
+//                    
+//                    self.changePlayerState(.loading(1.0))
+//                
+//                    if isStopPlayingAfterLoading == true || currentURLString != urlString{
+//                        isStopPlayingAfterLoading = false
+//                        return
+//                    }
+//                    
+//                    if let url = url {
+//                        palyFile(url) //播放
+//                    }else{
+//                        //暂停
+//                        self.stop()
+//                    }
+//                })
+//            }
+//        }
+//    }
+//    
+//
+//    func play() {
+//        self.audioPlayer?.play()
+//        changePlayerState(.play)
+//    }
+//    
+//    func stop() {
+//        self.audioPlayer?.currentTimeChanged = nil
+//        isStopPlayingAfterLoading = true
+//        currentURLString = ""
+//        self.audioPlayer?.stop()
+//        changePlayerState(.stop)
+//    }
+//    
+//    func pause() {
+//        isStopPlayingAfterLoading = true
+//        self.audioPlayer?.pause()
+//        changePlayerState(.pause)
+//    }
+//    
+//    func setVolume(volume:Float){
+//        self.audioPlayer?.volume = volume
+//        changePlayerState(.volume(volume))
+//    }
+//    
+//
+//    func changeAudioSwitch()->Float {
+//        let volume:Float = self.audioPlayer?.volume == 0.0 ? 1.0 : 0.0
+//        setVolume(volume: volume)
+//        return volume
+//    }
+//    
+//    func changePlayerState(_ state:PlayerState){
+//
+//        if case .currentTime(let time) = state {} else {
+//            logPrint("TSAudioPlayer changePlayerState=\(state)")
+//        }
+//        currentPlayerState = state
+//        kExecuteOnMainThread{
+//            self.stateChangedHandle?(state)
+////            NotificationCenter.default.post(name: .kBusinessAudioStateChange, object: nil, userInfo: ["PlayerState": state])
+//        }
+//    }
+//     
+//    deinit {
+//        logPrint("TSAudioPlayer TSBusinessAudioPlayer deinit")
+//    }
+//}
+//
+//
+//extension TSBusinessAudioPlayer{
+//    struct AudioFileInfo {
+//        let sizeInBytes: UInt64?    // 文件大小(字节)
+//        let durationInSeconds: Double?  // 音频时长(秒)
+//        let songName: String?  // 音频时长(秒)
+//    }
+//
+//    static func getAudioFileInfo(path: String) -> AudioFileInfo? {
+//        // 1. 检查URL有效性
+//        guard let url = URL(string: path) else {
+//            print("getAudioFileInfo 无效的URL字符串")
+//            return nil
+//        }
+//        
+//        // 2. 检查文件是否存在(仅限本地文件)
+//        guard FileManager.default.fileExists(atPath: url.path) else {
+//            print("getAudioFileInfo 文件不存在或不是本地路径")
+//            return nil
+//        }
+//        
+//        // 3. 获取文件大小
+//        let fileSize: UInt64? = {
+//            do {
+//                let attributes = try FileManager.default.attributesOfItem(atPath: url.path)
+//                return attributes[.size] as? UInt64
+//            } catch {
+//                print("获取文件大小失败: \(error.localizedDescription)")
+//                return nil
+//            }
+//        }()
+//        
+//        // 4. 获取音频时长
+//        let duration: Double? = {
+//            return getAudioDurationWithAudioFile(url: url)
+//        }()
+//        
+//        // 5. 获取音频名称
+//        let songName: String? = {
+//            return getSongNameFromLocalFile(fileURL: url)
+//        }()
+//        
+//        return AudioFileInfo(sizeInBytes: fileSize, durationInSeconds: duration,songName: songName)
+//    }
+//    
+//    /// 同步获取音频时长(可能阻塞线程!)
+//    /// 使用 AudioFile 同步获取音频时长
+//    static func getAudioDurationWithAudioFile(url: URL) -> TimeInterval? {
+//        var audioFile: AudioFileID?
+//        let status = AudioFileOpenURL(url as CFURL, .readPermission, 0, &audioFile)
+//        
+//        guard status == noErr, let file = audioFile else {
+//            print("⚠️ 打开音频文件失败: \(status)")
+//            return nil
+//        }
+//        
+//        // 获取音频时长(单位:秒)
+//        var duration: Float64 = 0
+//        var propertySize = UInt32(MemoryLayout.size(ofValue: duration))
+//        let durationStatus = AudioFileGetProperty(
+//            file,
+//            kAudioFilePropertyEstimatedDuration,
+//            &propertySize,
+//            &duration
+//        )
+//        
+//        AudioFileClose(file)
+//        
+//        return durationStatus == noErr ? duration : nil
+//    }
+//    
+//    //获取音频的名称
+//    static func getSongNameFromLocalFile(fileURL: URL) -> String? {
+//        // 1. 检查文件是否存在
+//        guard FileManager.default.fileExists(atPath: fileURL.path) else {
+//            print("文件不存在")
+//            return nil
+//        }
+//        
+//        // 2. 创建 AVAsset 对象(代表音频文件)
+//        let asset = AVAsset(url: fileURL)
+//        
+//        // 3. 同步读取元数据(适用于本地文件)
+//        var songName: String? = nil
+//        let metadataFormats = asset.availableMetadataFormats
+//        
+//        for format in metadataFormats {
+//            let metadata = asset.metadata(forFormat: format)
+//            
+//            // 4. 遍历元数据项,查找歌曲标题
+//            for item in metadata {
+//                if item.commonKey == .commonKeyTitle, // 标准键:标题
+//                   let value = item.value as? String { // 确保值是字符串
+//                    songName = value
+//                    break
+//                }
+//                
+//                // 额外检查 ID3 标签(某些 MP3 文件可能用非标准键)
+//                if item.key as? String == "TIT2", // ID3v2 标题键
+//                   let value = item.value as? String {
+//                    songName = value
+//                    break
+//                }
+//            }
+//            
+//            if songName != nil { break }
+//        }
+//        
+//        // 5. 返回结果(若未找到,则尝试从文件名推断)
+//        return songName ?? fileURL.deletingPathExtension().lastPathComponent
+//    }
+//}
+//
+//class TSAudioPlayer: NSObject {
+//    private var player: AVPlayer?
+//    private var timeObserverToken: Any?
+//    var isLooping: Bool = false
+//    
+//    override init() {
+//        super.init()
+//    }
+//    
+//    var isPlaying: Bool {
+////        return player?.rate != 0 && player?.error == nil
+//        
+//        if let player = player {
+//            if #available(iOS 10.0, *) {
+//                return player.timeControlStatus == .playing
+//            } else {
+//                return player.rate > 0
+//            }
+//        }
+//        return false
+//    }
+//    
+//    var duration: Double {
+//        if let currentItem = player?.currentItem {
+//            return CMTimeGetSeconds(currentItem.asset.duration)
+//        }
+//        return 0.0
+//    }
+//    
+//    var volume: Float {
+//        get {
+//            return player?.volume ?? 0.0
+//        }
+//        set {
+//            player?.volume = max(0.0, min(newValue, 1.0))
+//        }
+//    }
+//    
+//    var currentTime: Double {
+//        if let currentItem = player?.currentItem {
+//            return CMTimeGetSeconds(currentItem.currentTime())
+//        }
+//        return 0.0
+//    }
+//    
+//    var playerUsable: Bool {
+//        return player != nil
+//    }
+//    
+//    var currentTimeChanged: ((Double,Double) -> Void)?
+//    var audioPlayerDidFinishHandle: ((Bool) -> Void)?
+//    
+//    /// 初始化播放器
+//    /// - Parameter url: 音频文件的 URL
+//    init?(url: URL) {
+//        super.init()
+//        
+//        let playerItem = AVPlayerItem(url: url)
+//        player = AVPlayer(playerItem: playerItem)
+//        
+//        // 监听播放完成事件
+//        NotificationCenter.default.addObserver(
+//            self,
+//            selector: #selector(playerDidFinishPlaying),
+//            name: .AVPlayerItemDidPlayToEndTime,
+//            object: playerItem
+//        )
+//        
+//        // 设置音频会话
+//        do {
+//            let audioSession = AVAudioSession.sharedInstance()
+//            try audioSession.setCategory(.playback)
+//            try audioSession.setActive(true)
+//        } catch {
+//            print("TSAudioPlayer 音频会话设置失败: \(error.localizedDescription)")
+//            return nil
+//        }
+//    }
+//    
+//    deinit {
+//        stop()
+//    }
+//    
+//    /// 开始播放音频
+//    func play() {
+//        guard let player = player else { return }
+//        
+//        let outputVolume = AVAudioSession.sharedInstance().outputVolume
+//        print("TSAudioPlayer outputVolume: \(outputVolume)")
+//        
+//        if outputVolume == 0.0 {
+//            print("Please turn up the volume".localized)
+//        }
+//        
+//        player.play()
+//        
+//        // 监听播放进度
+//        addTimeObserver()
+//    }
+//    
+//    /// 暂停播放音频
+//    func pause() {
+//        player?.pause()
+//    }
+//    
+//    /// 停止并销毁播放器
+//    func stop() {
+//        player?.pause()
+//        player?.replaceCurrentItem(with: nil)
+//        player = nil
+//        removeTimeObserver()
+//    }
+//    
+//    /// 设置是否重复播放
+//    /// - Parameter loop: 是否循环播放
+//    func setLoop(_ loop: Bool) {
+//        isLooping = loop
+//    }
+//    
+//    /// 跳转到指定时间
+//    /// - Parameter time: 目标时间(秒)
+//    func seek(to time: Double) {
+//        if let player = player {
+//            let targetTime = CMTimeMakeWithSeconds(time, preferredTimescale: 600)
+//            player.seek(to: targetTime)
+//        }
+//    }
+//    
+//    /// 监听播放完成
+//    @objc private func playerDidFinishPlaying() {
+//        if isLooping {
+//            seek(to: 0.0)
+//            play()
+//        }
+//        audioPlayerDidFinishHandle?(true)
+//    }
+//    
+//    /// 添加时间观察者
+//    private func addTimeObserver() {
+//        let interval = CMTime(seconds: 0.1, preferredTimescale: CMTimeScale(NSEC_PER_SEC))
+//        timeObserverToken = player?.addPeriodicTimeObserver(forInterval: interval, queue: .main) { [weak self] time in
+//            guard let self = self else { return }
+//            let currentTime = CMTimeGetSeconds(time)
+//            self.currentTimeChanged?(currentTime,duration)
+//        }
+//    }
+//    
+//    /// 移除时间观察者
+//    private func removeTimeObserver() {
+//        if let token = timeObserverToken {
+//            player?.removeTimeObserver(token)
+//            timeObserverToken = nil
+//        }
+//    }
+//}

+ 7 - 7
AIPlayRingtones/CommonView/ASRingToneCellView.swift

@@ -191,7 +191,7 @@ class ASRingToneCellView: ASBaseView {
 extension ASRingToneCellView {
     
     func monitorPlayStateDefaultHandle(){
-        TSBusinessAudioPlayer.shared.stateChangedHandle = { [weak self] state  in
+        ASMediaPlayerController.main.onStatusChange = { [weak self] state  in
             guard let self = self else { return }
             DispatchQueue.main.async {
                 self.handelAudioPlayerStateChange(state: state)
@@ -199,26 +199,26 @@ extension ASRingToneCellView {
         }
     }
     
-    func handelAudioPlayerStateChange(state:TSBusinessAudioPlayer.PlayerState){
+    func handelAudioPlayerStateChange(state:ASMediaPlayerController.PlaybackStatus){
         logPrint("ASRingToneCellView handelAudioPlayerStateChange=\(state),self=\(self)")
         switch state {
-        case .loading(let progress):
+        case .buffering(let progress):
             if progress == 0.0 {
                 self.isloading = true
             }else if progress == 1.0 {
                 self.isloading = false
             }
-        case .play:
+        case .playing:
             self.isPlay = true
-        case .stop:
+        case .stopped:
             self.isloading = false
             self.isPlay = false
             self.progressView.isHidden = true
             self.progressView.progress = 0.0
-        case .currentTime(_):
+        case .timeUpdated(_):
             self.isPlay = true
             self.progressView.isHidden = false
-            self.progressView.progress = Float(TSBusinessAudioPlayer.shared.playProgress)
+            self.progressView.progress = Float(ASMediaPlayerController.main.playbackProgress)
         default:
             break
         }

+ 5 - 5
AIPlayRingtones/OperationQueue/Generate/ASGenerateBaseOperation.swift

@@ -153,23 +153,23 @@ class ASGenerateBaseOperation: ASBaseOperation , @unchecked Sendable{
                         }
                         
                         if URL(string:genmojiModel.response.musicUrl) != nil {
-                            ASDownloadManager.getDownLoadRing(urlString: genmojiModel.response.musicUrl) { [weak self]  progress in
+                            ASMediaDownloader.fetchMediaResource(remoteURL: genmojiModel.response.musicUrl) { [weak self]  progress in
                                     guard let self = self else { return }
                                     let progressInt = Int(progress*10.0)
                                     let progressString = "Generating".localized + " \(90 + progressInt)%"
                                 stateDatauPblished = (.progress(kPercentScale+Float(progress)*0.1,progressString),currentActionInfoModel)
                                     logPrint("生成后下载进度 \(progress)")
-                            } complete: { [weak self] url, success in
+                            } completion: { [weak self] url, success in
                                 guard let self = self else { return }
                                 if let url = url {
                                     genmojiModel.ringSavePath = url.path.documentLastURL
                  
-                                    if let info = TSBusinessAudioPlayer.getAudioFileInfo(path: url.path) {
-                                        if let duration = info.durationInSeconds {
+                                    if let info = ASMediaPlayerController.analyzeMediaFile(at: url.path) {
+                                        if let duration = info.duration {
                                             genmojiModel.response.duration = Int(duration)
                                         }
                                         
-                                        if let size = info.sizeInBytes {
+                                        if let size = info.fileSize {
                                             genmojiModel.response.size = Int(size)
                                         }
                                     }