@capgo/native-audio 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
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,16 @@
1
+ require 'json'
2
+
3
+ package = JSON.parse(File.read(File.join(__dir__, 'package.json')))
4
+
5
+ Pod::Spec.new do |s|
6
+ s.name = 'CapacitorCommunityNativeAudio'
7
+ s.version = package['version']
8
+ s.summary = package['description']
9
+ s.license = package['license']
10
+ s.homepage = package['repository']['url']
11
+ s.author = package['author']
12
+ s.source = { :git => package['repository']['url'], :tag => s.version.to_s }
13
+ s.source_files = 'ios/Plugin/**/*.{swift,h,m,c,cc,mm,cpp}'
14
+ s.ios.deployment_target = '12.0'
15
+ s.dependency 'Capacitor'
16
+ end
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) COPYRIGHT_YEAR COPYRIGHT_HOLDER
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,394 @@
1
+ <p align="center"><br><img src="https://user-images.githubusercontent.com/236501/85893648-1c92e880-b7a8-11ea-926d-95355b8175c7.png" width="128" height="128" /></p>
2
+ <h3 align="center">Native Audio</h3>
3
+ <p align="center"><strong><code>@capacitor-community/native-audio</code></strong></p>
4
+ <p align="center">
5
+ Capacitor community plugin for playing sounds.
6
+ </p>
7
+
8
+ <p align="center">
9
+ <img src="https://img.shields.io/maintenance/yes/2021?style=flat-square" />
10
+ <a href="https://github.com/capacitor-community/native-audio/actions?query=workflow%3A%22Test+and+Build+Plugin%22"><img src="https://img.shields.io/github/workflow/status/capacitor-community/native-audio/Test%20and%20Build%20Plugin?style=flat-square" /></a>
11
+ <a href="https://www.npmjs.com/package/@capacitor-community/native-audio"><img src="https://img.shields.io/npm/l/@capacitor-community/native-audio?style=flat-square" /></a>
12
+ <br>
13
+ <a href="https://www.npmjs.com/package/@capacitor-community/native-audio"><img src="https://img.shields.io/npm/dw/@capacitor-community/native-audio?style=flat-square" /></a>
14
+ <a href="https://www.npmjs.com/package/@capacitor-community/native-audio"><img src="https://img.shields.io/npm/v/@capacitor-community/native-audio?style=flat-square" /></a>
15
+ <!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
16
+ <a href="#contributors-"><img src="https://img.shields.io/badge/all%20contributors-6-orange?style=flat-square" /></a>
17
+ <!-- ALL-CONTRIBUTORS-BADGE:END -->
18
+ </p>
19
+
20
+ # Capacitor Native Audio Plugin
21
+
22
+ Capacitor plugin for native audio engine.
23
+ Capacitor v3 - ✅ Support!
24
+
25
+ Click on video to see example 💥
26
+
27
+ [![YouTube Example](https://img.youtube.com/vi/XpUGlWWtwHs/0.jpg)](https://www.youtube.com/watch?v=XpUGlWWtwHs)
28
+
29
+
30
+ ## Maintainers
31
+
32
+ | Maintainer | GitHub | Social |
33
+ | ------------- | ------------------------------------------- | ----------------------------------- |
34
+ | Maxim Bazuev | [bazuka5801](https://github.com/bazuka5801) | [Telegram](https://t.me/bazuka5801) |
35
+
36
+ Mainteinance Status: Actively Maintained
37
+
38
+ ## Preparation
39
+ All audio place in specific platform folder
40
+
41
+ Andoid: `android/app/src/assets`
42
+
43
+ iOS: `ios/App/App/sounds`
44
+
45
+ Web: `assets/sounds`
46
+
47
+ ## Installation
48
+
49
+ To use npm
50
+
51
+ ```bash
52
+ npm install @capacitor-community/native-audio
53
+ ```
54
+
55
+ To use yarn
56
+
57
+ ```bash
58
+ yarn add @capacitor-community/native-audio
59
+ ```
60
+
61
+ Sync native files
62
+
63
+ ```bash
64
+ npx cap sync
65
+ ```
66
+
67
+ On iOS, Android and Web, no further steps are needed.
68
+
69
+ ## Configuration
70
+
71
+ No configuration required for this plugin.
72
+ <docgen-config>
73
+ <!--Update the source file JSDoc comments and rerun docgen to update the docs below-->
74
+
75
+
76
+
77
+ </docgen-config>
78
+
79
+ ## Supported methods
80
+
81
+ | Name | Android | iOS | Web |
82
+ | :------------- | :------ | :-- | :-- |
83
+ | configure | ✅ | ✅ | ❌ |
84
+ | preload | ✅ | ✅ | ✅ |
85
+ | play | ✅ | ✅ | ✅ |
86
+ | pause | ✅ | ✅ | ✅ |
87
+ | resume | ✅ | ✅ | ✅ |
88
+ | loop | ✅ | ✅ | ✅ |
89
+ | stop | ✅ | ✅ | ✅ |
90
+ | unload | ✅ | ✅ | ✅ |
91
+ | setVolume | ✅ | ✅ | ✅ |
92
+ | getDuration | ✅ | ✅ | ✅ |
93
+ | getCurrentTime | ✅ | ✅ | ✅ |
94
+ | isPlaying | ✅ | ✅ | ✅ |
95
+
96
+ ## Usage
97
+
98
+ [Example repository](https://github.com/bazuka5801/native-audio-example)
99
+
100
+ ```typescript
101
+ import {NativeAudio} from '@capacitor-community/native-audio'
102
+
103
+
104
+ /**
105
+ * This method will load more optimized audio files for background into memory.
106
+ * @param assetPath - relative path of the file or absolute url (file://)
107
+ * assetId - unique identifier of the file
108
+ * audioChannelNum - number of audio channels
109
+ * isUrl - pass true if assetPath is a `file://` url
110
+ * @returns void
111
+ */
112
+ NativeAudio.preload({
113
+ assetId: "fire",
114
+ assetPath: "fire.mp3",
115
+ audioChannelNum: 1,
116
+ isUrl: false
117
+ });
118
+
119
+ /**
120
+ * This method will play the loaded audio file if present in the memory.
121
+ * @param assetId - identifier of the asset
122
+ * @param time - (optional) play with seek. example: 6.0 - start playing track from 6 sec
123
+ * @returns void
124
+ */
125
+ NativeAudio.play({
126
+ assetId: 'fire',
127
+ // time: 6.0 - seek time
128
+ });
129
+
130
+ /**
131
+ * This method will loop the audio file for playback.
132
+ * @param assetId - identifier of the asset
133
+ * @returns void
134
+ */
135
+ NativeAudio.loop({
136
+ assetId: 'fire',
137
+ });
138
+
139
+
140
+ /**
141
+ * This method will stop the audio file if it's currently playing.
142
+ * @param assetId - identifier of the asset
143
+ * @returns void
144
+ */
145
+ NativeAudio.stop({
146
+ assetId: 'fire',
147
+ });
148
+
149
+ /**
150
+ * This method will unload the audio file from the memory.
151
+ * @param assetId - identifier of the asset
152
+ * @returns void
153
+ */
154
+ NativeAudio.unload({
155
+ assetId: 'fire',
156
+ });
157
+
158
+ /**
159
+ * This method will set the new volume for a audio file.
160
+ * @param assetId - identifier of the asset
161
+ * volume - numerical value of the volume between 0.1 - 1.0
162
+ * @returns void
163
+ */
164
+ NativeAudio.setVolume({
165
+ assetId: 'fire',
166
+ volume: 0.4,
167
+ });
168
+
169
+ /**
170
+ * this method will get the duration of an audio file.
171
+ * only works if channels == 1
172
+ */
173
+ NativeAudio.getDuration({
174
+ assetId: 'fire'
175
+ })
176
+ .then(result => {
177
+ console.log(result.duration);
178
+ })
179
+
180
+ /**
181
+ * this method will get the current time of a playing audio file.
182
+ * only works if channels == 1
183
+ */
184
+ NativeAudio.getCurrentTime({
185
+ assetId: 'fire'
186
+ });
187
+ .then(result => {
188
+ console.log(result.currentTime);
189
+ })
190
+
191
+ /**
192
+ * This method will return false if audio is paused or not loaded.
193
+ * @param assetId - identifier of the asset
194
+ * @returns {isPlaying: boolean}
195
+ */
196
+ NativeAudio.isPlaying({
197
+ assetId: 'fire'
198
+ })
199
+ .then(result => {
200
+ console.log(result.isPlaying);
201
+ })
202
+ ```
203
+
204
+ ## API
205
+
206
+ <docgen-index>
207
+
208
+ <docgen-api>
209
+ <!--Update the source file JSDoc comments and rerun docgen to update the docs below-->
210
+
211
+ ### configure(...)
212
+
213
+ ```typescript
214
+ configure(options: ConfigureOptions) => Promise<void>
215
+ ```
216
+
217
+ | Param | Type |
218
+ | ------------- | ------------------------------------------------------------- |
219
+ | **`options`** | <code><a href="#configureoptions">ConfigureOptions</a></code> |
220
+
221
+ --------------------
222
+
223
+
224
+ ### preload(...)
225
+
226
+ ```typescript
227
+ preload(options: PreloadOptions) => Promise<void>
228
+ ```
229
+
230
+ | Param | Type |
231
+ | ------------- | --------------------------------------------------------- |
232
+ | **`options`** | <code><a href="#preloadoptions">PreloadOptions</a></code> |
233
+
234
+ --------------------
235
+
236
+
237
+ ### play(...)
238
+
239
+ ```typescript
240
+ play(options: { assetId: string; time: number; }) => Promise<void>
241
+ ```
242
+
243
+ | Param | Type |
244
+ | ------------- | ----------------------------------------------- |
245
+ | **`options`** | <code>{ assetId: string; time: number; }</code> |
246
+
247
+ --------------------
248
+
249
+
250
+ ### pause(...)
251
+
252
+ ```typescript
253
+ pause(options: { assetId: string; }) => Promise<void>
254
+ ```
255
+
256
+ | Param | Type |
257
+ | ------------- | --------------------------------- |
258
+ | **`options`** | <code>{ assetId: string; }</code> |
259
+
260
+ --------------------
261
+
262
+
263
+ ### resume(...)
264
+
265
+ ```typescript
266
+ resume(options: { assetId: string; }) => Promise<void>
267
+ ```
268
+
269
+ | Param | Type |
270
+ | ------------- | --------------------------------- |
271
+ | **`options`** | <code>{ assetId: string; }</code> |
272
+
273
+ --------------------
274
+
275
+
276
+ ### loop(...)
277
+
278
+ ```typescript
279
+ loop(options: { assetId: string; }) => Promise<void>
280
+ ```
281
+
282
+ | Param | Type |
283
+ | ------------- | --------------------------------- |
284
+ | **`options`** | <code>{ assetId: string; }</code> |
285
+
286
+ --------------------
287
+
288
+
289
+ ### stop(...)
290
+
291
+ ```typescript
292
+ stop(options: { assetId: string; }) => Promise<void>
293
+ ```
294
+
295
+ | Param | Type |
296
+ | ------------- | --------------------------------- |
297
+ | **`options`** | <code>{ assetId: string; }</code> |
298
+
299
+ --------------------
300
+
301
+
302
+ ### unload(...)
303
+
304
+ ```typescript
305
+ unload(options: { assetId: string; }) => Promise<void>
306
+ ```
307
+
308
+ | Param | Type |
309
+ | ------------- | --------------------------------- |
310
+ | **`options`** | <code>{ assetId: string; }</code> |
311
+
312
+ --------------------
313
+
314
+
315
+ ### setVolume(...)
316
+
317
+ ```typescript
318
+ setVolume(options: { assetId: string; volume: number; }) => Promise<void>
319
+ ```
320
+
321
+ | Param | Type |
322
+ | ------------- | ------------------------------------------------- |
323
+ | **`options`** | <code>{ assetId: string; volume: number; }</code> |
324
+
325
+ --------------------
326
+
327
+
328
+ ### getCurrentTime(...)
329
+
330
+ ```typescript
331
+ getCurrentTime(options: { assetId: string; }) => Promise<{ currentTime: number; }>
332
+ ```
333
+
334
+ | Param | Type |
335
+ | ------------- | --------------------------------- |
336
+ | **`options`** | <code>{ assetId: string; }</code> |
337
+
338
+ **Returns:** <code>Promise&lt;{ currentTime: number; }&gt;</code>
339
+
340
+ --------------------
341
+
342
+
343
+ ### getDuration(...)
344
+
345
+ ```typescript
346
+ getDuration(options: { assetId: string; }) => Promise<{ duration: number; }>
347
+ ```
348
+
349
+ | Param | Type |
350
+ | ------------- | --------------------------------- |
351
+ | **`options`** | <code>{ assetId: string; }</code> |
352
+
353
+ **Returns:** <code>Promise&lt;{ duration: number; }&gt;</code>
354
+
355
+ --------------------
356
+
357
+
358
+ ### isPlaying(...)
359
+
360
+ ```typescript
361
+ isPlaying(options: { assetId: string; }) => Promise<{ isPlaying: boolean; }>
362
+ ```
363
+
364
+ | Param | Type |
365
+ | ------------- | --------------------------------- |
366
+ | **`options`** | <code>{ assetId: string; }</code> |
367
+
368
+ **Returns:** <code>Promise&lt;{ isPlaying: boolean; }&gt;</code>
369
+
370
+ --------------------
371
+
372
+
373
+ ### Interfaces
374
+
375
+
376
+ #### ConfigureOptions
377
+
378
+ | Prop | Type |
379
+ | ----------- | -------------------- |
380
+ | **`fade`** | <code>boolean</code> |
381
+ | **`focus`** | <code>boolean</code> |
382
+
383
+
384
+ #### PreloadOptions
385
+
386
+ | Prop | Type |
387
+ | --------------------- | -------------------- |
388
+ | **`assetPath`** | <code>string</code> |
389
+ | **`assetId`** | <code>string</code> |
390
+ | **`volume`** | <code>number</code> |
391
+ | **`audioChannelNum`** | <code>number</code> |
392
+ | **`isUrl`** | <code>boolean</code> |
393
+
394
+ </docgen-api>
@@ -0,0 +1,55 @@
1
+ ext {
2
+ junitVersion = project.hasProperty('junitVersion') ? rootProject.ext.junitVersion : '4.12'
3
+ androidxJunitVersion = project.hasProperty('androidxJunitVersion') ? rootProject.ext.androidxJunitVersion : '1.1.1'
4
+ androidxEspressoCoreVersion = project.hasProperty('androidxEspressoCoreVersion') ? rootProject.ext.androidxEspressoCoreVersion : '3.2.0'
5
+ }
6
+
7
+ buildscript {
8
+ repositories {
9
+ google()
10
+ jcenter()
11
+ }
12
+ dependencies {
13
+ classpath 'com.android.tools.build:gradle:3.6.1'
14
+ }
15
+ }
16
+
17
+ apply plugin: 'com.android.library'
18
+
19
+ android {
20
+ compileSdkVersion project.hasProperty('compileSdkVersion') ? rootProject.ext.compileSdkVersion : 30
21
+ defaultConfig {
22
+ minSdkVersion project.hasProperty('minSdkVersion') ? rootProject.ext.minSdkVersion : 21
23
+ targetSdkVersion project.hasProperty('targetSdkVersion') ? rootProject.ext.targetSdkVersion : 29
24
+ versionCode 1
25
+ versionName "1.0"
26
+ testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
27
+ }
28
+ buildTypes {
29
+ release {
30
+ minifyEnabled false
31
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
32
+ }
33
+ }
34
+ lintOptions {
35
+ abortOnError false
36
+ disable "UnsafeExperimentalUsageError",
37
+ "UnsafeExperimentalUsageWarning"
38
+ }
39
+ }
40
+
41
+ repositories {
42
+ google()
43
+ jcenter()
44
+ mavenCentral()
45
+ }
46
+
47
+
48
+ dependencies {
49
+ implementation 'com.android.support:appcompat-v7:XX.X.+'
50
+ implementation fileTree(dir: 'libs', include: ['*.jar'])
51
+ implementation project(':capacitor-android')
52
+ testImplementation "junit:junit:$junitVersion"
53
+ androidTestImplementation "androidx.test.ext:junit:$androidxJunitVersion"
54
+ androidTestImplementation "androidx.test.espresso:espresso-core:$androidxEspressoCoreVersion"
55
+ }
@@ -0,0 +1,5 @@
1
+
2
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android"
3
+ package="ee.forgr.audio.nativeaudio">
4
+ </manifest>
5
+
@@ -0,0 +1,140 @@
1
+ package ee.forgr.audio;
2
+
3
+ import android.content.res.AssetFileDescriptor;
4
+ import com.getcapacitor.JSObject;
5
+ import java.util.ArrayList;
6
+ import java.util.concurrent.Callable;
7
+
8
+ public class AudioAsset {
9
+
10
+ private final String TAG = "AudioAsset";
11
+
12
+ private ArrayList<AudioDispatcher> audioList;
13
+ private int playIndex = 0;
14
+ private String assetId;
15
+ private NativeAudio owner;
16
+
17
+ AudioAsset(NativeAudio owner, String assetId, AssetFileDescriptor assetFileDescriptor, int audioChannelNum, float volume)
18
+ throws Exception {
19
+ audioList = new ArrayList<>();
20
+ this.owner = owner;
21
+ this.assetId = assetId;
22
+
23
+ if (audioChannelNum < 0) {
24
+ audioChannelNum = 1;
25
+ }
26
+
27
+ for (int x = 0; x < audioChannelNum; x++) {
28
+ AudioDispatcher audioDispatcher = new AudioDispatcher(assetFileDescriptor, volume);
29
+ audioList.add(audioDispatcher);
30
+ if (audioChannelNum == 1) audioDispatcher.setOwner(this);
31
+ }
32
+ }
33
+
34
+ public void dispatchComplete() {
35
+ this.owner.dispatchComplete(this.assetId);
36
+ }
37
+
38
+ public void play(Double time, Callable<Void> callback) throws Exception {
39
+ AudioDispatcher audio = audioList.get(playIndex);
40
+
41
+ if (audio != null) {
42
+ audio.play(time, callback);
43
+ playIndex++;
44
+ playIndex = playIndex % audioList.size();
45
+ }
46
+ }
47
+
48
+ public double getDuration() {
49
+ if (audioList.size() != 1) return 0;
50
+
51
+ AudioDispatcher audio = audioList.get(playIndex);
52
+
53
+ if (audio != null) {
54
+ return audio.getDuration();
55
+ }
56
+ return 0;
57
+ }
58
+
59
+ public double getCurrentPosition() {
60
+ if (audioList.size() != 1) return 0;
61
+
62
+ AudioDispatcher audio = audioList.get(playIndex);
63
+
64
+ if (audio != null) {
65
+ return audio.getCurrentPosition();
66
+ }
67
+ return 0;
68
+ }
69
+
70
+ public boolean pause() throws Exception {
71
+ boolean wasPlaying = false;
72
+
73
+ for (int x = 0; x < audioList.size(); x++) {
74
+ AudioDispatcher audio = audioList.get(x);
75
+ wasPlaying |= audio.pause();
76
+ }
77
+
78
+ return wasPlaying;
79
+ }
80
+
81
+ public void resume() throws Exception {
82
+ if (audioList.size() > 0) {
83
+ AudioDispatcher audio = audioList.get(0);
84
+
85
+ if (audio != null) {
86
+ audio.resume();
87
+ }
88
+ }
89
+ }
90
+
91
+ public void stop() throws Exception {
92
+ for (int x = 0; x < audioList.size(); x++) {
93
+ AudioDispatcher audio = audioList.get(x);
94
+
95
+ if (audio != null) {
96
+ audio.stop();
97
+ }
98
+ }
99
+ }
100
+
101
+ public void loop() throws Exception {
102
+ AudioDispatcher audio = audioList.get(playIndex);
103
+
104
+ if (audio != null) {
105
+ audio.loop();
106
+ playIndex++;
107
+ playIndex = playIndex % audioList.size();
108
+ }
109
+ }
110
+
111
+ public void unload() throws Exception {
112
+ this.stop();
113
+
114
+ for (int x = 0; x < audioList.size(); x++) {
115
+ AudioDispatcher audio = audioList.get(x);
116
+
117
+ if (audio != null) {
118
+ audio.unload();
119
+ }
120
+ }
121
+
122
+ audioList.clear();
123
+ }
124
+
125
+ public void setVolume(float volume) throws Exception {
126
+ for (int x = 0; x < audioList.size(); x++) {
127
+ AudioDispatcher audio = audioList.get(x);
128
+
129
+ if (audio != null) {
130
+ audio.setVolume(volume);
131
+ }
132
+ }
133
+ }
134
+
135
+ public boolean isPlaying() throws Exception {
136
+ if (audioList.size() != 1) return false;
137
+
138
+ return audioList.get(playIndex).isPlaying();
139
+ }
140
+ }