From b1aee4992ff26df0e1d2f15fa489aeb650054cb2 Mon Sep 17 00:00:00 2001 From: zirkc Date: Wed, 17 Jul 2024 15:06:13 -0700 Subject: [PATCH] Update Plugin.swift --- ios/Plugin/Plugin.swift | 223 +++++++++++++++++++--------------------- 1 file changed, 105 insertions(+), 118 deletions(-) diff --git a/ios/Plugin/Plugin.swift b/ios/Plugin/Plugin.swift index 19cf1d3..7052525 100644 --- a/ios/Plugin/Plugin.swift +++ b/ios/Plugin/Plugin.swift @@ -14,7 +14,8 @@ enum MyError: Error { @objc(NativeAudio) public class NativeAudio: CAPPlugin { - var audioList: [String: Any] = [:] + private var audioList: [String: Any] = [:] + private let lock = NSLock() var fadeMusic = false var session = AVAudioSession.sharedInstance() @@ -32,17 +33,20 @@ public class NativeAudio: CAPPlugin { } @objc func configure(_ call: CAPPluginCall) { - self.fadeMusic = call.getBool(Constant.FadeKey, false) - do { - if call.getBool(Constant.FocusAudio, false) { - try self.session.setCategory(AVAudioSession.Category.playback) - } else { - try self.session.setCategory(AVAudioSession.Category.ambient) + if let fade = call.getBool(Constant.FadeKey) { + self.fadeMusic = fade + } + if let focus = call.getBool(Constant.FocusAudio) { + do { + if focus { + try self.session.setCategory(AVAudioSession.Category.playback) + } else { + try self.session.setCategory(AVAudioSession.Category.ambient) + } + } catch { + print("Failed to set setCategory audio") } - } catch { - print("Failed to set setCategory audio") } - call.resolve() } @objc func preload(_ call: CAPPluginCall) { @@ -53,29 +57,23 @@ public class NativeAudio: CAPPlugin { let audioId = call.getString(Constant.AssetIdKey) ?? "" let time = call.getDouble("time") ?? 0 if audioId != "" { - let queue = DispatchQueue(label: "com.getcapacitor.community.audio.complex.queue", qos: .userInitiated) - - queue.async { - if self.audioList.count > 0 { - let asset = self.audioList[audioId] - - if asset != nil { - if asset is AudioAsset { - let audioAsset = asset as? AudioAsset - - if self.fadeMusic { - audioAsset?.playWithFade(time: time) - } else { - audioAsset?.play(time: time) - } - call.resolve() - } else if asset is Int32 { - let audioAsset = asset as? NSNumber ?? 0 - AudioServicesPlaySystemSound(SystemSoundID(audioAsset.intValue )) - call.resolve() + DispatchQueue.global(qos: .userInitiated).async { + self.lock.lock() + defer { self.lock.unlock() } + + if let asset = self.audioList[audioId] { + if let audioAsset = asset as? AudioAsset { + if self.fadeMusic { + audioAsset.playWithFade(time: time) } else { - call.reject(Constant.ErrorAssetNotFound) + audioAsset.play(time: time) } + call.resolve() + } else if let audioAsset = asset as? NSNumber { + AudioServicesPlaySystemSound(SystemSoundID(audioAsset.intValue)) + call.resolve() + } else { + call.reject(Constant.ErrorAssetNotFound) } } } @@ -84,42 +82,40 @@ public class NativeAudio: CAPPlugin { @objc private func getAudioAsset(_ call: CAPPluginCall) -> AudioAsset? { let audioId = call.getString(Constant.AssetIdKey) ?? "" - if audioId == "" { + if audioId.isEmpty { call.reject(Constant.ErrorAssetId) return nil } - if self.audioList.count > 0 { - let asset = self.audioList[audioId] - if asset != nil && asset is AudioAsset { - return asset as? AudioAsset - } + + lock.lock() + defer { lock.unlock() } + + if let asset = self.audioList[audioId], asset is AudioAsset { + return asset as? AudioAsset } + call.reject(Constant.ErrorAssetNotFound + " - " + audioId) return nil } @objc func getDuration(_ call: CAPPluginCall) { - guard let audioAsset: AudioAsset = self.getAudioAsset(call) else { + guard let audioAsset = self.getAudioAsset(call) else { return } - call.resolve([ - "duration": audioAsset.getDuration() - ]) + call.resolve(["duration": audioAsset.getDuration()]) } @objc func getCurrentTime(_ call: CAPPluginCall) { - guard let audioAsset: AudioAsset = self.getAudioAsset(call) else { + guard let audioAsset = self.getAudioAsset(call) else { return } - call.resolve([ - "currentTime": audioAsset.getCurrentTime() - ]) + call.resolve(["currentTime": audioAsset.getCurrentTime()]) } @objc func resume(_ call: CAPPluginCall) { - guard let audioAsset: AudioAsset = self.getAudioAsset(call) else { + guard let audioAsset = self.getAudioAsset(call) else { return } @@ -128,7 +124,7 @@ public class NativeAudio: CAPPlugin { } @objc func pause(_ call: CAPPluginCall) { - guard let audioAsset: AudioAsset = self.getAudioAsset(call) else { + guard let audioAsset = self.getAudioAsset(call) else { return } @@ -148,7 +144,7 @@ public class NativeAudio: CAPPlugin { } @objc func loop(_ call: CAPPluginCall) { - guard let audioAsset: AudioAsset = self.getAudioAsset(call) else { + guard let audioAsset = self.getAudioAsset(call) else { return } @@ -158,19 +154,19 @@ public class NativeAudio: CAPPlugin { @objc func unload(_ call: CAPPluginCall) { let audioId = call.getString(Constant.AssetIdKey) ?? "" - if self.audioList.count > 0 { - let asset = self.audioList[audioId] - if asset != nil && asset is AudioAsset { - let audioAsset = asset as! AudioAsset - audioAsset.unload() - self.audioList[audioId] = nil - } + lock.lock() + defer { lock.unlock() } + + if let asset = self.audioList[audioId], asset is AudioAsset { + (asset as? AudioAsset)?.unload() + self.audioList[audioId] = nil } + call.resolve() } @objc func setVolume(_ call: CAPPluginCall) { - guard let audioAsset: AudioAsset = self.getAudioAsset(call) else { + guard let audioAsset = self.getAudioAsset(call) else { return } @@ -181,95 +177,86 @@ public class NativeAudio: CAPPlugin { } @objc func isPlaying(_ call: CAPPluginCall) { - guard let audioAsset: AudioAsset = self.getAudioAsset(call) else { + guard let audioAsset = self.getAudioAsset(call) else { return } - call.resolve([ - "isPlaying": audioAsset.isPlaying() - ]) + call.resolve(["isPlaying": audioAsset.isPlaying()]) } private func preloadAsset(_ call: CAPPluginCall, isComplex complex: Bool) { let audioId = call.getString(Constant.AssetIdKey) ?? "" + guard !audioId.isEmpty else { return } + let channels: NSNumber? let volume: Float? let delay: NSNumber? let isUrl: Bool? - if audioId != "" { - let assetPath: String = call.getString(Constant.AssetPathKey) ?? "" - - if complex { - volume = call.getFloat("volume") ?? 1.0 - channels = NSNumber(value: call.getInt("channels") ?? 1) - delay = NSNumber(value: call.getInt("delay") ?? 1) - isUrl = call.getBool("isUrl") ?? false - } else { - channels = 0 - volume = 0 - delay = 0 - isUrl = false - } + let assetPath: String = call.getString(Constant.AssetPathKey) ?? "" + + if complex { + volume = call.getFloat("volume") ?? 1.0 + channels = NSNumber(value: call.getInt("channels") ?? 1) + delay = NSNumber(value: call.getInt("delay") ?? 1) + isUrl = call.getBool("isUrl") ?? false + } else { + channels = 0 + volume = 0 + delay = 0 + isUrl = false + } - if audioList.isEmpty { - audioList = [:] - } + DispatchQueue.global(qos: .userInitiated).async { + self.lock.lock() + defer { self.lock.unlock() } - let asset = audioList[audioId] - let queue = DispatchQueue(label: "com.getcapacitor.community.audio.simple.queue", qos: .userInitiated) + if self.audioList[audioId] == nil { + var basePath: String? + if isUrl == false { + let assetPathSplit = assetPath.components(separatedBy: ".") + basePath = Bundle.main.path(forResource: assetPathSplit[0], ofType: assetPathSplit[1]) + } else { + let url = URL(string: assetPath) + basePath = url?.path + } - queue.async { - if asset == nil { - var basePath: String? - if isUrl == false { - let assetPathSplit = assetPath.components(separatedBy: ".") - basePath = Bundle.main.path(forResource: assetPathSplit[0], ofType: assetPathSplit[1]) + if let basePath = basePath, FileManager.default.fileExists(atPath: basePath) { + if !complex { + let pathUrl = URL(fileURLWithPath: basePath) + let soundFileUrl: CFURL = pathUrl as CFURL + var soundId = SystemSoundID() + AudioServicesCreateSystemSoundID(soundFileUrl, &soundId) + self.audioList[audioId] = NSNumber(value: Int32(soundId)) + call.resolve() } else { - let url = URL(string: assetPath) - basePath = url!.path - } - - if FileManager.default.fileExists(atPath: basePath ?? "") { - if !complex { - let pathUrl = URL(fileURLWithPath: basePath ?? "") - let soundFileUrl: CFURL = CFBridgingRetain(pathUrl) as! CFURL - var soundId = SystemSoundID() - AudioServicesCreateSystemSoundID(soundFileUrl, &soundId) - self.audioList[audioId] = NSNumber(value: Int32(soundId)) - call.resolve() - } else { - let audioAsset: AudioAsset = AudioAsset(owner: self, withAssetId: audioId, withPath: basePath, withChannels: channels, withVolume: volume as NSNumber?, withFadeDelay: delay) - self.audioList[audioId] = audioAsset - call.resolve() - } - } else { - call.reject(Constant.ErrorAssetPath + " - " + assetPath) + let audioAsset = AudioAsset(owner: self, withAssetId: audioId, withPath: basePath, withChannels: channels, withVolume: volume as NSNumber?, withFadeDelay: delay) + self.audioList[audioId] = audioAsset + call.resolve() } } else { - call.reject(Constant.ErrorAssetExists) + call.reject(Constant.ErrorAssetPath + " - " + assetPath) } + } else { + call.reject(Constant.ErrorAssetExists) } } } private func stopAudio(audioId: String) throws { - if self.audioList.count > 0 { - let asset = self.audioList[audioId] - - if asset != nil { - if asset is AudioAsset { - let audioAsset = asset as? AudioAsset + lock.lock() + defer { lock.unlock() } - if self.fadeMusic { - audioAsset?.playWithFade(time: audioAsset?.getCurrentTime() ?? 0) - } else { - audioAsset?.stop() - } + if let asset = self.audioList[audioId] { + if let audioAsset = asset as? AudioAsset { + if self.fadeMusic { + audioAsset.playWithFade(time: audioAsset.getCurrentTime()) + } else { + audioAsset.stop() } - } else { - throw MyError.runtimeError(Constant.ErrorAssetNotFound) } + } else { + throw MyError.runtimeError(Constant.ErrorAssetNotFound) } } }