@capgo/native-audio 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/CapgoNativeAudio.podspec +16 -0
  2. package/LICENSE +21 -0
  3. package/README.md +394 -0
  4. package/android/build.gradle +55 -0
  5. package/android/src/main/AndroidManifest.xml +5 -0
  6. package/android/src/main/java/ee/forgr/audio/AudioAsset.java +140 -0
  7. package/android/src/main/java/ee/forgr/audio/AudioDispatcher.java +178 -0
  8. package/android/src/main/java/ee/forgr/audio/Constant.java +18 -0
  9. package/android/src/main/java/ee/forgr/audio/NativeAudio.java +471 -0
  10. package/android/src/main/res/layout/bridge_layout_main.xml +15 -0
  11. package/android/src/main/res/values/colors.xml +3 -0
  12. package/android/src/main/res/values/strings.xml +3 -0
  13. package/android/src/main/res/values/styles.xml +3 -0
  14. package/dist/docs.json +279 -0
  15. package/dist/esm/audio-asset.d.ts +4 -0
  16. package/dist/esm/audio-asset.js +6 -0
  17. package/dist/esm/audio-asset.js.map +1 -0
  18. package/dist/esm/definitions.d.ts +53 -0
  19. package/dist/esm/definitions.js +2 -0
  20. package/dist/esm/definitions.js.map +1 -0
  21. package/dist/esm/index.d.ts +4 -0
  22. package/dist/esm/index.js +7 -0
  23. package/dist/esm/index.js.map +1 -0
  24. package/dist/esm/web.d.ts +52 -0
  25. package/dist/esm/web.js +113 -0
  26. package/dist/esm/web.js.map +1 -0
  27. package/dist/plugin.cjs.js +134 -0
  28. package/dist/plugin.cjs.js.map +1 -0
  29. package/dist/plugin.js +137 -0
  30. package/dist/plugin.js.map +1 -0
  31. package/ios/Plugin/AudioAsset.swift +184 -0
  32. package/ios/Plugin/Constant.swift +20 -0
  33. package/ios/Plugin/Info.plist +24 -0
  34. package/ios/Plugin/Plugin.h +10 -0
  35. package/ios/Plugin/Plugin.m +19 -0
  36. package/ios/Plugin/Plugin.swift +276 -0
  37. package/package.json +91 -0
