react-native-audio-api 0.6.0-rc.4 → 0.6.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 (206) hide show
  1. package/android/src/main/cpp/audioapi/android/AudioAPIModule.cpp +35 -2
  2. package/android/src/main/cpp/audioapi/android/AudioAPIModule.h +4 -0
  3. package/android/src/main/cpp/audioapi/android/core/AndroidAudioRecorder.cpp +31 -17
  4. package/android/src/main/cpp/audioapi/android/core/AndroidAudioRecorder.h +1 -3
  5. package/android/src/main/java/com/swmansion/audioapi/AudioAPIModule.kt +56 -2
  6. package/android/src/main/java/com/swmansion/audioapi/AudioAPIPackage.kt +0 -12
  7. package/android/src/main/java/com/swmansion/audioapi/system/AudioFocusListener.kt +35 -12
  8. package/android/src/main/java/com/swmansion/audioapi/system/LockScreenManager.kt +30 -29
  9. package/android/src/main/java/com/swmansion/audioapi/system/MediaNotificationManager.kt +20 -22
  10. package/android/src/main/java/com/swmansion/audioapi/system/MediaReceiver.kt +19 -9
  11. package/android/src/main/java/com/swmansion/audioapi/system/MediaSessionCallback.kt +30 -11
  12. package/android/src/main/java/com/swmansion/audioapi/system/MediaSessionManager.kt +53 -26
  13. package/android/src/main/java/com/swmansion/audioapi/system/VolumeChangeListener.kt +10 -5
  14. package/android/src/oldarch/NativeAudioAPIModuleSpec.java +39 -0
  15. package/common/cpp/audioapi/AudioAPIModuleInstaller.h +20 -14
  16. package/common/cpp/audioapi/HostObjects/AudioBufferSourceNodeHostObject.h +2 -3
  17. package/common/cpp/audioapi/HostObjects/AudioNodeHostObject.h +24 -11
  18. package/common/cpp/audioapi/HostObjects/AudioParamHostObject.h +1 -0
  19. package/common/cpp/audioapi/HostObjects/AudioRecorderHostObject.h +10 -89
  20. package/common/cpp/audioapi/HostObjects/AudioScheduledSourceNodeHostObject.h +3 -24
  21. package/common/cpp/audioapi/HostObjects/BaseAudioContextHostObject.h +2 -2
  22. package/common/cpp/audioapi/HostObjects/OscillatorNodeHostObject.h +2 -3
  23. package/common/cpp/audioapi/core/AudioContext.cpp +4 -1
  24. package/common/cpp/audioapi/core/AudioContext.h +1 -1
  25. package/common/cpp/audioapi/core/AudioNode.cpp +31 -2
  26. package/common/cpp/audioapi/core/AudioNode.h +7 -1
  27. package/common/cpp/audioapi/core/AudioParam.cpp +84 -2
  28. package/common/cpp/audioapi/core/AudioParam.h +14 -1
  29. package/common/cpp/audioapi/core/BaseAudioContext.cpp +7 -1
  30. package/common/cpp/audioapi/core/BaseAudioContext.h +7 -1
  31. package/common/cpp/audioapi/core/OfflineAudioContext.cpp +3 -2
  32. package/common/cpp/audioapi/core/OfflineAudioContext.h +1 -1
  33. package/common/cpp/audioapi/core/analysis/AnalyserNode.cpp +19 -56
  34. package/common/cpp/audioapi/core/analysis/AnalyserNode.h +3 -2
  35. package/common/cpp/audioapi/core/effects/BiquadFilterNode.cpp +28 -26
  36. package/common/cpp/audioapi/core/effects/GainNode.cpp +9 -9
  37. package/common/cpp/audioapi/core/effects/StereoPannerNode.cpp +5 -2
  38. package/common/cpp/audioapi/core/inputs/AudioRecorder.cpp +56 -0
  39. package/common/cpp/audioapi/core/inputs/AudioRecorder.h +13 -13
  40. package/common/cpp/audioapi/core/sources/AudioBufferSourceNode.cpp +14 -10
  41. package/common/cpp/audioapi/core/sources/AudioBufferSourceNode.h +1 -1
  42. package/common/cpp/audioapi/core/sources/AudioScheduledSourceNode.cpp +7 -6
  43. package/common/cpp/audioapi/core/sources/AudioScheduledSourceNode.h +5 -3
  44. package/common/cpp/audioapi/core/sources/OscillatorNode.cpp +15 -10
  45. package/common/cpp/audioapi/core/utils/AudioNodeManager.cpp +35 -1
  46. package/common/cpp/audioapi/core/utils/AudioNodeManager.h +15 -1
  47. package/common/cpp/audioapi/events/AudioEventHandlerRegistry.cpp +108 -0
  48. package/common/cpp/audioapi/events/AudioEventHandlerRegistry.h +62 -0
  49. package/common/cpp/audioapi/events/AudioEventHandlerRegistryHostObject.h +48 -0
  50. package/common/cpp/audioapi/jsi/JsiPromise.cpp +3 -4
  51. package/common/cpp/audioapi/utils/AudioArray.h +1 -1
  52. package/common/cpp/audioapi/utils/CircularAudioArray.cpp +94 -0
  53. package/common/cpp/audioapi/utils/CircularAudioArray.h +26 -0
  54. package/ios/audioapi/ios/AudioAPIModule.h +13 -0
  55. package/ios/audioapi/ios/AudioAPIModule.mm +115 -6
  56. package/ios/audioapi/ios/core/IOSAudioRecorder.h +3 -10
  57. package/ios/audioapi/ios/core/IOSAudioRecorder.mm +15 -52
  58. package/ios/audioapi/ios/core/NativeAudioPlayer.m +2 -0
  59. package/ios/audioapi/ios/core/NativeAudioRecorder.m +7 -3
  60. package/ios/audioapi/ios/events/IOSAudioEventHandlerRegistry.h +7 -0
  61. package/ios/audioapi/ios/events/IOSAudioEventHandlerRegistry.mm +12 -0
  62. package/ios/audioapi/ios/system/AudioEngine.h +5 -0
  63. package/ios/audioapi/ios/system/AudioEngine.mm +7 -15
  64. package/ios/audioapi/ios/system/AudioSessionManager.h +3 -1
  65. package/ios/audioapi/ios/system/AudioSessionManager.mm +36 -17
  66. package/ios/audioapi/ios/system/LockScreenManager.h +3 -3
  67. package/ios/audioapi/ios/system/LockScreenManager.mm +36 -48
  68. package/ios/audioapi/ios/system/NotificationManager.h +3 -3
  69. package/ios/audioapi/ios/system/NotificationManager.mm +21 -29
  70. package/lib/commonjs/api.js +4 -4
  71. package/lib/commonjs/api.js.map +1 -1
  72. package/lib/commonjs/core/AudioBufferSourceNode.js +2 -2
  73. package/lib/commonjs/core/AudioBufferSourceNode.js.map +1 -1
  74. package/lib/commonjs/core/AudioNode.js +8 -2
  75. package/lib/commonjs/core/AudioNode.js.map +1 -1
  76. package/lib/commonjs/core/AudioParam.js +2 -1
  77. package/lib/commonjs/core/AudioParam.js.map +1 -1
  78. package/lib/commonjs/core/AudioRecorder.js +11 -28
  79. package/lib/commonjs/core/AudioRecorder.js.map +1 -1
  80. package/lib/commonjs/core/AudioScheduledSourceNode.js +4 -1
  81. package/lib/commonjs/core/AudioScheduledSourceNode.js.map +1 -1
  82. package/lib/commonjs/core/BiquadFilterNode.js +4 -4
  83. package/lib/commonjs/core/BiquadFilterNode.js.map +1 -1
  84. package/lib/commonjs/core/GainNode.js +1 -1
  85. package/lib/commonjs/core/GainNode.js.map +1 -1
  86. package/lib/commonjs/core/OscillatorNode.js +2 -2
  87. package/lib/commonjs/core/OscillatorNode.js.map +1 -1
  88. package/lib/commonjs/core/StereoPannerNode.js +1 -1
  89. package/lib/commonjs/core/StereoPannerNode.js.map +1 -1
  90. package/lib/commonjs/events/AudioEventEmitter.js +22 -0
  91. package/lib/commonjs/events/AudioEventEmitter.js.map +1 -0
  92. package/lib/commonjs/events/AudioEventSubscription.js +20 -0
  93. package/lib/commonjs/events/AudioEventSubscription.js.map +1 -0
  94. package/lib/commonjs/events/index.js +21 -0
  95. package/lib/commonjs/events/index.js.map +1 -0
  96. package/lib/commonjs/events/types.js +6 -0
  97. package/lib/commonjs/events/types.js.map +1 -0
  98. package/lib/commonjs/hooks/useSytemVolume.js +1 -1
  99. package/lib/commonjs/hooks/useSytemVolume.js.map +1 -1
  100. package/lib/commonjs/specs/NativeAudioAPIModule.js +3 -3
  101. package/lib/commonjs/specs/NativeAudioAPIModule.js.map +1 -1
  102. package/lib/commonjs/specs/index.js +2 -16
  103. package/lib/commonjs/specs/index.js.map +1 -1
  104. package/lib/commonjs/system/AudioManager.js +26 -26
  105. package/lib/commonjs/system/AudioManager.js.map +1 -1
  106. package/lib/module/api.js +2 -2
  107. package/lib/module/api.js.map +1 -1
  108. package/lib/module/core/AudioBufferSourceNode.js +2 -2
  109. package/lib/module/core/AudioBufferSourceNode.js.map +1 -1
  110. package/lib/module/core/AudioNode.js +7 -2
  111. package/lib/module/core/AudioNode.js.map +1 -1
  112. package/lib/module/core/AudioParam.js +2 -1
  113. package/lib/module/core/AudioParam.js.map +1 -1
  114. package/lib/module/core/AudioRecorder.js +11 -28
  115. package/lib/module/core/AudioRecorder.js.map +1 -1
  116. package/lib/module/core/AudioScheduledSourceNode.js +4 -1
  117. package/lib/module/core/AudioScheduledSourceNode.js.map +1 -1
  118. package/lib/module/core/BiquadFilterNode.js +4 -4
  119. package/lib/module/core/BiquadFilterNode.js.map +1 -1
  120. package/lib/module/core/GainNode.js +1 -1
  121. package/lib/module/core/GainNode.js.map +1 -1
  122. package/lib/module/core/OscillatorNode.js +2 -2
  123. package/lib/module/core/OscillatorNode.js.map +1 -1
  124. package/lib/module/core/StereoPannerNode.js +1 -1
  125. package/lib/module/core/StereoPannerNode.js.map +1 -1
  126. package/lib/module/events/AudioEventEmitter.js +16 -0
  127. package/lib/module/events/AudioEventEmitter.js.map +1 -0
  128. package/lib/module/events/AudioEventSubscription.js +15 -0
  129. package/lib/module/events/AudioEventSubscription.js.map +1 -0
  130. package/lib/module/events/index.js +6 -0
  131. package/lib/module/events/index.js.map +1 -0
  132. package/lib/module/events/types.js +4 -0
  133. package/lib/module/events/types.js.map +1 -0
  134. package/lib/module/hooks/useSytemVolume.js +1 -1
  135. package/lib/module/hooks/useSytemVolume.js.map +1 -1
  136. package/lib/module/specs/NativeAudioAPIModule.js +3 -2
  137. package/lib/module/specs/NativeAudioAPIModule.js.map +1 -1
  138. package/lib/module/specs/index.js +2 -3
  139. package/lib/module/specs/index.js.map +1 -1
  140. package/lib/module/system/AudioManager.js +27 -27
  141. package/lib/module/system/AudioManager.js.map +1 -1
  142. package/lib/typescript/api.d.ts +2 -1
  143. package/lib/typescript/api.d.ts.map +1 -1
  144. package/lib/typescript/core/AudioNode.d.ts +2 -1
  145. package/lib/typescript/core/AudioNode.d.ts.map +1 -1
  146. package/lib/typescript/core/AudioParam.d.ts +4 -2
  147. package/lib/typescript/core/AudioParam.d.ts.map +1 -1
  148. package/lib/typescript/core/AudioRecorder.d.ts +4 -14
  149. package/lib/typescript/core/AudioRecorder.d.ts.map +1 -1
  150. package/lib/typescript/core/AudioScheduledSourceNode.d.ts +3 -1
  151. package/lib/typescript/core/AudioScheduledSourceNode.d.ts.map +1 -1
  152. package/lib/typescript/events/AudioEventEmitter.d.ts +10 -0
  153. package/lib/typescript/events/AudioEventEmitter.d.ts.map +1 -0
  154. package/lib/typescript/events/AudioEventSubscription.d.ts +11 -0
  155. package/lib/typescript/events/AudioEventSubscription.d.ts.map +1 -0
  156. package/lib/typescript/events/index.d.ts +4 -0
  157. package/lib/typescript/events/index.d.ts.map +1 -0
  158. package/lib/typescript/events/types.d.ts +50 -0
  159. package/lib/typescript/events/types.d.ts.map +1 -0
  160. package/lib/typescript/hooks/useSytemVolume.d.ts.map +1 -1
  161. package/lib/typescript/interfaces.d.ts +10 -10
  162. package/lib/typescript/interfaces.d.ts.map +1 -1
  163. package/lib/typescript/specs/NativeAudioAPIModule.d.ts +15 -3
  164. package/lib/typescript/specs/NativeAudioAPIModule.d.ts.map +1 -1
  165. package/lib/typescript/specs/index.d.ts +2 -3
  166. package/lib/typescript/specs/index.d.ts.map +1 -1
  167. package/lib/typescript/system/AudioManager.d.ts +8 -4
  168. package/lib/typescript/system/AudioManager.d.ts.map +1 -1
  169. package/lib/typescript/system/types.d.ts +1 -34
  170. package/lib/typescript/system/types.d.ts.map +1 -1
  171. package/lib/typescript/types.d.ts +0 -1
  172. package/lib/typescript/types.d.ts.map +1 -1
  173. package/package.json +3 -3
  174. package/src/api.ts +6 -3
  175. package/src/core/AudioBufferSourceNode.ts +2 -2
  176. package/src/core/AudioNode.ts +8 -3
  177. package/src/core/AudioParam.ts +5 -2
  178. package/src/core/AudioRecorder.ts +22 -62
  179. package/src/core/AudioScheduledSourceNode.ts +13 -2
  180. package/src/core/BiquadFilterNode.ts +4 -4
  181. package/src/core/GainNode.ts +1 -1
  182. package/src/core/OscillatorNode.ts +2 -2
  183. package/src/core/StereoPannerNode.ts +1 -1
  184. package/src/events/AudioEventEmitter.ts +29 -0
  185. package/src/events/AudioEventSubscription.ts +26 -0
  186. package/src/events/index.ts +4 -0
  187. package/src/events/types.ts +64 -0
  188. package/src/hooks/useSytemVolume.ts +2 -1
  189. package/src/interfaces.ts +19 -20
  190. package/src/specs/NativeAudioAPIModule.ts +23 -2
  191. package/src/specs/index.ts +2 -4
  192. package/src/system/AudioManager.ts +39 -38
  193. package/src/system/types.ts +1 -41
  194. package/src/types.ts +0 -8
  195. package/android/src/main/java/com/swmansion/audioapi/AudioManagerModule.kt +0 -64
  196. package/android/src/main/java/com/swmansion/audioapi/system/MediaSessionEventEmitter.kt +0 -88
  197. package/android/src/oldarch/NativeAudioManagerModuleSpec.java +0 -99
  198. package/ios/audioapi/ios/AudioManagerModule.h +0 -18
  199. package/ios/audioapi/ios/AudioManagerModule.mm +0 -93
  200. package/lib/commonjs/specs/NativeAudioManagerModule.js +0 -36
  201. package/lib/commonjs/specs/NativeAudioManagerModule.js.map +0 -1
  202. package/lib/module/specs/NativeAudioManagerModule.js +0 -33
  203. package/lib/module/specs/NativeAudioManagerModule.js.map +0 -1
  204. package/lib/typescript/specs/NativeAudioManagerModule.d.ts +0 -15
  205. package/lib/typescript/specs/NativeAudioManagerModule.d.ts.map +0 -1
  206. package/src/specs/NativeAudioManagerModule.ts +0 -45