@@ -0,0 +1,276 @@
1
+ import AVFoundation
2
+ import Foundation
3
+ import Capacitor
4
+ import CoreAudio
5
+
6
+ enum MyError: Error {
7
+ case runtimeError(String)
8
+ }
9
+
10
+ /**
11
+ * Please read the Capacitor iOS Plugin Development Guide
12
+ * here: https://capacitor.ionicframework.com/docs/plugins/ios
13
+ */
14
+ @objc(NativeAudio)
15
+ public class NativeAudio: CAPPlugin {
16
+
17
+ var audioList: [String : Any] = [:]
18
+ var fadeMusic = false
19
+ var session = AVAudioSession.sharedInstance()
20
+
21
+ public override func load() {
22
+ super.load()
23
+
24
+ self.fadeMusic = false
25
+
26
+ do {
27
+ try self.session.setCategory(AVAudioSession.Category.playback)
28
+ try self.session.setActive(false)
29
+ } catch {
30
+ print("Failed to set session category")
31
+ }
32
+ }
33
+
34
+ @objc func configure(_ call: CAPPluginCall) {
35
+ if let fade = call.getBool(Constant.FadeKey) {
36
+ self.fadeMusic = fade
37
+ }
38
+ if let focus = call.getBool(Constant.FocusAudio) {
39
+ do {
40
+ if focus {
41
+ try self.session.setCategory(AVAudioSession.Category.playback)
42
+ } else {
43
+ try self.session.setCategory(AVAudioSession.Category.ambient)
44
+ }
45
+ } catch {
46
+ print("Failed to set setCategory audio")
47
+ }
48
+ }
49
+ }
50
+
51
+ @objc func preload(_ call: CAPPluginCall) {
52
+ preloadAsset(call, isComplex: true)
53
+ }
54
+
55
+ @objc func play(_ call: CAPPluginCall) {
56
+ let audioId = call.getString(Constant.AssetIdKey) ?? ""
57
+ let time = call.getDouble("time") ?? 0
58
+ if audioId != "" {
59
+ let queue = DispatchQueue(label: "ee.forgr.audio.complex.queue", qos: .userInitiated)
60
+
61
+ queue.async {
62
+ if self.audioList.count > 0 {
63
+ let asset = self.audioList[audioId]
64
+
65
+ if asset != nil {
66
+ if asset is AudioAsset {
67
+ let audioAsset = asset as? AudioAsset
68
+
69
+ if self.fadeMusic {
70
+ audioAsset?.playWithFade(time: time)
71
+ } else {
72
+ audioAsset?.play(time: time)
73
+ }
74
+ call.resolve()
75
+ } else if (asset is Int32) {
76
+ let audioAsset = asset as? NSNumber ?? 0
77
+ AudioServicesPlaySystemSound(SystemSoundID(audioAsset.intValue ))
78
+ call.resolve()
79
+ } else {
80
+ call.reject(Constant.ErrorAssetNotFound)
81
+ }
82
+ }
83
+ }
84
+ }
85
+ }
86
+ }
87
+
88
+ @objc private func getAudioAsset(_ call: CAPPluginCall) -> AudioAsset? {
89
+ let audioId = call.getString(Constant.AssetIdKey) ?? ""
90
+ if audioId == "" {
91
+ call.reject(Constant.ErrorAssetId)
92
+ return nil
93
+ }
94
+ if self.audioList.count > 0 {
95
+ let asset = self.audioList[audioId]
96
+ if asset != nil && asset is AudioAsset {
97
+ return asset as? AudioAsset
98
+ }
99
+ }
100
+ call.reject(Constant.ErrorAssetNotFound + " - " + audioId)
101
+ return nil
102
+ }
103
+
104
+
105
+ @objc func getDuration(_ call: CAPPluginCall) {
106
+ guard let audioAsset: AudioAsset = self.getAudioAsset(call) else {
107
+ return
108
+ }
109
+
110
+ call.resolve([
111
+ "duration": audioAsset.getDuration()
112
+ ])
113
+ }
114
+
115
+ @objc func getCurrentTime(_ call: CAPPluginCall) {
116
+ guard let audioAsset: AudioAsset = self.getAudioAsset(call) else {
117
+ return
118
+ }
119
+
120
+ call.resolve([
121
+ "currentTime": audioAsset.getCurrentTime()
122
+ ])
123
+ }
124
+
125
+ @objc func resume(_ call: CAPPluginCall) {
126
+ guard let audioAsset: AudioAsset = self.getAudioAsset(call) else {
127
+ return
128
+ }
129
+
130
+ audioAsset.resume()
131
+ call.resolve()
132
+ }
133
+
134
+ @objc func pause(_ call: CAPPluginCall) {
135
+ guard let audioAsset: AudioAsset = self.getAudioAsset(call) else {
136
+ return
137
+ }
138
+
139
+ audioAsset.pause()
140
+ call.resolve()
141
+ }
142
+
143
+ @objc func stop(_ call: CAPPluginCall) {
144
+ let audioId = call.getString(Constant.AssetIdKey) ?? ""
145
+
146
+ do {
147
+ try stopAudio(audioId: audioId)
148
+ } catch {
149
+ call.reject(Constant.ErrorAssetNotFound)
150
+ }
151
+ }
152
+
153
+ @objc func loop(_ call: CAPPluginCall) {
154
+ guard let audioAsset: AudioAsset = self.getAudioAsset(call) else {
155
+ return
156
+ }
157
+
158
+ audioAsset.loop()
159
+ call.resolve()
160
+ }
161
+
162
+ @objc func unload(_ call: CAPPluginCall) {
163
+ let audioId = call.getString(Constant.AssetIdKey) ?? ""
164
+ if self.audioList.count > 0 {
165
+ let asset = self.audioList[audioId]
166
+ if asset != nil && asset is AudioAsset {
167
+ let audioAsset = asset as! AudioAsset
168
+ audioAsset.unload();
169
+ self.audioList[audioId] = nil
170
+ }
171
+ }
172
+ call.resolve()
173
+ }
174
+
175
+ @objc func setVolume(_ call: CAPPluginCall) {
176
+ guard let audioAsset: AudioAsset = self.getAudioAsset(call) else {
177
+ return
178
+ }
179
+
180
+ let volume = call.getFloat(Constant.Volume) ?? 1.0
181
+
182
+ audioAsset.setVolume(volume: volume as NSNumber)
183
+ call.resolve()
184
+ }
185
+
186
+ @objc func isPlaying(_ call: CAPPluginCall) {
187
+ guard let audioAsset: AudioAsset = self.getAudioAsset(call) else {
188
+ return
189
+ }
190
+
191
+ call.resolve([
192
+ "isPlaying": audioAsset.isPlaying()
193
+ ])
194
+ }
195
+
196
+ private func preloadAsset(_ call: CAPPluginCall, isComplex complex: Bool) {
197
+ let audioId = call.getString(Constant.AssetIdKey) ?? ""
198
+ let channels: NSNumber?
199
+ let volume: Float?
200
+ let delay: NSNumber?
201
+ let isUrl: Bool?
202
+
203
+ if audioId != "" {
204
+ let assetPath: String = call.getString(Constant.AssetPathKey) ?? ""
205
+
206
+ if (complex) {
207
+ volume = call.getFloat("volume") ?? 1.0
208
+ channels = NSNumber(value: call.getInt("channels") ?? 1)
209
+ delay = NSNumber(value: call.getInt("delay") ?? 1)
210
+ isUrl = call.getBool("isUrl") ?? false
211
+ } else {
212
+ channels = 0
213
+ volume = 0
214
+ delay = 0
215
+ isUrl = false
216
+ }
217
+
218
+ if audioList.isEmpty {
219
+ audioList = [:]
220
+ }
221
+
222
+ let asset = audioList[audioId]
223
+ let queue = DispatchQueue(label: "ee.forgr.audio.simple.queue", qos: .userInitiated)
224
+
225
+ queue.async {
226
+ if asset == nil {
227
+ var basePath: String?
228
+ if isUrl == false {
229
+ let assetPathSplit = assetPath.components(separatedBy: ".")
230
+ basePath = Bundle.main.path(forResource: assetPathSplit[0], ofType: assetPathSplit[1])
231
+ } else {
232
+ let url = URL(string: assetPath)
233
+ basePath = url!.path
234
+ }
235
+
236
+ if FileManager.default.fileExists(atPath: basePath ?? "") {
237
+ if !complex {
238
+ let pathUrl = URL(fileURLWithPath: basePath ?? "")
239
+ let soundFileUrl: CFURL = CFBridgingRetain(pathUrl) as! CFURL
240
+ var soundId = SystemSoundID()
241
+ AudioServicesCreateSystemSoundID(soundFileUrl, &soundId)
242
+ self.audioList[audioId] = NSNumber(value: Int32(soundId))
243
+ call.resolve()
244
+ } else {
245
+ let audioAsset: AudioAsset = AudioAsset(owner: self, withAssetId: audioId, withPath: basePath, withChannels: channels, withVolume: volume as NSNumber?, withFadeDelay: delay)
246
+ self.audioList[audioId] = audioAsset
247
+ call.resolve()
248
+ }
249
+ } else {
250
+ call.reject(Constant.ErrorAssetPath + " - " + assetPath)
251
+ }
252
+ }
253
+ }
254
+ }
255
+ }
256
+
257
+ private func stopAudio(audioId: String) throws {
258
+ if self.audioList.count > 0 {
259
+ let asset = self.audioList[audioId]
260
+
261
+ if asset != nil {
262
+ if asset is AudioAsset {
263
+ let audioAsset = asset as? AudioAsset
264
+
265
+ if self.fadeMusic {
266
+ audioAsset?.playWithFade(time: audioAsset?.getCurrentTime() ?? 0)
267
+ } else {
268
+ audioAsset?.stop()
269
+ }
270
+ }
271
+ } else {
272
+ throw MyError.runtimeError(Constant.ErrorAssetNotFound)
273
+ }
274
+ }
275
+ }
276
+ }
package/package.json ADDED
@@ -0,0 +1,91 @@
1
+ {
2
+ "name": "@capgo/native-audio",
3
+ "version": "4.0.0",
4
+ "description": "A native plugin for native audio engine",
5
+ "main": "dist/plugin.js",
6
+ "module": "dist/esm/index.js",
7
+ "types": "dist/esm/index.d.ts",
8
+ "unpkg": "dist/plugin.js",
9
+ "files": [
10
+ "android/src/main/",
11
+ "android/build.gradle",
12
+ "dist/",
13
+ "ios/Plugin/",
14
+ "CapgoNativeAudio.podspec"
15
+ ],
16
+ "keywords": [
17
+ "capacitor",
18
+ "plugin",
19
+ "audio",
20
+ "media",
21
+ "native"
22
+ ],
23
+ "scripts": {
24
+ "verify": "npm run verify:ios && npm run verify:android && npm run verify:web",
25
+ "verify:ios": "cd ios && pod install && xcodebuild -workspace Plugin.xcworkspace -scheme Plugin && cd ..",
26
+ "verify:android": "cd android && ./gradlew clean build test && cd ..",
27
+ "verify:web": "npm run build",
28
+ "lint": "npm run eslint && npm run prettier -- --check && npm run swiftlint -- lint",
29
+ "fmt": "npm run eslint -- --fix && npm run prettier -- --write && npm run swiftlint -- autocorrect --format",
30
+ "eslint": "eslint . --ext ts",
31
+ "prettier": "prettier \"**/*.{css,html,ts,js,java}\"",
32
+ "swiftlint": "node-swiftlint",
33
+ "docgen": "docgen --api NativeAudio --output-readme README.md --output-json dist/docs.json",
34
+ "build": "npm run clean && npm run docgen && tsc && rollup -c rollup.config.js",
35
+ "clean": "rimraf ./dist",
36
+ "watch": "tsc --watch",
37
+ "prepublishOnly": "npm run build",
38
+ "prepare": "husky install"
39
+ },
40
+ "author": "Martin Donadieu <martindonadieu@gmail.com>",
41
+ "license": "MIT",
42
+ "devDependencies": {
43
+ "@capacitor/android": "^4.4.0",
44
+ "@capacitor/cli": "^4.4.0",
45
+ "@capacitor/core": "^4.4.0",
46
+ "@capacitor/docgen": "^0.2.0",
47
+ "@capacitor/ios": "^4.4.0",
48
+ "@ionic/eslint-config": "^0.3.0",
49
+ "@ionic/prettier-config": "^2.0.0",
50
+ "@ionic/swiftlint-config": "^1.1.2",
51
+ "eslint": "^7.32.0",
52
+ "husky": "^8.0.1",
53
+ "prettier": "^2.7.1",
54
+ "prettier-plugin-java": "^1.6.2",
55
+ "rimraf": "^3.0.2",
56
+ "rollup": "^2.79.1",
57
+ "swiftlint": "^1.0.1",
58
+ "typescript": "^4.8.4"
59
+ },
60
+ "peerDependencies": {
61
+ "@capacitor/core": "^3.0.0 || ^4.0.0"
62
+ },
63
+ "husky": {
64
+ "hooks": {
65
+ "pre-commit": "pretty-quick --staged"
66
+ }
67
+ },
68
+ "capacitor": {
69
+ "ios": {
70
+ "src": "ios"
71
+ },
72
+ "android": {
73
+ "src": "android"
74
+ }
75
+ },
76
+ "prettier": "@ionic/prettier-config",
77
+ "swiftlint": "@ionic/swiftlint-config",
78
+ "eslintConfig": {
79
+ "extends": "@ionic/eslint-config/recommended"
80
+ },
81
+ "repository": {
82
+ "type": "git",
83
+ "url": "https://github.com/capacitor-community/native-audio"
84
+ },
85
+ "bugs": {
86
+ "url": "https://github.com/capacitor-community/native-audio/issues"
87
+ },
88
+ "publishConfig": {
89
+ "access": "public"
90
+ }
91
+ }