@@ -4,12 +4,17 @@ import android.content.BroadcastReceiver
4
4
  import android.content.Context
5
5
  import android.content.Intent
6
6
  import android.media.AudioManager
7
+ import android.support.v4.media.session.MediaSessionCompat
7
8
  import android.view.KeyEvent
8
9
  import com.facebook.react.bridge.ReactApplicationContext
10
+ import com.swmansion.audioapi.AudioAPIModule
11
+ import java.lang.ref.WeakReference
9
12
 
10
13
  class MediaReceiver(
11
- val reactContext: ReactApplicationContext,
12
- private val mediaSessionManager: MediaSessionManager,
14
+ private val reactContext: WeakReference<ReactApplicationContext>,
15
+ private val mediaSession: WeakReference<MediaSessionCompat>,
16
+ private val mediaNotificationManager: WeakReference<MediaNotificationManager>,
17
+ private val audioAPIModule: WeakReference<AudioAPIModule>,
13
18
  ) : BroadcastReceiver() {
14
19
  override fun onReceive(
15
20
  context: Context?,
@@ -20,26 +25,31 @@ class MediaReceiver(
20
25
  if (MediaNotificationManager.REMOVE_NOTIFICATION == action) {
21
26
  if (!checkApp(intent)) return
22
27
 
23
- mediaSessionManager.mediaNotificationManager.hide()
24
- mediaSessionManager.mediaSession.isActive = false
28
+ mediaNotificationManager.get()?.hide()
29
+ mediaSession.get()?.isActive = false
25
30
 
26
- mediaSessionManager.eventEmitter.sendEvent("onCloseNotification", null)
31
+ audioAPIModule.get()?.invokeHandlerWithEventNameAndEventBody("closeNotification", mapOf()) // add to ts events
27
32
  } else if (MediaNotificationManager.MEDIA_BUTTON == action || Intent.ACTION_MEDIA_BUTTON == action) {
28
33
  if (!intent.hasExtra(Intent.EXTRA_KEY_EVENT)) return
29
34
  if (!checkApp(intent)) return
30
35
 
31
36
  val keyEvent = intent.getParcelableExtra<KeyEvent>(Intent.EXTRA_KEY_EVENT)
32
- mediaSessionManager.mediaSession.controller.dispatchMediaButtonEvent(keyEvent)
37
+ mediaSession.get()?.controller?.dispatchMediaButtonEvent(keyEvent)
33
38
  } else if (AudioManager.ACTION_AUDIO_BECOMING_NOISY == action) {
34
- mediaSessionManager.mediaSession.controller.transportControls
35
- .pause()
39
+ mediaSession
40
+ .get()
41
+ ?.controller
42
+ ?.transportControls
43
+ ?.pause()
36
44
  }
37
45
  }
38
46
 
39
47
  private fun checkApp(intent: Intent): Boolean {
40
48
  if (intent.hasExtra(MediaNotificationManager.PACKAGE_NAME)) {
41
49
  val name = intent.getStringExtra(MediaNotificationManager.PACKAGE_NAME)
42
- if (!reactContext.packageName.equals(name)) return false
50
+ if (!reactContext.get()?.packageName.equals(name)) {
51
+ return false
52
+ }
43
53
  }
44
54
  return true
45
55
  }
@@ -1,39 +1,58 @@
1
1
  package com.swmansion.audioapi.system
2
2
 
3
+ import android.content.Intent
4
+ import android.os.Build
3
5
  import android.support.v4.media.session.MediaSessionCompat
4
6
  import android.support.v4.media.session.PlaybackStateCompat
7
+ import androidx.core.app.NotificationManagerCompat
8
+ import com.swmansion.audioapi.AudioAPIModule
9
+ import java.lang.ref.WeakReference
10
+ import java.util.HashMap
5
11
 
6
12
  class MediaSessionCallback(
7
- val eventEmitter: MediaSessionEventEmitter,
8
- private val lockScreenManager: LockScreenManager,
13
+ private val audioAPIModule: WeakReference<AudioAPIModule>,
14
+ private val lockScreenManager: WeakReference<LockScreenManager>,
9
15
  ) : MediaSessionCompat.Callback() {
10
16
  override fun onPlay() {
11
- lockScreenManager.updatePlaybackState(PlaybackStateCompat.STATE_PLAYING)
12
- eventEmitter.onPlay()
17
+ lockScreenManager.get()?.updatePlaybackState(PlaybackStateCompat.STATE_PLAYING)
18
+ audioAPIModule.get()?.invokeHandlerWithEventNameAndEventBody("remotePlay", mapOf())
13
19
  }
14
20
 
15
21
  override fun onPause() {
16
- lockScreenManager.updatePlaybackState(PlaybackStateCompat.STATE_PAUSED)
17
- eventEmitter.onPause()
22
+ lockScreenManager.get()?.updatePlaybackState(PlaybackStateCompat.STATE_PAUSED)
23
+ audioAPIModule.get()?.invokeHandlerWithEventNameAndEventBody("remotePause", mapOf())
18
24
  }
19
25
 
20
26
  override fun onStop() {
21
- eventEmitter.onStop()
27
+ val reactContext = audioAPIModule.get()?.reactContext?.get()!!
28
+ NotificationManagerCompat.from(reactContext).cancel(MediaSessionManager.NOTIFICATION_ID)
29
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
30
+ val myIntent =
31
+ Intent(reactContext, MediaNotificationManager.NotificationService::class.java)
32
+ reactContext.stopService(myIntent)
33
+ }
34
+
35
+ audioAPIModule.get()?.invokeHandlerWithEventNameAndEventBody("remoteStop", mapOf())
22
36
  }
23
37
 
24
38
  override fun onSkipToNext() {
25
- eventEmitter.onSkipToNext()
39
+ audioAPIModule.get()?.invokeHandlerWithEventNameAndEventBody("remoteNextTrack", mapOf())
26
40
  }
27
41
 
28
42
  override fun onSkipToPrevious() {
29
- eventEmitter.onSkipToPrevious()
43
+ audioAPIModule.get()?.invokeHandlerWithEventNameAndEventBody("remotePreviousTrack", mapOf())
30
44
  }
31
45
 
32
46
  override fun onFastForward() {
33
- eventEmitter.onFastForward()
47
+ audioAPIModule.get()?.invokeHandlerWithEventNameAndEventBody("remoteSkipForward", mapOf())
34
48
  }
35
49
 
36
50
  override fun onRewind() {
37
- eventEmitter.onRewind()
51
+ audioAPIModule.get()?.invokeHandlerWithEventNameAndEventBody("remoteSkipBackward", mapOf())
52
+ }
53
+
54
+ override fun onSeekTo(pos: Long) {
55
+ val body = HashMap<String, Any>().apply { put("value", (pos.toDouble() / 1000)) }
56
+ audioAPIModule.get()?.invokeHandlerWithEventNameAndEventBody("remoteChangePlaybackPosition", body)
38
57
  }
39
58
  }
@@ -1,5 +1,7 @@
1
1
  package com.swmansion.audioapi.system
2
2
 
3
+ import android.Manifest
4
+ import android.app.Activity
3
5
  import android.app.NotificationChannel
4
6
  import android.app.NotificationManager
5
7
  import android.content.ComponentName
@@ -7,27 +9,31 @@ import android.content.Context
7
9
  import android.content.Intent
8
10
  import android.content.IntentFilter
9
11
  import android.content.ServiceConnection
12
+ import android.content.pm.PackageManager
10
13
  import android.media.AudioManager
11
14
  import android.os.Build
12
15
  import android.os.IBinder
13
16
  import android.support.v4.media.session.MediaSessionCompat
14
17
  import android.util.Log
15
18
  import androidx.annotation.RequiresApi
19
+ import androidx.core.app.ActivityCompat
16
20
  import androidx.core.app.NotificationCompat
17
21
  import androidx.core.content.ContextCompat
18
22
  import com.facebook.react.bridge.ReactApplicationContext
19
23
  import com.facebook.react.bridge.ReadableMap
24
+ import com.swmansion.audioapi.AudioAPIModule
25
+ import java.lang.ref.WeakReference
20
26
 
21
27
  object MediaSessionManager {
22
- lateinit var reactContext: ReactApplicationContext
23
- val notificationId = 100
24
- val channelId = "react-native-audio-api"
28
+ private lateinit var audioAPIModule: WeakReference<AudioAPIModule>
29
+ private lateinit var reactContext: WeakReference<ReactApplicationContext>
30
+ const val NOTIFICATION_ID = 100
31
+ const val CHANNEL_ID = "react-native-audio-api"
25
32
 
26
33
  private lateinit var audioManager: AudioManager
27
- lateinit var mediaSession: MediaSessionCompat
34
+ private lateinit var mediaSession: MediaSessionCompat
28
35
  lateinit var mediaNotificationManager: MediaNotificationManager
29
36
  private lateinit var lockScreenManager: LockScreenManager
30
- lateinit var eventEmitter: MediaSessionEventEmitter
31
37
  private lateinit var audioFocusListener: AudioFocusListener
32
38
  private lateinit var volumeChangeListener: VolumeChangeListener
33
39
  private lateinit var mediaReceiver: MediaReceiver
@@ -42,7 +48,7 @@ object MediaSessionManager {
42
48
  val binder = service as MediaNotificationManager.NotificationService.LocalBinder
43
49
  val notificationService = binder.getService()
44
50
  notificationService?.forceForeground()
45
- reactContext.unbindService(this)
51
+ reactContext.get()?.unbindService(this)
46
52
  }
47
53
 
48
54
  override fun onServiceDisconnected(name: ComponentName) {
@@ -58,20 +64,24 @@ object MediaSessionManager {
58
64
  }
59
65
  }
60
66
 
61
- fun initialize(reactContext: ReactApplicationContext) {
67
+ fun initialize(
68
+ audioAPIModule: WeakReference<AudioAPIModule>,
69
+ reactContext: WeakReference<ReactApplicationContext>,
70
+ ) {
71
+ this.audioAPIModule = audioAPIModule
62
72
  this.reactContext = reactContext
63
- this.audioManager = reactContext.getSystemService(Context.AUDIO_SERVICE) as AudioManager
64
- this.mediaSession = MediaSessionCompat(reactContext, "MediaSessionManager")
73
+ this.audioManager = reactContext.get()?.getSystemService(Context.AUDIO_SERVICE) as AudioManager
74
+ this.mediaSession = MediaSessionCompat(reactContext.get()!!, "MediaSessionManager")
65
75
 
66
76
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
67
77
  createChannel()
68
78
  }
69
79
 
70
- this.mediaNotificationManager = MediaNotificationManager(reactContext, notificationId, channelId)
71
- this.lockScreenManager = LockScreenManager(reactContext, mediaSession, mediaNotificationManager, channelId)
72
- this.eventEmitter = MediaSessionEventEmitter(reactContext, notificationId)
73
- this.mediaReceiver = MediaReceiver(reactContext, this)
74
- this.mediaSession.setCallback(MediaSessionCallback(eventEmitter, lockScreenManager))
80
+ this.mediaNotificationManager = MediaNotificationManager(this.reactContext)
81
+ this.lockScreenManager = LockScreenManager(this.reactContext, WeakReference(this.mediaSession), WeakReference(mediaNotificationManager))
82
+ this.mediaReceiver =
83
+ MediaReceiver(this.reactContext, WeakReference(this.mediaSession), WeakReference(mediaNotificationManager), this.audioAPIModule)
84
+ this.mediaSession.setCallback(MediaSessionCallback(this.audioAPIModule, WeakReference(this.lockScreenManager)))
75
85
 
76
86
  val filter = IntentFilter()
77
87
  filter.addAction(MediaNotificationManager.REMOVE_NOTIFICATION)
@@ -80,29 +90,30 @@ object MediaSessionManager {
80
90
  filter.addAction(AudioManager.ACTION_AUDIO_BECOMING_NOISY)
81
91
 
82
92
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
83
- reactContext.registerReceiver(mediaReceiver, filter, Context.RECEIVER_EXPORTED)
93
+ this.reactContext.get()!!.registerReceiver(mediaReceiver, filter, Context.RECEIVER_EXPORTED)
84
94
  } else {
85
95
  ContextCompat.registerReceiver(
86
- reactContext,
96
+ this.reactContext.get()!!,
87
97
  mediaReceiver,
88
98
  filter,
89
99
  ContextCompat.RECEIVER_NOT_EXPORTED,
90
100
  )
91
101
  }
92
102
 
93
- this.audioFocusListener = AudioFocusListener(audioManager, eventEmitter, lockScreenManager)
94
- this.volumeChangeListener = VolumeChangeListener(audioManager, eventEmitter)
103
+ this.audioFocusListener =
104
+ AudioFocusListener(WeakReference(this.audioManager), this.audioAPIModule, WeakReference(this.lockScreenManager))
105
+ this.volumeChangeListener = VolumeChangeListener(WeakReference(this.audioManager), this.audioAPIModule)
95
106
 
96
- val myIntent = Intent(reactContext, MediaNotificationManager.NotificationService::class.java)
107
+ val myIntent = Intent(this.reactContext.get(), MediaNotificationManager.NotificationService::class.java)
97
108
 
98
109
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
99
110
  try {
100
- reactContext.bindService(myIntent, connection, Context.BIND_AUTO_CREATE)
111
+ this.reactContext.get()?.bindService(myIntent, connection, Context.BIND_AUTO_CREATE)
101
112
  } catch (ignored: Exception) {
102
- ContextCompat.startForegroundService(reactContext, myIntent)
113
+ ContextCompat.startForegroundService(this.reactContext.get()!!, myIntent)
103
114
  }
104
115
  } else {
105
- reactContext.startService(myIntent)
116
+ this.reactContext.get()?.startService(myIntent)
106
117
  }
107
118
  }
108
119
 
@@ -137,23 +148,39 @@ object MediaSessionManager {
137
148
  fun observeVolumeChanges(observe: Boolean) {
138
149
  if (observe) {
139
150
  ContextCompat.registerReceiver(
140
- reactContext,
151
+ reactContext.get()!!,
141
152
  volumeChangeListener,
142
153
  volumeChangeListener.getIntentFilter(),
143
154
  ContextCompat.RECEIVER_NOT_EXPORTED,
144
155
  )
145
156
  } else {
146
- reactContext.unregisterReceiver(volumeChangeListener)
157
+ reactContext.get()?.unregisterReceiver(volumeChangeListener)
147
158
  }
148
159
  }
149
160
 
161
+ fun requestRecordingPermissions(currentActivity: Activity?): String {
162
+ ActivityCompat.requestPermissions(currentActivity!!, arrayOf(Manifest.permission.RECORD_AUDIO), 200)
163
+ return checkRecordingPermissions()
164
+ }
165
+
166
+ fun checkRecordingPermissions(): String =
167
+ if (ContextCompat.checkSelfPermission(
168
+ reactContext.get()!!,
169
+ Manifest.permission.RECORD_AUDIO,
170
+ ) == PackageManager.PERMISSION_GRANTED
171
+ ) {
172
+ "Granted"
173
+ } else {
174
+ "Denied"
175
+ }
176
+
150
177
  @RequiresApi(Build.VERSION_CODES.O)
151
178
  private fun createChannel() {
152
179
  val notificationManager =
153
- reactContext.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
180
+ reactContext.get()?.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
154
181
 
155
182
  val mChannel =
156
- NotificationChannel(channelId, "Audio manager", NotificationManager.IMPORTANCE_LOW)
183
+ NotificationChannel(CHANNEL_ID, "Audio manager", NotificationManager.IMPORTANCE_LOW)
157
184
  mChannel.description = "Audio manager"
158
185
  mChannel.setShowBadge(false)
159
186
  mChannel.lockscreenVisibility = NotificationCompat.VISIBILITY_PUBLIC
@@ -5,18 +5,23 @@ import android.content.Context
5
5
  import android.content.Intent
6
6
  import android.content.IntentFilter
7
7
  import android.media.AudioManager
8
+ import com.swmansion.audioapi.AudioAPIModule
9
+ import java.lang.ref.WeakReference
10
+ import java.util.HashMap
8
11
 
9
12
  class VolumeChangeListener(
10
- private val audioManager: AudioManager,
11
- private val eventEmitter: MediaSessionEventEmitter,
13
+ private val audioManager: WeakReference<AudioManager>,
14
+ private val audioAPIModule: WeakReference<AudioAPIModule>,
12
15
  ) : BroadcastReceiver() {
13
16
  override fun onReceive(
14
17
  context: Context?,
15
18
  intent: Intent?,
16
19
  ) {
17
- val currentVolume = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC).toDouble()
18
- val maxVolume = audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC).toDouble()
19
- eventEmitter.onVolumeChange(mapOf("value" to currentVolume / maxVolume))
20
+ val currentVolume = audioManager.get()?.getStreamVolume(AudioManager.STREAM_MUSIC)?.toDouble()!!
21
+ val maxVolume = audioManager.get()?.getStreamMaxVolume(AudioManager.STREAM_MUSIC)?.toDouble()!!
22
+
23
+ val body = HashMap<String, Any>().apply { put("value", currentVolume / maxVolume) }
24
+ audioAPIModule.get()?.invokeHandlerWithEventNameAndEventBody("volumeChange", body)
20
25
  }
21
26
 
22
27
  fun getIntentFilter(): IntentFilter {
@@ -13,9 +13,12 @@
13
13
  package com.swmansion.audioapi;
14
14
 
15
15
  import com.facebook.proguard.annotations.DoNotStrip;
16
+ import com.facebook.react.bridge.Promise;
16
17
  import com.facebook.react.bridge.ReactApplicationContext;
17
18
  import com.facebook.react.bridge.ReactContextBaseJavaModule;
18
19
  import com.facebook.react.bridge.ReactMethod;
20
+ import com.facebook.react.bridge.ReadableArray;
21
+ import com.facebook.react.bridge.ReadableMap;
19
22
  import com.facebook.react.turbomodule.core.interfaces.TurboModule;
20
23
  import javax.annotation.Nonnull;
21
24
 
@@ -34,4 +37,40 @@ public abstract class NativeAudioAPIModuleSpec extends ReactContextBaseJavaModul
34
37
  @ReactMethod(isBlockingSynchronousMethod = true)
35
38
  @DoNotStrip
36
39
  public abstract boolean install();
40
+
41
+ @ReactMethod
42
+ @DoNotStrip
43
+ public abstract void setLockScreenInfo(ReadableMap info);
44
+
45
+ @ReactMethod
46
+ @DoNotStrip
47
+ public abstract void resetLockScreenInfo();
48
+
49
+ @ReactMethod
50
+ @DoNotStrip
51
+ public abstract void enableRemoteCommand(String name, boolean enabled);
52
+
53
+ @ReactMethod
54
+ @DoNotStrip
55
+ public abstract void setAudioSessionOptions(String category, String mode, ReadableArray options);
56
+
57
+ @ReactMethod(isBlockingSynchronousMethod = true)
58
+ @DoNotStrip
59
+ public abstract double getDevicePreferredSampleRate();
60
+
61
+ @ReactMethod
62
+ @DoNotStrip
63
+ public abstract void observeAudioInterruptions(boolean enabled);
64
+
65
+ @ReactMethod
66
+ @DoNotStrip
67
+ public abstract void observeVolumeChanges(boolean enabled);
68
+
69
+ @ReactMethod
70
+ @DoNotStrip
71
+ public abstract void requestRecordingPermissions(Promise promise);
72
+
73
+ @ReactMethod
74
+ @DoNotStrip
75
+ public abstract void checkRecordingPermissions(Promise promise);
37
76
  }
@@ -8,6 +8,9 @@
8
8
  #include <audioapi/HostObjects/OfflineAudioContextHostObject.h>
9
9
  #include <audioapi/HostObjects/AudioRecorderHostObject.h>
10
10
 
11
+ #include <audioapi/events/AudioEventHandlerRegistry.h>
12
+ #include <audioapi/events/AudioEventHandlerRegistryHostObject.h>
13
+
11
14
  #include <memory>
12
15
 
13
16
  namespace audioapi {
@@ -16,30 +19,33 @@ using namespace facebook;
16
19
 
17
20
  class AudioAPIModuleInstaller {
18
21
  public:
19
- static void injectJSIBindings(jsi::Runtime *jsiRuntime, const std::shared_ptr<react::CallInvoker> &jsCallInvoker) {
20
- auto createAudioContext = getCreateAudioContextFunction(jsiRuntime, jsCallInvoker);
21
- auto createAudioRecorder = getCreateAudioRecorderFunction(jsiRuntime, jsCallInvoker);
22
- auto createOfflineAudioContext = getCreateOfflineAudioContextFunction(jsiRuntime, jsCallInvoker);
22
+ static void injectJSIBindings(jsi::Runtime *jsiRuntime, const std::shared_ptr<react::CallInvoker> &jsCallInvoker, const std::shared_ptr<AudioEventHandlerRegistry> &audioEventHandlerRegistry) {
23
+ auto createAudioContext = getCreateAudioContextFunction(jsiRuntime, jsCallInvoker, audioEventHandlerRegistry);
24
+ auto createAudioRecorder = getCreateAudioRecorderFunction(jsiRuntime, audioEventHandlerRegistry);
25
+ auto createOfflineAudioContext = getCreateOfflineAudioContextFunction(jsiRuntime, jsCallInvoker, audioEventHandlerRegistry);
23
26
 
24
27
  jsiRuntime->global().setProperty(*jsiRuntime, "createAudioContext", createAudioContext);
25
28
  jsiRuntime->global().setProperty(*jsiRuntime, "createAudioRecorder", createAudioRecorder);
26
29
  jsiRuntime->global().setProperty(*jsiRuntime, "createOfflineAudioContext", createOfflineAudioContext);
30
+
31
+ auto audioEventHandlerRegistryHostObject = std::make_shared<AudioEventHandlerRegistryHostObject>(audioEventHandlerRegistry);
32
+ jsiRuntime->global().setProperty(*jsiRuntime, "AudioEventEmitter", jsi::Object::createFromHostObject(*jsiRuntime, audioEventHandlerRegistryHostObject));
27
33
  }
28
34
 
29
35
  private:
30
- static jsi::Function getCreateAudioContextFunction(jsi::Runtime *jsiRuntime, const std::shared_ptr<react::CallInvoker> &jsCallInvoker) {
36
+ static jsi::Function getCreateAudioContextFunction(jsi::Runtime *jsiRuntime, const std::shared_ptr<react::CallInvoker> &jsCallInvoker, const std::shared_ptr<AudioEventHandlerRegistry> &audioEventHandlerRegistry) {
31
37
  return jsi::Function::createFromHostFunction(
32
38
  *jsiRuntime,
33
39
  jsi::PropNameID::forAscii(*jsiRuntime, "createAudioContext"),
34
40
  0,
35
- [jsCallInvoker](
41
+ [jsCallInvoker, audioEventHandlerRegistry](
36
42
  jsi::Runtime &runtime,
37
43
  const jsi::Value &thisValue,
38
44
  const jsi::Value *args,
39
45
  size_t count) -> jsi::Value {
40
46
  std::shared_ptr<AudioContext> audioContext;
41
47
  auto sampleRate = static_cast<float>(args[0].getNumber());
42
- audioContext = std::make_shared<AudioContext>(sampleRate);
48
+ audioContext = std::make_shared<AudioContext>(sampleRate, audioEventHandlerRegistry);
43
49
 
44
50
  auto audioContextHostObject = std::make_shared<AudioContextHostObject>(
45
51
  audioContext, &runtime, jsCallInvoker);
@@ -49,12 +55,12 @@ class AudioAPIModuleInstaller {
49
55
  });
50
56
  }
51
57
 
52
- static jsi::Function getCreateOfflineAudioContextFunction(jsi::Runtime *jsiRuntime, const std::shared_ptr<react::CallInvoker> &jsCallInvoker) {
58
+ static jsi::Function getCreateOfflineAudioContextFunction(jsi::Runtime *jsiRuntime, const std::shared_ptr<react::CallInvoker> &jsCallInvoker, const std::shared_ptr<AudioEventHandlerRegistry> &audioEventHandlerRegistry) {
53
59
  return jsi::Function::createFromHostFunction(
54
60
  *jsiRuntime,
55
61
  jsi::PropNameID::forAscii(*jsiRuntime, "createOfflineAudioContext"),
56
62
  0,
57
- [jsiRuntime, jsCallInvoker](
63
+ [jsCallInvoker, audioEventHandlerRegistry](
58
64
  jsi::Runtime &runtime,
59
65
  const jsi::Value &thisValue,
60
66
  const jsi::Value *args,
@@ -63,21 +69,21 @@ class AudioAPIModuleInstaller {
63
69
  auto length = static_cast<size_t>(args[1].getNumber());
64
70
  auto sampleRate = static_cast<float>(args[2].getNumber());
65
71
 
66
- auto offlineAudioContext = std::make_shared<OfflineAudioContext>(numberOfChannels, length, sampleRate);
72
+ auto offlineAudioContext = std::make_shared<OfflineAudioContext>(numberOfChannels, length, sampleRate, audioEventHandlerRegistry);
67
73
  auto audioContextHostObject = std::make_shared<OfflineAudioContextHostObject>(
68
- offlineAudioContext, jsiRuntime, jsCallInvoker);
74
+ offlineAudioContext, &runtime, jsCallInvoker);
69
75
 
70
76
  return jsi::Object::createFromHostObject(
71
77
  runtime, audioContextHostObject);
72
78
  });
73
79
  }
74
80
 
75
- static jsi::Function getCreateAudioRecorderFunction(jsi::Runtime *jsiRuntime, const std::shared_ptr<react::CallInvoker> &jsCallInvoker) {
81
+ static jsi::Function getCreateAudioRecorderFunction(jsi::Runtime *jsiRuntime, const std::shared_ptr<AudioEventHandlerRegistry> &audioEventHandlerRegistry) {
76
82
  return jsi::Function::createFromHostFunction(
77
83
  *jsiRuntime,
78
84
  jsi::PropNameID::forAscii(*jsiRuntime, "createAudioRecorder"),
79
85
  0,
80
- [jsCallInvoker](
86
+ [audioEventHandlerRegistry](
81
87
  jsi::Runtime &runtime,
82
88
  const jsi::Value &thisValue,
83
89
  const jsi::Value *args,
@@ -87,7 +93,7 @@ class AudioAPIModuleInstaller {
87
93
  auto sampleRate = static_cast<float>(options.getProperty(runtime, "sampleRate").getNumber());
88
94
  auto bufferLength = static_cast<int>(options.getProperty(runtime, "bufferLengthInSamples").getNumber());
89
95
 
90
- auto audioRecorderHostObject = std::make_shared<AudioRecorderHostObject>(&runtime, jsCallInvoker, sampleRate, bufferLength);
96
+ auto audioRecorderHostObject = std::make_shared<AudioRecorderHostObject>(&runtime, audioEventHandlerRegistry, sampleRate, bufferLength);
91
97
 
92
98
  return jsi::Object::createFromHostObject(runtime, audioRecorderHostObject);
93
99
  });
@@ -15,9 +15,8 @@ class AudioBufferSourceNodeHostObject
15
15
  : public AudioScheduledSourceNodeHostObject {
16
16
  public:
17
17
  explicit AudioBufferSourceNodeHostObject(
18
- const std::shared_ptr<AudioBufferSourceNode> &node,
19
- const std::shared_ptr<react::CallInvoker> &callInvoker)
20
- : AudioScheduledSourceNodeHostObject(node, callInvoker) {
18
+ const std::shared_ptr<AudioBufferSourceNode> &node)
19
+ : AudioScheduledSourceNodeHostObject(node) {
21
20
  addGetters(
22
21
  JSI_EXPORT_PROPERTY_GETTER(AudioBufferSourceNodeHostObject, loop),
23
22
  JSI_EXPORT_PROPERTY_GETTER(AudioBufferSourceNodeHostObject, buffer),
@@ -1,7 +1,8 @@
1
1
  #pragma once
2
2
 
3
- #include <audioapi/jsi/JsiHostObject.h>
3
+ #include <audioapi/HostObjects/AudioParamHostObject.h>
4
4
  #include <audioapi/core/AudioNode.h>
5
+ #include <audioapi/jsi/JsiHostObject.h>
5
6
 
6
7
  #include <jsi/jsi.h>
7
8
  #include <memory>
@@ -47,21 +48,33 @@ class AudioNodeHostObject : public JsiHostObject {
47
48
  }
48
49
 
49
50
  JSI_HOST_FUNCTION(connect) {
50
- auto node =
51
- args[0].getObject(runtime).getHostObject<AudioNodeHostObject>(runtime);
52
- node_->connect(std::shared_ptr<AudioNodeHostObject>(node)->node_);
51
+ auto obj = args[0].getObject(runtime);
52
+ if (obj.isHostObject<AudioNodeHostObject>(runtime)) {
53
+ auto node = obj.getHostObject<AudioNodeHostObject>(runtime);
54
+ node_->connect(std::shared_ptr<AudioNodeHostObject>(node)->node_);
55
+ }
56
+ if (obj.isHostObject<AudioParamHostObject>(runtime)) {
57
+ auto param = obj.getHostObject<AudioParamHostObject>(runtime);
58
+ node_->connect(std::shared_ptr<AudioParamHostObject>(param)->param_);
59
+ }
53
60
  return jsi::Value::undefined();
54
61
  }
55
62
 
56
63
  JSI_HOST_FUNCTION(disconnect) {
57
- if(args[0].isUndefined()) {
58
- node_->disconnect();
59
- return jsi::Value::undefined();
60
- }
64
+ if (args[0].isUndefined()) {
65
+ node_->disconnect();
66
+ return jsi::Value::undefined();
67
+ }
68
+ auto obj = args[0].getObject(runtime);
69
+ if (obj.isHostObject<AudioNodeHostObject>(runtime)) {
70
+ auto node = obj.getHostObject<AudioNodeHostObject>(runtime);
71
+ node_->disconnect(std::shared_ptr<AudioNodeHostObject>(node)->node_);
72
+ }
61
73
 
62
- auto node =
63
- args[0].getObject(runtime).getHostObject<AudioNodeHostObject>(runtime);
64
- node_->disconnect(std::shared_ptr<AudioNodeHostObject>(node)->node_);
74
+ if (obj.isHostObject<AudioParamHostObject>(runtime)) {
75
+ auto param = obj.getHostObject<AudioParamHostObject>(runtime);
76
+ node_->disconnect(std::shared_ptr<AudioParamHostObject>(param)->param_);
77
+ }
65
78
  return jsi::Value::undefined();
66
79
  }
67
80
 
@@ -32,6 +32,7 @@ class AudioParamHostObject : public JsiHostObject {
32
32
 
33
33
  addSetters(JSI_EXPORT_PROPERTY_SETTER(AudioParamHostObject, value));
34
34
  }
35
+ friend class AudioNodeHostObject;
35
36
 
36
37
  JSI_PROPERTY_GETTER(value) {
37
38
  return {param_->getValue()};