react-native-queue-player 1.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 (1218) hide show
  1. package/LICENSE +201 -0
  2. package/QueuePlayer.podspec +114 -0
  3. package/README.md +194 -0
  4. package/android/CMakeLists.txt +41 -0
  5. package/android/build.gradle +257 -0
  6. package/android/src/androidTest/java/com/margelo/nitro/queueplayer/SignalsmithStretchNativeTest.kt +136 -0
  7. package/android/src/main/AndroidManifest.xml +173 -0
  8. package/android/src/main/cpp/CMakeLists.txt +221 -0
  9. package/android/src/main/cpp/THIRD_PARTY_LICENSES +128 -0
  10. package/android/src/main/cpp/THIRD_PARTY_VERSIONS.txt +32 -0
  11. package/android/src/main/cpp/airplay2_audio.c +537 -0
  12. package/android/src/main/cpp/airplay2_audio.h +66 -0
  13. package/android/src/main/cpp/airplay2_control.c +680 -0
  14. package/android/src/main/cpp/airplay2_control.h +101 -0
  15. package/android/src/main/cpp/airplay2_crypto.c +548 -0
  16. package/android/src/main/cpp/airplay2_crypto.h +213 -0
  17. package/android/src/main/cpp/airplay2_dmap.c +81 -0
  18. package/android/src/main/cpp/airplay2_dmap.h +53 -0
  19. package/android/src/main/cpp/airplay2_filelog.h +100 -0
  20. package/android/src/main/cpp/airplay2_jni.cpp +579 -0
  21. package/android/src/main/cpp/airplay2_ntp.c +203 -0
  22. package/android/src/main/cpp/airplay2_ntp.h +39 -0
  23. package/android/src/main/cpp/airplay2_pair.c +653 -0
  24. package/android/src/main/cpp/airplay2_pair.h +114 -0
  25. package/android/src/main/cpp/airplay2_plist.c +840 -0
  26. package/android/src/main/cpp/airplay2_plist.h +184 -0
  27. package/android/src/main/cpp/airplay2_ptp.c +509 -0
  28. package/android/src/main/cpp/airplay2_ptp.h +40 -0
  29. package/android/src/main/cpp/airplay2_rtsp.c +693 -0
  30. package/android/src/main/cpp/airplay2_rtsp.h +90 -0
  31. package/android/src/main/cpp/airplay2_session.c +196 -0
  32. package/android/src/main/cpp/airplay2_session.h +197 -0
  33. package/android/src/main/cpp/airplay2_tlv.c +135 -0
  34. package/android/src/main/cpp/airplay2_tlv.h +87 -0
  35. package/android/src/main/cpp/airplay_jni.cpp +589 -0
  36. package/android/src/main/cpp/build-openssl-android.sh +94 -0
  37. package/android/src/main/cpp/cpp-adapter.cpp +11 -0
  38. package/android/src/main/cpp/prebuilt/libsodium/arm64-v8a/lib/libsodium.a +0 -0
  39. package/android/src/main/cpp/prebuilt/libsodium/include/sodium/core.h +28 -0
  40. package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_aead_aegis128l.h +92 -0
  41. package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_aead_aegis256.h +92 -0
  42. package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_aead_aes256gcm.h +179 -0
  43. package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_aead_chacha20poly1305.h +180 -0
  44. package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_aead_xchacha20poly1305.h +100 -0
  45. package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_auth.h +46 -0
  46. package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_auth_hmacsha256.h +70 -0
  47. package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_auth_hmacsha512.h +68 -0
  48. package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_auth_hmacsha512256.h +65 -0
  49. package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_box.h +177 -0
  50. package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_box_curve25519xchacha20poly1305.h +164 -0
  51. package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_box_curve25519xsalsa20poly1305.h +112 -0
  52. package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_core_ed25519.h +104 -0
  53. package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_core_hchacha20.h +36 -0
  54. package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_core_hsalsa20.h +36 -0
  55. package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_core_ristretto255.h +100 -0
  56. package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_core_salsa20.h +36 -0
  57. package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_core_salsa2012.h +36 -0
  58. package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_core_salsa208.h +40 -0
  59. package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_generichash.h +84 -0
  60. package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_generichash_blake2b.h +122 -0
  61. package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_hash.h +40 -0
  62. package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_hash_sha256.h +60 -0
  63. package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_hash_sha512.h +60 -0
  64. package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_kdf.h +53 -0
  65. package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_kdf_blake2b.h +44 -0
  66. package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_kdf_hkdf_sha256.h +74 -0
  67. package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_kdf_hkdf_sha512.h +75 -0
  68. package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_kx.h +66 -0
  69. package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_onetimeauth.h +65 -0
  70. package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_onetimeauth_poly1305.h +72 -0
  71. package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_pwhash.h +147 -0
  72. package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_pwhash_argon2i.h +122 -0
  73. package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_pwhash_argon2id.h +122 -0
  74. package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_pwhash_scryptsalsa208sha256.h +120 -0
  75. package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_scalarmult.h +46 -0
  76. package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_scalarmult_curve25519.h +42 -0
  77. package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_scalarmult_ed25519.h +51 -0
  78. package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_scalarmult_ristretto255.h +43 -0
  79. package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_secretbox.h +93 -0
  80. package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_secretbox_xchacha20poly1305.h +70 -0
  81. package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_secretbox_xsalsa20poly1305.h +69 -0
  82. package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_secretstream_xchacha20poly1305.h +108 -0
  83. package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_shorthash.h +41 -0
  84. package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_shorthash_siphash24.h +50 -0
  85. package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_sign.h +107 -0
  86. package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_sign_ed25519.h +124 -0
  87. package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_sign_edwards25519sha512batch.h +55 -0
  88. package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_stream.h +59 -0
  89. package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_stream_chacha20.h +106 -0
  90. package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_stream_salsa20.h +61 -0
  91. package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_stream_salsa2012.h +53 -0
  92. package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_stream_salsa208.h +56 -0
  93. package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_stream_xchacha20.h +61 -0
  94. package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_stream_xsalsa20.h +61 -0
  95. package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_verify_16.h +23 -0
  96. package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_verify_32.h +23 -0
  97. package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_verify_64.h +23 -0
  98. package/android/src/main/cpp/prebuilt/libsodium/include/sodium/export.h +57 -0
  99. package/android/src/main/cpp/prebuilt/libsodium/include/sodium/randombytes.h +72 -0
  100. package/android/src/main/cpp/prebuilt/libsodium/include/sodium/randombytes_internal_random.h +22 -0
  101. package/android/src/main/cpp/prebuilt/libsodium/include/sodium/randombytes_sysrandom.h +19 -0
  102. package/android/src/main/cpp/prebuilt/libsodium/include/sodium/runtime.h +55 -0
  103. package/android/src/main/cpp/prebuilt/libsodium/include/sodium/utils.h +179 -0
  104. package/android/src/main/cpp/prebuilt/libsodium/include/sodium/version.h +33 -0
  105. package/android/src/main/cpp/prebuilt/libsodium/include/sodium.h +75 -0
  106. package/android/src/main/cpp/prebuilt/libsodium/x86_64/lib/libsodium.a +0 -0
  107. package/android/src/main/cpp/prebuilt/openssl/arm64-v8a/lib/libcrypto.a +0 -0
  108. package/android/src/main/cpp/prebuilt/openssl/arm64-v8a/lib/libssl.a +0 -0
  109. package/android/src/main/cpp/prebuilt/openssl/x86_64/lib/libcrypto.a +0 -0
  110. package/android/src/main/cpp/prebuilt/openssl/x86_64/lib/libssl.a +0 -0
  111. package/android/src/main/cpp/stretch_jni.cpp +171 -0
  112. package/android/src/main/cpp/third_party/alac/addons/alac_wrapper.cpp +198 -0
  113. package/android/src/main/cpp/third_party/alac/addons/alac_wrapper.h +46 -0
  114. package/android/src/main/cpp/third_party/alac/codec/ALACAudioTypes.h +197 -0
  115. package/android/src/main/cpp/third_party/alac/codec/ALACBitUtilities.c +260 -0
  116. package/android/src/main/cpp/third_party/alac/codec/ALACBitUtilities.h +104 -0
  117. package/android/src/main/cpp/third_party/alac/codec/ALACDecoder.cpp +730 -0
  118. package/android/src/main/cpp/third_party/alac/codec/ALACDecoder.h +65 -0
  119. package/android/src/main/cpp/third_party/alac/codec/ALACEncoder.cpp +1425 -0
  120. package/android/src/main/cpp/third_party/alac/codec/ALACEncoder.h +92 -0
  121. package/android/src/main/cpp/third_party/alac/codec/EndianPortable.c +181 -0
  122. package/android/src/main/cpp/third_party/alac/codec/EndianPortable.h +59 -0
  123. package/android/src/main/cpp/third_party/alac/codec/ag_dec.c +362 -0
  124. package/android/src/main/cpp/third_party/alac/codec/ag_enc.c +370 -0
  125. package/android/src/main/cpp/third_party/alac/codec/aglib.h +81 -0
  126. package/android/src/main/cpp/third_party/alac/codec/dp_dec.c +381 -0
  127. package/android/src/main/cpp/third_party/alac/codec/dp_enc.c +386 -0
  128. package/android/src/main/cpp/third_party/alac/codec/dplib.h +61 -0
  129. package/android/src/main/cpp/third_party/alac/codec/matrix_dec.c +390 -0
  130. package/android/src/main/cpp/third_party/alac/codec/matrix_enc.c +342 -0
  131. package/android/src/main/cpp/third_party/alac/codec/matrixlib.h +80 -0
  132. package/android/src/main/cpp/third_party/crosstools/cross_log.c +95 -0
  133. package/android/src/main/cpp/third_party/crosstools/cross_log.h +25 -0
  134. package/android/src/main/cpp/third_party/crosstools/cross_net.c +1139 -0
  135. package/android/src/main/cpp/third_party/crosstools/cross_net.h +51 -0
  136. package/android/src/main/cpp/third_party/crosstools/cross_ssl.c +371 -0
  137. package/android/src/main/cpp/third_party/crosstools/cross_ssl.h +15 -0
  138. package/android/src/main/cpp/third_party/crosstools/cross_thread.c +134 -0
  139. package/android/src/main/cpp/third_party/crosstools/cross_thread.h +20 -0
  140. package/android/src/main/cpp/third_party/crosstools/cross_util.c +753 -0
  141. package/android/src/main/cpp/third_party/crosstools/cross_util.h +125 -0
  142. package/android/src/main/cpp/third_party/crosstools/platform.c +227 -0
  143. package/android/src/main/cpp/third_party/crosstools/platform.h +127 -0
  144. package/android/src/main/cpp/third_party/curve25519/include/curve25519_dh.h +53 -0
  145. package/android/src/main/cpp/third_party/curve25519/include/ed25519_signature.h +98 -0
  146. package/android/src/main/cpp/third_party/curve25519/include/external_calls.h +36 -0
  147. package/android/src/main/cpp/third_party/curve25519/source/BaseTypes.h +125 -0
  148. package/android/src/main/cpp/third_party/curve25519/source/base_folding8.h +1288 -0
  149. package/android/src/main/cpp/third_party/curve25519/source/curve25519_dh.c +208 -0
  150. package/android/src/main/cpp/third_party/curve25519/source/curve25519_mehdi.c +410 -0
  151. package/android/src/main/cpp/third_party/curve25519/source/curve25519_mehdi.h +175 -0
  152. package/android/src/main/cpp/third_party/curve25519/source/curve25519_order.c +155 -0
  153. package/android/src/main/cpp/third_party/curve25519/source/curve25519_utils.c +153 -0
  154. package/android/src/main/cpp/third_party/curve25519/source/custom_blind.c +27 -0
  155. package/android/src/main/cpp/third_party/curve25519/source/custom_blind.h +11 -0
  156. package/android/src/main/cpp/third_party/curve25519/source/ed25519_sign.c +419 -0
  157. package/android/src/main/cpp/third_party/curve25519/source/ed25519_signature.h +98 -0
  158. package/android/src/main/cpp/third_party/curve25519/source/ed25519_verify.c +313 -0
  159. package/android/src/main/cpp/third_party/curve25519/source/sha512.c +294 -0
  160. package/android/src/main/cpp/third_party/curve25519/source/sha512.h +93 -0
  161. package/android/src/main/cpp/third_party/dmap-parser/dmap_parser.c +545 -0
  162. package/android/src/main/cpp/third_party/dmap-parser/dmap_parser.h +90 -0
  163. package/android/src/main/cpp/third_party/libraop/aes.c +863 -0
  164. package/android/src/main/cpp/third_party/libraop/aes.h +18 -0
  165. package/android/src/main/cpp/third_party/libraop/aes_ctr.c +89 -0
  166. package/android/src/main/cpp/third_party/libraop/aes_ctr.h +59 -0
  167. package/android/src/main/cpp/third_party/libraop/alac.c +1135 -0
  168. package/android/src/main/cpp/third_party/libraop/alac.h +55 -0
  169. package/android/src/main/cpp/third_party/libraop/raop_client.c +1500 -0
  170. package/android/src/main/cpp/third_party/libraop/raop_client.h +178 -0
  171. package/android/src/main/cpp/third_party/libraop/rtsp_client.c +743 -0
  172. package/android/src/main/cpp/third_party/libraop/rtsp_client.h +50 -0
  173. package/android/src/main/cpp/third_party/openssl/include/openssl/__DECC_INCLUDE_EPILOGUE.H +22 -0
  174. package/android/src/main/cpp/third_party/openssl/include/openssl/__DECC_INCLUDE_PROLOGUE.H +26 -0
  175. package/android/src/main/cpp/third_party/openssl/include/openssl/aes.h +111 -0
  176. package/android/src/main/cpp/third_party/openssl/include/openssl/asn1.h +1134 -0
  177. package/android/src/main/cpp/third_party/openssl/include/openssl/asn1.h.in +967 -0
  178. package/android/src/main/cpp/third_party/openssl/include/openssl/asn1err.h +142 -0
  179. package/android/src/main/cpp/third_party/openssl/include/openssl/asn1t.h +946 -0
  180. package/android/src/main/cpp/third_party/openssl/include/openssl/asn1t.h.in +923 -0
  181. package/android/src/main/cpp/third_party/openssl/include/openssl/async.h +104 -0
  182. package/android/src/main/cpp/third_party/openssl/include/openssl/asyncerr.h +29 -0
  183. package/android/src/main/cpp/third_party/openssl/include/openssl/bio.h +1022 -0
  184. package/android/src/main/cpp/third_party/openssl/include/openssl/bio.h.in +999 -0
  185. package/android/src/main/cpp/third_party/openssl/include/openssl/bioerr.h +72 -0
  186. package/android/src/main/cpp/third_party/openssl/include/openssl/blowfish.h +78 -0
  187. package/android/src/main/cpp/third_party/openssl/include/openssl/bn.h +590 -0
  188. package/android/src/main/cpp/third_party/openssl/include/openssl/bnerr.h +47 -0
  189. package/android/src/main/cpp/third_party/openssl/include/openssl/buffer.h +62 -0
  190. package/android/src/main/cpp/third_party/openssl/include/openssl/buffererr.h +25 -0
  191. package/android/src/main/cpp/third_party/openssl/include/openssl/byteorder.h +339 -0
  192. package/android/src/main/cpp/third_party/openssl/include/openssl/camellia.h +117 -0
  193. package/android/src/main/cpp/third_party/openssl/include/openssl/cast.h +71 -0
  194. package/android/src/main/cpp/third_party/openssl/include/openssl/cmac.h +52 -0
  195. package/android/src/main/cpp/third_party/openssl/include/openssl/cmp.h +727 -0
  196. package/android/src/main/cpp/third_party/openssl/include/openssl/cmp.h.in +584 -0
  197. package/android/src/main/cpp/third_party/openssl/include/openssl/cmp_util.h +56 -0
  198. package/android/src/main/cpp/third_party/openssl/include/openssl/cmperr.h +134 -0
  199. package/android/src/main/cpp/third_party/openssl/include/openssl/cms.h +511 -0
  200. package/android/src/main/cpp/third_party/openssl/include/openssl/cms.h.in +413 -0
  201. package/android/src/main/cpp/third_party/openssl/include/openssl/cmserr.h +126 -0
  202. package/android/src/main/cpp/third_party/openssl/include/openssl/comp.h +98 -0
  203. package/android/src/main/cpp/third_party/openssl/include/openssl/comp.h.in +76 -0
  204. package/android/src/main/cpp/third_party/openssl/include/openssl/comperr.h +38 -0
  205. package/android/src/main/cpp/third_party/openssl/include/openssl/conf.h +214 -0
  206. package/android/src/main/cpp/third_party/openssl/include/openssl/conf.h.in +177 -0
  207. package/android/src/main/cpp/third_party/openssl/include/openssl/conf_api.h +46 -0
  208. package/android/src/main/cpp/third_party/openssl/include/openssl/conferr.h +52 -0
  209. package/android/src/main/cpp/third_party/openssl/include/openssl/configuration.h +212 -0
  210. package/android/src/main/cpp/third_party/openssl/include/openssl/configuration.h.in +75 -0
  211. package/android/src/main/cpp/third_party/openssl/include/openssl/conftypes.h +44 -0
  212. package/android/src/main/cpp/third_party/openssl/include/openssl/core.h +236 -0
  213. package/android/src/main/cpp/third_party/openssl/include/openssl/core_dispatch.h +1141 -0
  214. package/android/src/main/cpp/third_party/openssl/include/openssl/core_names.h +575 -0
  215. package/android/src/main/cpp/third_party/openssl/include/openssl/core_names.h.in +126 -0
  216. package/android/src/main/cpp/third_party/openssl/include/openssl/core_object.h +41 -0
  217. package/android/src/main/cpp/third_party/openssl/include/openssl/crmf.h +278 -0
  218. package/android/src/main/cpp/third_party/openssl/include/openssl/crmf.h.in +207 -0
  219. package/android/src/main/cpp/third_party/openssl/include/openssl/crmferr.h +57 -0
  220. package/android/src/main/cpp/third_party/openssl/include/openssl/crypto.h +583 -0
  221. package/android/src/main/cpp/third_party/openssl/include/openssl/crypto.h.in +560 -0
  222. package/android/src/main/cpp/third_party/openssl/include/openssl/cryptoerr.h +56 -0
  223. package/android/src/main/cpp/third_party/openssl/include/openssl/cryptoerr_legacy.h +1466 -0
  224. package/android/src/main/cpp/third_party/openssl/include/openssl/ct.h +573 -0
  225. package/android/src/main/cpp/third_party/openssl/include/openssl/ct.h.in +525 -0
  226. package/android/src/main/cpp/third_party/openssl/include/openssl/cterr.h +45 -0
  227. package/android/src/main/cpp/third_party/openssl/include/openssl/decoder.h +133 -0
  228. package/android/src/main/cpp/third_party/openssl/include/openssl/decodererr.h +28 -0
  229. package/android/src/main/cpp/third_party/openssl/include/openssl/des.h +211 -0
  230. package/android/src/main/cpp/third_party/openssl/include/openssl/dh.h +339 -0
  231. package/android/src/main/cpp/third_party/openssl/include/openssl/dherr.h +59 -0
  232. package/android/src/main/cpp/third_party/openssl/include/openssl/dsa.h +280 -0
  233. package/android/src/main/cpp/third_party/openssl/include/openssl/dsaerr.h +44 -0
  234. package/android/src/main/cpp/third_party/openssl/include/openssl/dtls1.h +57 -0
  235. package/android/src/main/cpp/third_party/openssl/include/openssl/e_os2.h +310 -0
  236. package/android/src/main/cpp/third_party/openssl/include/openssl/e_ostime.h +38 -0
  237. package/android/src/main/cpp/third_party/openssl/include/openssl/ebcdic.h +39 -0
  238. package/android/src/main/cpp/third_party/openssl/include/openssl/ec.h +1588 -0
  239. package/android/src/main/cpp/third_party/openssl/include/openssl/ecdh.h +10 -0
  240. package/android/src/main/cpp/third_party/openssl/include/openssl/ecdsa.h +10 -0
  241. package/android/src/main/cpp/third_party/openssl/include/openssl/ecerr.h +104 -0
  242. package/android/src/main/cpp/third_party/openssl/include/openssl/encoder.h +124 -0
  243. package/android/src/main/cpp/third_party/openssl/include/openssl/encodererr.h +28 -0
  244. package/android/src/main/cpp/third_party/openssl/include/openssl/engine.h +833 -0
  245. package/android/src/main/cpp/third_party/openssl/include/openssl/engineerr.h +63 -0
  246. package/android/src/main/cpp/third_party/openssl/include/openssl/err.h +512 -0
  247. package/android/src/main/cpp/third_party/openssl/include/openssl/err.h.in +501 -0
  248. package/android/src/main/cpp/third_party/openssl/include/openssl/ess.h +128 -0
  249. package/android/src/main/cpp/third_party/openssl/include/openssl/ess.h.in +81 -0
  250. package/android/src/main/cpp/third_party/openssl/include/openssl/esserr.h +32 -0
  251. package/android/src/main/cpp/third_party/openssl/include/openssl/evp.h +2310 -0
  252. package/android/src/main/cpp/third_party/openssl/include/openssl/evperr.h +142 -0
  253. package/android/src/main/cpp/third_party/openssl/include/openssl/fips_names.h +50 -0
  254. package/android/src/main/cpp/third_party/openssl/include/openssl/fipskey.h +41 -0
  255. package/android/src/main/cpp/third_party/openssl/include/openssl/fipskey.h.in +40 -0
  256. package/android/src/main/cpp/third_party/openssl/include/openssl/hmac.h +62 -0
  257. package/android/src/main/cpp/third_party/openssl/include/openssl/hpke.h +169 -0
  258. package/android/src/main/cpp/third_party/openssl/include/openssl/http.h +119 -0
  259. package/android/src/main/cpp/third_party/openssl/include/openssl/httperr.h +56 -0
  260. package/android/src/main/cpp/third_party/openssl/include/openssl/idea.h +82 -0
  261. package/android/src/main/cpp/third_party/openssl/include/openssl/indicator.h +31 -0
  262. package/android/src/main/cpp/third_party/openssl/include/openssl/kdf.h +138 -0
  263. package/android/src/main/cpp/third_party/openssl/include/openssl/kdferr.h +16 -0
  264. package/android/src/main/cpp/third_party/openssl/include/openssl/lhash.h +398 -0
  265. package/android/src/main/cpp/third_party/openssl/include/openssl/lhash.h.in +373 -0
  266. package/android/src/main/cpp/third_party/openssl/include/openssl/macros.h +349 -0
  267. package/android/src/main/cpp/third_party/openssl/include/openssl/md2.h +56 -0
  268. package/android/src/main/cpp/third_party/openssl/include/openssl/md4.h +63 -0
  269. package/android/src/main/cpp/third_party/openssl/include/openssl/md5.h +62 -0
  270. package/android/src/main/cpp/third_party/openssl/include/openssl/mdc2.h +55 -0
  271. package/android/src/main/cpp/third_party/openssl/include/openssl/ml_kem.h +31 -0
  272. package/android/src/main/cpp/third_party/openssl/include/openssl/modes.h +219 -0
  273. package/android/src/main/cpp/third_party/openssl/include/openssl/obj_mac.h +6636 -0
  274. package/android/src/main/cpp/third_party/openssl/include/openssl/objects.h +184 -0
  275. package/android/src/main/cpp/third_party/openssl/include/openssl/objectserr.h +28 -0
  276. package/android/src/main/cpp/third_party/openssl/include/openssl/ocsp.h +483 -0
  277. package/android/src/main/cpp/third_party/openssl/include/openssl/ocsp.h.in +387 -0
  278. package/android/src/main/cpp/third_party/openssl/include/openssl/ocsperr.h +53 -0
  279. package/android/src/main/cpp/third_party/openssl/include/openssl/opensslconf.h +17 -0
  280. package/android/src/main/cpp/third_party/openssl/include/openssl/opensslv.h +114 -0
  281. package/android/src/main/cpp/third_party/openssl/include/openssl/opensslv.h.in +113 -0
  282. package/android/src/main/cpp/third_party/openssl/include/openssl/ossl_typ.h +16 -0
  283. package/android/src/main/cpp/third_party/openssl/include/openssl/param_build.h +63 -0
  284. package/android/src/main/cpp/third_party/openssl/include/openssl/params.h +163 -0
  285. package/android/src/main/cpp/third_party/openssl/include/openssl/pem.h +547 -0
  286. package/android/src/main/cpp/third_party/openssl/include/openssl/pem2.h +19 -0
  287. package/android/src/main/cpp/third_party/openssl/include/openssl/pemerr.h +59 -0
  288. package/android/src/main/cpp/third_party/openssl/include/openssl/pkcs12.h +366 -0
  289. package/android/src/main/cpp/third_party/openssl/include/openssl/pkcs12.h.in +343 -0
  290. package/android/src/main/cpp/third_party/openssl/include/openssl/pkcs12err.h +46 -0
  291. package/android/src/main/cpp/third_party/openssl/include/openssl/pkcs7.h +430 -0
  292. package/android/src/main/cpp/third_party/openssl/include/openssl/pkcs7.h.in +359 -0
  293. package/android/src/main/cpp/third_party/openssl/include/openssl/pkcs7err.h +63 -0
  294. package/android/src/main/cpp/third_party/openssl/include/openssl/prov_ssl.h +38 -0
  295. package/android/src/main/cpp/third_party/openssl/include/openssl/proverr.h +169 -0
  296. package/android/src/main/cpp/third_party/openssl/include/openssl/provider.h +94 -0
  297. package/android/src/main/cpp/third_party/openssl/include/openssl/quic.h +75 -0
  298. package/android/src/main/cpp/third_party/openssl/include/openssl/rand.h +131 -0
  299. package/android/src/main/cpp/third_party/openssl/include/openssl/randerr.h +70 -0
  300. package/android/src/main/cpp/third_party/openssl/include/openssl/rc2.h +68 -0
  301. package/android/src/main/cpp/third_party/openssl/include/openssl/rc4.h +47 -0
  302. package/android/src/main/cpp/third_party/openssl/include/openssl/rc5.h +79 -0
  303. package/android/src/main/cpp/third_party/openssl/include/openssl/ripemd.h +59 -0
  304. package/android/src/main/cpp/third_party/openssl/include/openssl/rsa.h +615 -0
  305. package/android/src/main/cpp/third_party/openssl/include/openssl/rsaerr.h +107 -0
  306. package/android/src/main/cpp/third_party/openssl/include/openssl/safestack.h +297 -0
  307. package/android/src/main/cpp/third_party/openssl/include/openssl/safestack.h.in +227 -0
  308. package/android/src/main/cpp/third_party/openssl/include/openssl/seed.h +113 -0
  309. package/android/src/main/cpp/third_party/openssl/include/openssl/self_test.h +112 -0
  310. package/android/src/main/cpp/third_party/openssl/include/openssl/sha.h +139 -0
  311. package/android/src/main/cpp/third_party/openssl/include/openssl/srp.h +285 -0
  312. package/android/src/main/cpp/third_party/openssl/include/openssl/srp.h.in +214 -0
  313. package/android/src/main/cpp/third_party/openssl/include/openssl/srtp.h +68 -0
  314. package/android/src/main/cpp/third_party/openssl/include/openssl/ssl.h +2933 -0
  315. package/android/src/main/cpp/third_party/openssl/include/openssl/ssl.h.in +2886 -0
  316. package/android/src/main/cpp/third_party/openssl/include/openssl/ssl2.h +30 -0
  317. package/android/src/main/cpp/third_party/openssl/include/openssl/ssl3.h +358 -0
  318. package/android/src/main/cpp/third_party/openssl/include/openssl/sslerr.h +382 -0
  319. package/android/src/main/cpp/third_party/openssl/include/openssl/sslerr_legacy.h +467 -0
  320. package/android/src/main/cpp/third_party/openssl/include/openssl/stack.h +90 -0
  321. package/android/src/main/cpp/third_party/openssl/include/openssl/store.h +377 -0
  322. package/android/src/main/cpp/third_party/openssl/include/openssl/storeerr.h +49 -0
  323. package/android/src/main/cpp/third_party/openssl/include/openssl/symhacks.h +39 -0
  324. package/android/src/main/cpp/third_party/openssl/include/openssl/thread.h +31 -0
  325. package/android/src/main/cpp/third_party/openssl/include/openssl/tls1.h +1220 -0
  326. package/android/src/main/cpp/third_party/openssl/include/openssl/trace.h +321 -0
  327. package/android/src/main/cpp/third_party/openssl/include/openssl/ts.h +522 -0
  328. package/android/src/main/cpp/third_party/openssl/include/openssl/tserr.h +67 -0
  329. package/android/src/main/cpp/third_party/openssl/include/openssl/txt_db.h +63 -0
  330. package/android/src/main/cpp/third_party/openssl/include/openssl/types.h +248 -0
  331. package/android/src/main/cpp/third_party/openssl/include/openssl/ui.h +407 -0
  332. package/android/src/main/cpp/third_party/openssl/include/openssl/ui.h.in +384 -0
  333. package/android/src/main/cpp/third_party/openssl/include/openssl/uierr.h +38 -0
  334. package/android/src/main/cpp/third_party/openssl/include/openssl/whrlpool.h +62 -0
  335. package/android/src/main/cpp/third_party/openssl/include/openssl/x509.h +1303 -0
  336. package/android/src/main/cpp/third_party/openssl/include/openssl/x509.h.in +1109 -0
  337. package/android/src/main/cpp/third_party/openssl/include/openssl/x509_acert.h +294 -0
  338. package/android/src/main/cpp/third_party/openssl/include/openssl/x509_acert.h.in +199 -0
  339. package/android/src/main/cpp/third_party/openssl/include/openssl/x509_vfy.h +903 -0
  340. package/android/src/main/cpp/third_party/openssl/include/openssl/x509_vfy.h.in +806 -0
  341. package/android/src/main/cpp/third_party/openssl/include/openssl/x509err.h +70 -0
  342. package/android/src/main/cpp/third_party/openssl/include/openssl/x509v3.h +1968 -0
  343. package/android/src/main/cpp/third_party/openssl/include/openssl/x509v3.h.in +1367 -0
  344. package/android/src/main/cpp/third_party/openssl/include/openssl/x509v3err.h +97 -0
  345. package/android/src/main/cpp/third_party/pair_ap/pair-internal.h +390 -0
  346. package/android/src/main/cpp/third_party/pair_ap/pair-tlv.c +221 -0
  347. package/android/src/main/cpp/third_party/pair_ap/pair-tlv.h +77 -0
  348. package/android/src/main/cpp/third_party/pair_ap/pair.c +806 -0
  349. package/android/src/main/cpp/third_party/pair_ap/pair.h +266 -0
  350. package/android/src/main/cpp/third_party/pair_ap/pair_fruit_stub.c +36 -0
  351. package/android/src/main/cpp/third_party/pair_ap/pair_homekit.c +3190 -0
  352. package/android/src/main/cpp/third_party/signalsmith/LICENSE-signalsmith-linear.txt +21 -0
  353. package/android/src/main/cpp/third_party/signalsmith/LICENSE-signalsmith-stretch.txt +21 -0
  354. package/android/src/main/cpp/third_party/signalsmith/THIRD_PARTY_VERSIONS.txt +9 -0
  355. package/android/src/main/cpp/third_party/signalsmith/include/signalsmith-linear/fft.h +1380 -0
  356. package/android/src/main/cpp/third_party/signalsmith/include/signalsmith-linear/linear.h +1075 -0
  357. package/android/src/main/cpp/third_party/signalsmith/include/signalsmith-linear/stft.h +643 -0
  358. package/android/src/main/cpp/third_party/signalsmith/include/signalsmith-stretch.h +1060 -0
  359. package/android/src/main/java/com/margelo/nitro/queueplayer/AirPlayEngine.kt +314 -0
  360. package/android/src/main/java/com/margelo/nitro/queueplayer/ArtworkContentProvider.kt +124 -0
  361. package/android/src/main/java/com/margelo/nitro/queueplayer/AudioFocusErrorMapping.kt +89 -0
  362. package/android/src/main/java/com/margelo/nitro/queueplayer/AudioPipelineRenderersFactory.kt +60 -0
  363. package/android/src/main/java/com/margelo/nitro/queueplayer/BrowseCallbackRegistry.kt +136 -0
  364. package/android/src/main/java/com/margelo/nitro/queueplayer/BrowseDataProvider.kt +128 -0
  365. package/android/src/main/java/com/margelo/nitro/queueplayer/BufferStateTranslator.kt +35 -0
  366. package/android/src/main/java/com/margelo/nitro/queueplayer/CacheMimeTypes.kt +79 -0
  367. package/android/src/main/java/com/margelo/nitro/queueplayer/CastManager.kt +629 -0
  368. package/android/src/main/java/com/margelo/nitro/queueplayer/CrossfadeEngine.kt +1350 -0
  369. package/android/src/main/java/com/margelo/nitro/queueplayer/CrossfadeForwardingPlayer.kt +66 -0
  370. package/android/src/main/java/com/margelo/nitro/queueplayer/CustomPresetStore.kt +100 -0
  371. package/android/src/main/java/com/margelo/nitro/queueplayer/Equalizer.kt +348 -0
  372. package/android/src/main/java/com/margelo/nitro/queueplayer/EqualizerEngine.kt +222 -0
  373. package/android/src/main/java/com/margelo/nitro/queueplayer/EqualizerLegacyEngine.kt +213 -0
  374. package/android/src/main/java/com/margelo/nitro/queueplayer/EqualizerPresets.kt +45 -0
  375. package/android/src/main/java/com/margelo/nitro/queueplayer/FFTProcessorTee.kt +173 -0
  376. package/android/src/main/java/com/margelo/nitro/queueplayer/FifoCacheEvictor.kt +96 -0
  377. package/android/src/main/java/com/margelo/nitro/queueplayer/GaplessEngine.kt +587 -0
  378. package/android/src/main/java/com/margelo/nitro/queueplayer/HeadlessJsMediaService.kt +220 -0
  379. package/android/src/main/java/com/margelo/nitro/queueplayer/IEqualizerEngine.kt +97 -0
  380. package/android/src/main/java/com/margelo/nitro/queueplayer/ListenerRegistry.kt +59 -0
  381. package/android/src/main/java/com/margelo/nitro/queueplayer/LookaheadCache.kt +343 -0
  382. package/android/src/main/java/com/margelo/nitro/queueplayer/LookaheadCacheWriter.kt +533 -0
  383. package/android/src/main/java/com/margelo/nitro/queueplayer/MediaButtonDispatch.kt +88 -0
  384. package/android/src/main/java/com/margelo/nitro/queueplayer/MediaItemBuilder.kt +281 -0
  385. package/android/src/main/java/com/margelo/nitro/queueplayer/MediaItemMapper.kt +76 -0
  386. package/android/src/main/java/com/margelo/nitro/queueplayer/MilestoneTracker.kt +66 -0
  387. package/android/src/main/java/com/margelo/nitro/queueplayer/MimeCapturingDataSource.kt +64 -0
  388. package/android/src/main/java/com/margelo/nitro/queueplayer/MultiplexingAudioBufferSink.kt +92 -0
  389. package/android/src/main/java/com/margelo/nitro/queueplayer/NotificationProvider.kt +37 -0
  390. package/android/src/main/java/com/margelo/nitro/queueplayer/NowPlayingFormatExtractor.kt +166 -0
  391. package/android/src/main/java/com/margelo/nitro/queueplayer/PendingBrowseRequests.kt +70 -0
  392. package/android/src/main/java/com/margelo/nitro/queueplayer/PendingIntentBuffer.kt +82 -0
  393. package/android/src/main/java/com/margelo/nitro/queueplayer/PitchAwareAudioProcessorChain.kt +69 -0
  394. package/android/src/main/java/com/margelo/nitro/queueplayer/PitchCorrection.kt +27 -0
  395. package/android/src/main/java/com/margelo/nitro/queueplayer/PlaceholderArtwork.kt +65 -0
  396. package/android/src/main/java/com/margelo/nitro/queueplayer/PlaceholderFallbackBitmapLoader.kt +75 -0
  397. package/android/src/main/java/com/margelo/nitro/queueplayer/PlaybackEngine.kt +336 -0
  398. package/android/src/main/java/com/margelo/nitro/queueplayer/PlaybackErrorMapping.kt +175 -0
  399. package/android/src/main/java/com/margelo/nitro/queueplayer/PlaybackModeStateMachine.kt +127 -0
  400. package/android/src/main/java/com/margelo/nitro/queueplayer/PlaybackService.kt +1716 -0
  401. package/android/src/main/java/com/margelo/nitro/queueplayer/PlaybackServiceCallback.kt +755 -0
  402. package/android/src/main/java/com/margelo/nitro/queueplayer/ProgressEmissionGate.kt +70 -0
  403. package/android/src/main/java/com/margelo/nitro/queueplayer/QueueMutationArithmetic.kt +131 -0
  404. package/android/src/main/java/com/margelo/nitro/queueplayer/QueuePlayerPackage.kt +22 -0
  405. package/android/src/main/java/com/margelo/nitro/queueplayer/QueueSkipArithmetic.kt +113 -0
  406. package/android/src/main/java/com/margelo/nitro/queueplayer/RadixTwoFFT.kt +176 -0
  407. package/android/src/main/java/com/margelo/nitro/queueplayer/RemoteCommandDeduper.kt +81 -0
  408. package/android/src/main/java/com/margelo/nitro/queueplayer/ReplayGainAudioProcessor.kt +84 -0
  409. package/android/src/main/java/com/margelo/nitro/queueplayer/ReplayGainConfig.kt +34 -0
  410. package/android/src/main/java/com/margelo/nitro/queueplayer/ReplayGainData.kt +44 -0
  411. package/android/src/main/java/com/margelo/nitro/queueplayer/ReplayGainExtractor.kt +209 -0
  412. package/android/src/main/java/com/margelo/nitro/queueplayer/ReplayGainGain.kt +34 -0
  413. package/android/src/main/java/com/margelo/nitro/queueplayer/SearchResultCache.kt +72 -0
  414. package/android/src/main/java/com/margelo/nitro/queueplayer/SessionCommandForwardingPlayer.kt +167 -0
  415. package/android/src/main/java/com/margelo/nitro/queueplayer/SignalsmithStretchAudioProcessor.kt +225 -0
  416. package/android/src/main/java/com/margelo/nitro/queueplayer/SignalsmithStretchNative.kt +93 -0
  417. package/android/src/main/java/com/margelo/nitro/queueplayer/SleepTimerCore.kt +125 -0
  418. package/android/src/main/java/com/margelo/nitro/queueplayer/TrackPlayer.kt +4242 -0
  419. package/android/src/main/java/com/margelo/nitro/queueplayer/TransportStateTranslator.kt +70 -0
  420. package/android/src/main/java/com/margelo/nitro/queueplayer/UrlSchemes.kt +9 -0
  421. package/android/src/main/java/com/margelo/nitro/queueplayer/VisualizationGate.kt +35 -0
  422. package/android/src/main/java/com/margelo/nitro/queueplayer/Visualizer.kt +240 -0
  423. package/android/src/main/java/com/margelo/nitro/queueplayer/VisualizerTeeBuilder.kt +63 -0
  424. package/android/src/main/java/com/margelo/nitro/queueplayer/VoiceSearchExtrasParser.kt +103 -0
  425. package/android/src/main/java/com/margelo/nitro/queueplayer/cast/AudioRouteState.kt +202 -0
  426. package/android/src/main/java/com/margelo/nitro/queueplayer/cast/AuthRequiredException.kt +14 -0
  427. package/android/src/main/java/com/margelo/nitro/queueplayer/cast/CastBackend.kt +41 -0
  428. package/android/src/main/java/com/margelo/nitro/queueplayer/cast/CastBackends.kt +56 -0
  429. package/android/src/main/java/com/margelo/nitro/queueplayer/cast/CastEventBridge.kt +122 -0
  430. package/android/src/main/java/com/margelo/nitro/queueplayer/cast/CastMediaItem.kt +20 -0
  431. package/android/src/main/java/com/margelo/nitro/queueplayer/cast/CastSession.kt +193 -0
  432. package/android/src/main/java/com/margelo/nitro/queueplayer/cast/CastSinkRouter.kt +95 -0
  433. package/android/src/main/java/com/margelo/nitro/queueplayer/cast/CastTransportRouter.kt +151 -0
  434. package/android/src/main/java/com/margelo/nitro/queueplayer/cast/DiscoveryState.kt +53 -0
  435. package/android/src/main/java/com/margelo/nitro/queueplayer/cast/MetadataAwareSession.kt +17 -0
  436. package/android/src/main/java/com/margelo/nitro/queueplayer/cast/PlaybackStateRouter.kt +65 -0
  437. package/android/src/main/java/com/margelo/nitro/queueplayer/cast/Receiver.kt +35 -0
  438. package/android/src/main/java/com/margelo/nitro/queueplayer/cast/airplay/AirPlay2JNI.kt +129 -0
  439. package/android/src/main/java/com/margelo/nitro/queueplayer/cast/airplay/AirPlay2MetadataSync.kt +189 -0
  440. package/android/src/main/java/com/margelo/nitro/queueplayer/cast/airplay/AirPlay2Session.kt +123 -0
  441. package/android/src/main/java/com/margelo/nitro/queueplayer/cast/airplay/AirPlay2Sink.kt +205 -0
  442. package/android/src/main/java/com/margelo/nitro/queueplayer/cast/airplay/AirPlayBackend.kt +585 -0
  443. package/android/src/main/java/com/margelo/nitro/queueplayer/cast/airplay/AirPlayBackendInitializer.kt +43 -0
  444. package/android/src/main/java/com/margelo/nitro/queueplayer/cast/airplay/AirPlayDiscovery.kt +511 -0
  445. package/android/src/main/java/com/margelo/nitro/queueplayer/cast/airplay/AirPlayDiscoveryLifecycleObserver.kt +57 -0
  446. package/android/src/main/java/com/margelo/nitro/queueplayer/cast/airplay/AirPlayMetadataSync.kt +199 -0
  447. package/android/src/main/java/com/margelo/nitro/queueplayer/cast/airplay/AirPlayReceiverMapper.kt +42 -0
  448. package/android/src/main/java/com/margelo/nitro/queueplayer/cast/airplay/AirPlayRenderersFactory.kt +43 -0
  449. package/android/src/main/java/com/margelo/nitro/queueplayer/cast/airplay/AirPlaySession.kt +101 -0
  450. package/android/src/main/java/com/margelo/nitro/queueplayer/cast/airplay/AirPlaySink.kt +265 -0
  451. package/android/src/main/java/com/margelo/nitro/queueplayer/cast/airplay/AirPlayTxtParser.kt +203 -0
  452. package/android/src/main/java/com/margelo/nitro/queueplayer/cast/airplay/AirplayJNI.kt +106 -0
  453. package/android/src/main/java/com/margelo/nitro/queueplayer/cast/airplay/MulticastLockHolder.kt +75 -0
  454. package/android/src/main/java/com/margelo/nitro/queueplayer/cast/chromecast/CastMediaItemConverter.kt +67 -0
  455. package/android/src/main/java/com/margelo/nitro/queueplayer/cast/chromecast/CastVolumeForwardingPlayer.kt +156 -0
  456. package/android/src/main/java/com/margelo/nitro/queueplayer/cast/chromecast/ChromecastBackend.kt +171 -0
  457. package/android/src/main/java/com/margelo/nitro/queueplayer/cast/chromecast/ChromecastOptionsProvider.kt +51 -0
  458. package/android/src/main/java/com/margelo/nitro/queueplayer/cast/chromecast/ChromecastReceiverMapper.kt +44 -0
  459. package/android/src/main/java/com/margelo/nitro/queueplayer/cast/chromecast/ChromecastSession.kt +544 -0
  460. package/android/src/main/java/com/margelo/nitro/queueplayer/cast/chromecast/MediaInfoBuilder.kt +92 -0
  461. package/android/src/main/java/com/margelo/nitro/queueplayer/cast/chromecast/RemoteMediaCallbacks.kt +113 -0
  462. package/android/src/main/java/com/margelo/nitro/queueplayer/cast/http/LocalMediaServer.kt +160 -0
  463. package/android/src/main/java/com/margelo/nitro/queueplayer/cast/http/LocalMediaServerLifecycle.kt +15 -0
  464. package/android/src/main/java/com/margelo/nitro/queueplayer/cast/http/MediaServerHandle.kt +44 -0
  465. package/android/src/main/java/com/margelo/nitro/queueplayer/cast/http/MediaTokenRegistry.kt +37 -0
  466. package/android/src/main/java/com/margelo/nitro/queueplayer/cast/http/MimeTypes.kt +27 -0
  467. package/android/src/main/java/com/margelo/nitro/queueplayer/cast/net/LocalAddressMonitor.kt +86 -0
  468. package/android/src/main/res/raw/rnqp_placeholder.jpg +0 -0
  469. package/android/src/main/res/values/cast_strings.xml +15 -0
  470. package/android/src/main/res/values/strings.xml +24 -0
  471. package/android/src/main/res/xml/automotive_app_desc.xml +15 -0
  472. package/android/src/test/java/androidx/media3/session/MediaSessionControllerRequestTestSeam.kt +27 -0
  473. package/android/src/test/java/com/margelo/nitro/queueplayer/ArtworkContentProviderTest.kt +124 -0
  474. package/android/src/test/java/com/margelo/nitro/queueplayer/AudioFocusErrorMappingTest.kt +122 -0
  475. package/android/src/test/java/com/margelo/nitro/queueplayer/AudioPipelineRenderersFactoryTest.kt +57 -0
  476. package/android/src/test/java/com/margelo/nitro/queueplayer/AvrcpMetadataTest.kt +264 -0
  477. package/android/src/test/java/com/margelo/nitro/queueplayer/BrowseCallbackRegistryTest.kt +104 -0
  478. package/android/src/test/java/com/margelo/nitro/queueplayer/BrowseDataProviderTest.kt +276 -0
  479. package/android/src/test/java/com/margelo/nitro/queueplayer/BufferStateTranslatorTest.kt +58 -0
  480. package/android/src/test/java/com/margelo/nitro/queueplayer/CacheMimeTypesTest.kt +116 -0
  481. package/android/src/test/java/com/margelo/nitro/queueplayer/CrossfadeEngineLifecycleTest.kt +214 -0
  482. package/android/src/test/java/com/margelo/nitro/queueplayer/CrossfadeEngineReplayGainTest.kt +180 -0
  483. package/android/src/test/java/com/margelo/nitro/queueplayer/CustomPresetStoreTest.kt +128 -0
  484. package/android/src/test/java/com/margelo/nitro/queueplayer/EqualizerEngineTest.kt +223 -0
  485. package/android/src/test/java/com/margelo/nitro/queueplayer/EqualizerKtTest.kt +274 -0
  486. package/android/src/test/java/com/margelo/nitro/queueplayer/EqualizerLegacyEngineTest.kt +214 -0
  487. package/android/src/test/java/com/margelo/nitro/queueplayer/EqualizerPresetsTest.kt +89 -0
  488. package/android/src/test/java/com/margelo/nitro/queueplayer/FFTProcessorTeeTest.kt +185 -0
  489. package/android/src/test/java/com/margelo/nitro/queueplayer/FifoCacheEvictorTest.kt +112 -0
  490. package/android/src/test/java/com/margelo/nitro/queueplayer/ForwardingPlayerTestAccess.kt +21 -0
  491. package/android/src/test/java/com/margelo/nitro/queueplayer/GaplessEngineLifecycleTest.kt +65 -0
  492. package/android/src/test/java/com/margelo/nitro/queueplayer/GaplessEngineReplayGainTest.kt +154 -0
  493. package/android/src/test/java/com/margelo/nitro/queueplayer/HeadlessJsMediaServiceTest.kt +106 -0
  494. package/android/src/test/java/com/margelo/nitro/queueplayer/LookaheadCacheTest.kt +183 -0
  495. package/android/src/test/java/com/margelo/nitro/queueplayer/LookaheadCacheWriterTest.kt +649 -0
  496. package/android/src/test/java/com/margelo/nitro/queueplayer/MediaButtonDispatchTest.kt +192 -0
  497. package/android/src/test/java/com/margelo/nitro/queueplayer/MediaItemBuilderTest.kt +389 -0
  498. package/android/src/test/java/com/margelo/nitro/queueplayer/MediaItemMapperTest.kt +145 -0
  499. package/android/src/test/java/com/margelo/nitro/queueplayer/MilestoneTrackerTest.kt +81 -0
  500. package/android/src/test/java/com/margelo/nitro/queueplayer/MultiplexingAudioBufferSinkTest.kt +112 -0
  501. package/android/src/test/java/com/margelo/nitro/queueplayer/NotificationProviderTest.kt +86 -0
  502. package/android/src/test/java/com/margelo/nitro/queueplayer/NowPlayingFormatExtractorTest.kt +106 -0
  503. package/android/src/test/java/com/margelo/nitro/queueplayer/PendingBrowseRequestsTest.kt +82 -0
  504. package/android/src/test/java/com/margelo/nitro/queueplayer/PendingIntentBufferTest.kt +192 -0
  505. package/android/src/test/java/com/margelo/nitro/queueplayer/PitchAwareAudioProcessorChainTest.kt +147 -0
  506. package/android/src/test/java/com/margelo/nitro/queueplayer/PitchCorrectionTest.kt +55 -0
  507. package/android/src/test/java/com/margelo/nitro/queueplayer/PlaceholderFallbackBitmapLoaderTest.kt +187 -0
  508. package/android/src/test/java/com/margelo/nitro/queueplayer/PlaybackEngineInterfaceTest.kt +134 -0
  509. package/android/src/test/java/com/margelo/nitro/queueplayer/PlaybackModeStateMachineTest.kt +157 -0
  510. package/android/src/test/java/com/margelo/nitro/queueplayer/PlaybackServiceArtworkLoaderTest.kt +95 -0
  511. package/android/src/test/java/com/margelo/nitro/queueplayer/PlaybackServiceCallbackBrowseTest.kt +480 -0
  512. package/android/src/test/java/com/margelo/nitro/queueplayer/PlaybackServiceCallbackSearchTest.kt +171 -0
  513. package/android/src/test/java/com/margelo/nitro/queueplayer/PlaybackServiceCallbackTest.kt +773 -0
  514. package/android/src/test/java/com/margelo/nitro/queueplayer/PlaybackServiceCastBindTest.kt +100 -0
  515. package/android/src/test/java/com/margelo/nitro/queueplayer/PlaybackServiceLifecycleTest.kt +315 -0
  516. package/android/src/test/java/com/margelo/nitro/queueplayer/PlaybackServiceSessionActivityTest.kt +121 -0
  517. package/android/src/test/java/com/margelo/nitro/queueplayer/PlayerCommandsForTest.kt +246 -0
  518. package/android/src/test/java/com/margelo/nitro/queueplayer/ProgressEmissionGateTest.kt +113 -0
  519. package/android/src/test/java/com/margelo/nitro/queueplayer/QueueMutationArithmeticTest.kt +252 -0
  520. package/android/src/test/java/com/margelo/nitro/queueplayer/QueueSkipArithmeticTest.kt +343 -0
  521. package/android/src/test/java/com/margelo/nitro/queueplayer/RadixTwoFFTTest.kt +109 -0
  522. package/android/src/test/java/com/margelo/nitro/queueplayer/RemoteCommandDeduperTest.kt +106 -0
  523. package/android/src/test/java/com/margelo/nitro/queueplayer/ReplayGainAudioProcessorTest.kt +141 -0
  524. package/android/src/test/java/com/margelo/nitro/queueplayer/ReplayGainConfigTest.kt +103 -0
  525. package/android/src/test/java/com/margelo/nitro/queueplayer/ReplayGainExtractorTest.kt +469 -0
  526. package/android/src/test/java/com/margelo/nitro/queueplayer/ReplayGainGainTest.kt +129 -0
  527. package/android/src/test/java/com/margelo/nitro/queueplayer/RobolectricServiceBindHelper.kt +83 -0
  528. package/android/src/test/java/com/margelo/nitro/queueplayer/SearchResultCacheTest.kt +128 -0
  529. package/android/src/test/java/com/margelo/nitro/queueplayer/ServiceReadyReasonTest.kt +42 -0
  530. package/android/src/test/java/com/margelo/nitro/queueplayer/SessionCommandForwardingPlayerTest.kt +521 -0
  531. package/android/src/test/java/com/margelo/nitro/queueplayer/SleepTimerCoreTest.kt +125 -0
  532. package/android/src/test/java/com/margelo/nitro/queueplayer/SmokeTest.kt +27 -0
  533. package/android/src/test/java/com/margelo/nitro/queueplayer/TrackPlayerAirPlayMetadataWiringTest.kt +305 -0
  534. package/android/src/test/java/com/margelo/nitro/queueplayer/TrackPlayerAudioFocusTest.kt +179 -0
  535. package/android/src/test/java/com/margelo/nitro/queueplayer/TrackPlayerEventsTest.kt +497 -0
  536. package/android/src/test/java/com/margelo/nitro/queueplayer/TrackPlayerLifecycleTest.kt +209 -0
  537. package/android/src/test/java/com/margelo/nitro/queueplayer/TrackPlayerLookaheadConfigTest.kt +417 -0
  538. package/android/src/test/java/com/margelo/nitro/queueplayer/TrackPlayerMutationTest.kt +473 -0
  539. package/android/src/test/java/com/margelo/nitro/queueplayer/TrackPlayerPitchCorrectionTest.kt +61 -0
  540. package/android/src/test/java/com/margelo/nitro/queueplayer/TrackPlayerPlaybackModeTest.kt +28 -0
  541. package/android/src/test/java/com/margelo/nitro/queueplayer/TrackPlayerProgressThrottleTest.kt +89 -0
  542. package/android/src/test/java/com/margelo/nitro/queueplayer/TrackPlayerQueueTest.kt +290 -0
  543. package/android/src/test/java/com/margelo/nitro/queueplayer/TrackPlayerReadersTest.kt +151 -0
  544. package/android/src/test/java/com/margelo/nitro/queueplayer/TrackPlayerReplayGainTest.kt +69 -0
  545. package/android/src/test/java/com/margelo/nitro/queueplayer/TrackPlayerSkipCapabilityTest.kt +324 -0
  546. package/android/src/test/java/com/margelo/nitro/queueplayer/TrackPlayerSkipTest.kt +287 -0
  547. package/android/src/test/java/com/margelo/nitro/queueplayer/TrackPlayerSourceClassifierTest.kt +82 -0
  548. package/android/src/test/java/com/margelo/nitro/queueplayer/TrackPlayerTransportTest.kt +222 -0
  549. package/android/src/test/java/com/margelo/nitro/queueplayer/TransportStateTranslatorTest.kt +287 -0
  550. package/android/src/test/java/com/margelo/nitro/queueplayer/VisualizationGateTest.kt +96 -0
  551. package/android/src/test/java/com/margelo/nitro/queueplayer/VisualizerKtTest.kt +202 -0
  552. package/android/src/test/java/com/margelo/nitro/queueplayer/VoiceSearchExtrasParserTest.kt +211 -0
  553. package/android/src/test/java/com/margelo/nitro/queueplayer/cast/CastSinkRouterTest.kt +120 -0
  554. package/android/src/test/java/com/margelo/nitro/queueplayer/cast/FakeRemotePlayer.kt +62 -0
  555. package/android/src/test/java/com/margelo/nitro/queueplayer/cast/PlaybackStateRouterTest.kt +43 -0
  556. package/android/src/test/java/com/margelo/nitro/queueplayer/cast/airplay/AirPlayDiscoveryFilterTest.kt +86 -0
  557. package/android/src/test/java/com/margelo/nitro/queueplayer/cast/airplay/AirPlayTxtParserClassificationTest.kt +34 -0
  558. package/android/src/test/java/com/margelo/nitro/queueplayer/cast/chromecast/CastMediaItemConverterTest.kt +78 -0
  559. package/android/src/test/java/com/margelo/nitro/queueplayer/cast/chromecast/CastVolumeForwardingPlayerTest.kt +176 -0
  560. package/app.plugin.js +466 -0
  561. package/ios/AVPlayerItemQueueItemId.swift +61 -0
  562. package/ios/AVQueueBuilder.swift +200 -0
  563. package/ios/Array+SafeSubscript.swift +6 -0
  564. package/ios/ArtworkLoader.swift +136 -0
  565. package/ios/ArtworkResolver.swift +87 -0
  566. package/ios/AudioCategoryMapping.swift +48 -0
  567. package/ios/AudioSession.swift +220 -0
  568. package/ios/AudioSessionError.swift +44 -0
  569. package/ios/AudioTapProvider.swift +647 -0
  570. package/ios/BiquadCoefficients.swift +80 -0
  571. package/ios/CarPlayBridge.swift +178 -0
  572. package/ios/CarPlayBrowseBuilder.swift +368 -0
  573. package/ios/CarPlayBrowseDataProvider.swift +162 -0
  574. package/ios/CarPlayCoordinator.swift +42 -0
  575. package/ios/CarPlaySceneDelegate.swift +199 -0
  576. package/ios/Cast/AirPlayRouteState.swift +281 -0
  577. package/ios/Cast/Chromecast/ChromecastDiscoveryAdapter.swift +27 -0
  578. package/ios/Cast/Chromecast/ChromecastReceiverMapper.swift +48 -0
  579. package/ios/Cast/Chromecast/ChromecastSession.swift +740 -0
  580. package/ios/Cast/Chromecast/ChromecastSessionAdapter.swift +114 -0
  581. package/ios/Cast/Chromecast/ChromecastSupport.swift +63 -0
  582. package/ios/Cast/Chromecast/MediaInfoBuilder.swift +104 -0
  583. package/ios/Cast/Chromecast/RemoteMediaObserver.swift +147 -0
  584. package/ios/Cast/Core/CastEventBridge.swift +210 -0
  585. package/ios/Cast/Core/CastMediaItem.swift +41 -0
  586. package/ios/Cast/Core/CastNowPlayingController.swift +310 -0
  587. package/ios/Cast/Core/CastReceiverState.swift +22 -0
  588. package/ios/Cast/Core/CastSession.swift +147 -0
  589. package/ios/Cast/Core/CastTransportRouter.swift +162 -0
  590. package/ios/Cast/Core/ChromecastBackend.swift +259 -0
  591. package/ios/Cast/Core/LocalAddressMonitor.swift +110 -0
  592. package/ios/Cast/Core/LocalMediaServer.swift +270 -0
  593. package/ios/Cast/Core/LocalNetworkPermissionProbe.swift +265 -0
  594. package/ios/Cast/Core/MediaHTTPConnection.swift +349 -0
  595. package/ios/Cast/Core/MediaServerHandle.swift +49 -0
  596. package/ios/Cast/Core/MediaTokenRegistry.swift +51 -0
  597. package/ios/Cast/Core/MimeTypes.swift +26 -0
  598. package/ios/Cast/Core/PlaybackStateRouter.swift +123 -0
  599. package/ios/CastManager.swift +493 -0
  600. package/ios/CrossfadeEngine.swift +1343 -0
  601. package/ios/CustomPresetStore.swift +78 -0
  602. package/ios/EQProcessor.swift +321 -0
  603. package/ios/EQTap.swift +241 -0
  604. package/ios/Equalizer.swift +321 -0
  605. package/ios/EqualizerPresets.swift +48 -0
  606. package/ios/FFTProcessor.swift +237 -0
  607. package/ios/GaplessEngine.swift +385 -0
  608. package/ios/InputGuards.swift +63 -0
  609. package/ios/InterruptionEventMapping.swift +51 -0
  610. package/ios/ListenerRegistry.swift +73 -0
  611. package/ios/LookaheadCache.swift +833 -0
  612. package/ios/LookaheadCacheEviction.swift +83 -0
  613. package/ios/LookaheadCachePrefetcher.swift +503 -0
  614. package/ios/MetadataReader.swift +555 -0
  615. package/ios/MilestoneTracker.swift +63 -0
  616. package/ios/NowPlayingFormatExtractor.swift +362 -0
  617. package/ios/NowPlayingInfo.swift +190 -0
  618. package/ios/OutputRouteMonitor.swift +125 -0
  619. package/ios/PendingBrowseRequests.swift +62 -0
  620. package/ios/PitchAlgorithm.swift +24 -0
  621. package/ios/PlaceholderArtwork.swift +46 -0
  622. package/ios/PlaybackEngine.swift +319 -0
  623. package/ios/PlaybackErrorMapping.swift +195 -0
  624. package/ios/PlaybackModeStateMachine.swift +159 -0
  625. package/ios/PlayerStateDerivation.swift +45 -0
  626. package/ios/ProgressEmissionGate.swift +54 -0
  627. package/ios/QueueMutationArithmetic.swift +129 -0
  628. package/ios/QueueSkipArithmetic.swift +109 -0
  629. package/ios/QueueState.swift +49 -0
  630. package/ios/RemoteCommands.swift +229 -0
  631. package/ios/ReplayGainData.swift +58 -0
  632. package/ios/ReplayGainExtractor.swift +82 -0
  633. package/ios/ReplayGainProcessor.swift +46 -0
  634. package/ios/Resources/RNQP-placeholder.jpg +0 -0
  635. package/ios/Resources/silence.m4a +0 -0
  636. package/ios/Siri/PendingIntentBuffer.swift +100 -0
  637. package/ios/Siri/PlayMediaIntentHandler.swift +283 -0
  638. package/ios/Siri/QueuePlayerMediaIntents.swift +45 -0
  639. package/ios/Siri/VoiceDonation.swift +50 -0
  640. package/ios/SleepTimerCore.swift +128 -0
  641. package/ios/StreamingBitrateProbe.swift +318 -0
  642. package/ios/Tests/AVQueueBuilderTests.swift +430 -0
  643. package/ios/Tests/ArtworkResolverTests.swift +540 -0
  644. package/ios/Tests/AudioSessionTests.swift +222 -0
  645. package/ios/Tests/AudioTapProviderReplayGainTests.swift +136 -0
  646. package/ios/Tests/AudioTapProviderVisualizationFlagTests.swift +104 -0
  647. package/ios/Tests/BiquadCoefficientsTests.swift +84 -0
  648. package/ios/Tests/CarPlayBridgeTests.swift +91 -0
  649. package/ios/Tests/CarPlayBrowseBuilderTests.swift +221 -0
  650. package/ios/Tests/CarPlayBrowseDataProviderTests.swift +218 -0
  651. package/ios/Tests/CastNowPlayingControllerTests.swift +204 -0
  652. package/ios/Tests/CrossfadeEngineStubTests.swift +43 -0
  653. package/ios/Tests/EQProcessorTests.swift +302 -0
  654. package/ios/Tests/EQTapTests.swift +49 -0
  655. package/ios/Tests/EqualizerAudioMixProviderTests.swift +110 -0
  656. package/ios/Tests/EqualizerHybridTests.swift +303 -0
  657. package/ios/Tests/EqualizerPresetsTests.swift +69 -0
  658. package/ios/Tests/FFTProcessorTests.swift +303 -0
  659. package/ios/Tests/Fixtures/silence-aac-128.m4a +0 -0
  660. package/ios/Tests/Fixtures/silence-cbr-128.mp3 +0 -0
  661. package/ios/Tests/Fixtures/silence-vbr.mp3 +0 -0
  662. package/ios/Tests/GaplessEngineLifecycleTests.swift +160 -0
  663. package/ios/Tests/InputGuardsTests.swift +75 -0
  664. package/ios/Tests/InterruptionEventMappingTests.swift +91 -0
  665. package/ios/Tests/LookaheadCacheEvictionTests.swift +217 -0
  666. package/ios/Tests/LookaheadCachePrefetcherTests.swift +630 -0
  667. package/ios/Tests/LookaheadCacheRuntimeConfigTests.swift +247 -0
  668. package/ios/Tests/LookaheadCacheTests.swift +717 -0
  669. package/ios/Tests/MediaHTTPConnectionTests.swift +163 -0
  670. package/ios/Tests/MetadataReaderTests.swift +605 -0
  671. package/ios/Tests/MilestoneTrackerTests.swift +76 -0
  672. package/ios/Tests/NowPlayingFormatExtractorTests.swift +158 -0
  673. package/ios/Tests/NowPlayingInfoTests.swift +292 -0
  674. package/ios/Tests/PendingBrowseRequestsTests.swift +69 -0
  675. package/ios/Tests/PendingIntentBufferTests.swift +164 -0
  676. package/ios/Tests/PlaybackEngineProtocolTests.swift +92 -0
  677. package/ios/Tests/PlaybackErrorMappingTests.swift +179 -0
  678. package/ios/Tests/PlaybackModeStateMachineTests.swift +40 -0
  679. package/ios/Tests/PlaybackStateRouterTests.swift +178 -0
  680. package/ios/Tests/PlayerStateDerivationTests.swift +69 -0
  681. package/ios/Tests/ProgressEmissionGateTests.swift +113 -0
  682. package/ios/Tests/QueueMutationArithmeticTests.swift +245 -0
  683. package/ios/Tests/RemoteCommandsTests.swift +147 -0
  684. package/ios/Tests/ReplayGainExtractorTests.swift +197 -0
  685. package/ios/Tests/ReplayGainProcessorTests.swift +90 -0
  686. package/ios/Tests/SkipCapabilityTests.swift +98 -0
  687. package/ios/Tests/SkipIndexTests.swift +259 -0
  688. package/ios/Tests/SleepTimerCoreTests.swift +98 -0
  689. package/ios/Tests/StreamingBitrateProbeTests.swift +29 -0
  690. package/ios/Tests/TrackSourceClassifierTests.swift +50 -0
  691. package/ios/Tests/VoiceDonationTests.swift +26 -0
  692. package/ios/TrackPlayer.swift +4766 -0
  693. package/ios/Visualizer.swift +274 -0
  694. package/ios/WindowApplicationSceneDelegate.swift +59 -0
  695. package/ios/tests-harness/Podfile +56 -0
  696. package/ios/tests-harness/TestHost/App.swift +12 -0
  697. package/ios/tests-harness/TestHost/Info.plist +37 -0
  698. package/ios/tests-harness/TestHost.xcodeproj/project.pbxproj +472 -0
  699. package/ios/tests-harness/TestHost.xcodeproj/xcshareddata/xcschemes/TestHost.xcscheme +68 -0
  700. package/ios/tests-harness/package.json +10 -0
  701. package/ios/tests-harness/scripts/seed-xcodeproj.rb +118 -0
  702. package/lib/module/CastManager.nitro.js +4 -0
  703. package/lib/module/CastManager.nitro.js.map +1 -0
  704. package/lib/module/Equalizer.nitro.js +4 -0
  705. package/lib/module/Equalizer.nitro.js.map +1 -0
  706. package/lib/module/TrackPlayer.nitro.js +4 -0
  707. package/lib/module/TrackPlayer.nitro.js.map +1 -0
  708. package/lib/module/Visualizer.nitro.js +4 -0
  709. package/lib/module/Visualizer.nitro.js.map +1 -0
  710. package/lib/module/cast/index.js +156 -0
  711. package/lib/module/cast/index.js.map +1 -0
  712. package/lib/module/clients.js +43 -0
  713. package/lib/module/clients.js.map +1 -0
  714. package/lib/module/equalizer.js +85 -0
  715. package/lib/module/equalizer.js.map +1 -0
  716. package/lib/module/hooks/index.js +16 -0
  717. package/lib/module/hooks/index.js.map +1 -0
  718. package/lib/module/hooks/useActiveTrack.js +50 -0
  719. package/lib/module/hooks/useActiveTrack.js.map +1 -0
  720. package/lib/module/hooks/useAudioRoute.js +60 -0
  721. package/lib/module/hooks/useAudioRoute.js.map +1 -0
  722. package/lib/module/hooks/useBufferState.js +34 -0
  723. package/lib/module/hooks/useBufferState.js.map +1 -0
  724. package/lib/module/hooks/useCanSkip.js +67 -0
  725. package/lib/module/hooks/useCanSkip.js.map +1 -0
  726. package/lib/module/hooks/useCast.js +107 -0
  727. package/lib/module/hooks/useCast.js.map +1 -0
  728. package/lib/module/hooks/useEqualizer.js +91 -0
  729. package/lib/module/hooks/useEqualizer.js.map +1 -0
  730. package/lib/module/hooks/useFullyBuffered.js +33 -0
  731. package/lib/module/hooks/useFullyBuffered.js.map +1 -0
  732. package/lib/module/hooks/useLookaheadCache.js +49 -0
  733. package/lib/module/hooks/useLookaheadCache.js.map +1 -0
  734. package/lib/module/hooks/useNowPlayingFormat.js +42 -0
  735. package/lib/module/hooks/useNowPlayingFormat.js.map +1 -0
  736. package/lib/module/hooks/usePlaybackState.js +36 -0
  737. package/lib/module/hooks/usePlaybackState.js.map +1 -0
  738. package/lib/module/hooks/useProgress.js +31 -0
  739. package/lib/module/hooks/useProgress.js.map +1 -0
  740. package/lib/module/hooks/useSleepTimer.js +65 -0
  741. package/lib/module/hooks/useSleepTimer.js.map +1 -0
  742. package/lib/module/hooks/useVisualizerState.js +99 -0
  743. package/lib/module/hooks/useVisualizerState.js.map +1 -0
  744. package/lib/module/index.js +37 -0
  745. package/lib/module/index.js.map +1 -0
  746. package/lib/module/package.json +1 -0
  747. package/lib/module/playbackService.js +174 -0
  748. package/lib/module/playbackService.js.map +1 -0
  749. package/lib/module/types.js +592 -0
  750. package/lib/module/types.js.map +1 -0
  751. package/lib/typescript/CastManager.nitro.d.ts +154 -0
  752. package/lib/typescript/CastManager.nitro.d.ts.map +1 -0
  753. package/lib/typescript/Equalizer.nitro.d.ts +30 -0
  754. package/lib/typescript/Equalizer.nitro.d.ts.map +1 -0
  755. package/lib/typescript/TrackPlayer.nitro.d.ts +584 -0
  756. package/lib/typescript/TrackPlayer.nitro.d.ts.map +1 -0
  757. package/lib/typescript/Visualizer.nitro.d.ts +36 -0
  758. package/lib/typescript/Visualizer.nitro.d.ts.map +1 -0
  759. package/lib/typescript/cast/index.d.ts +65 -0
  760. package/lib/typescript/cast/index.d.ts.map +1 -0
  761. package/lib/typescript/clients.d.ts +9 -0
  762. package/lib/typescript/clients.d.ts.map +1 -0
  763. package/lib/typescript/equalizer.d.ts +45 -0
  764. package/lib/typescript/equalizer.d.ts.map +1 -0
  765. package/lib/typescript/hooks/index.d.ts +22 -0
  766. package/lib/typescript/hooks/index.d.ts.map +1 -0
  767. package/lib/typescript/hooks/useActiveTrack.d.ts +21 -0
  768. package/lib/typescript/hooks/useActiveTrack.d.ts.map +1 -0
  769. package/lib/typescript/hooks/useAudioRoute.d.ts +13 -0
  770. package/lib/typescript/hooks/useAudioRoute.d.ts.map +1 -0
  771. package/lib/typescript/hooks/useBufferState.d.ts +18 -0
  772. package/lib/typescript/hooks/useBufferState.d.ts.map +1 -0
  773. package/lib/typescript/hooks/useCanSkip.d.ts +43 -0
  774. package/lib/typescript/hooks/useCanSkip.d.ts.map +1 -0
  775. package/lib/typescript/hooks/useCast.d.ts +32 -0
  776. package/lib/typescript/hooks/useCast.d.ts.map +1 -0
  777. package/lib/typescript/hooks/useEqualizer.d.ts +20 -0
  778. package/lib/typescript/hooks/useEqualizer.d.ts.map +1 -0
  779. package/lib/typescript/hooks/useFullyBuffered.d.ts +15 -0
  780. package/lib/typescript/hooks/useFullyBuffered.d.ts.map +1 -0
  781. package/lib/typescript/hooks/useLookaheadCache.d.ts +13 -0
  782. package/lib/typescript/hooks/useLookaheadCache.d.ts.map +1 -0
  783. package/lib/typescript/hooks/useNowPlayingFormat.d.ts +18 -0
  784. package/lib/typescript/hooks/useNowPlayingFormat.d.ts.map +1 -0
  785. package/lib/typescript/hooks/usePlaybackState.d.ts +9 -0
  786. package/lib/typescript/hooks/usePlaybackState.d.ts.map +1 -0
  787. package/lib/typescript/hooks/useProgress.d.ts +15 -0
  788. package/lib/typescript/hooks/useProgress.d.ts.map +1 -0
  789. package/lib/typescript/hooks/useSleepTimer.d.ts +26 -0
  790. package/lib/typescript/hooks/useSleepTimer.d.ts.map +1 -0
  791. package/lib/typescript/hooks/useVisualizerState.d.ts +40 -0
  792. package/lib/typescript/hooks/useVisualizerState.d.ts.map +1 -0
  793. package/lib/typescript/index.d.ts +14 -0
  794. package/lib/typescript/index.d.ts.map +1 -0
  795. package/lib/typescript/package.json +1 -0
  796. package/lib/typescript/playbackService.d.ts +140 -0
  797. package/lib/typescript/playbackService.d.ts.map +1 -0
  798. package/lib/typescript/types.d.ts +1215 -0
  799. package/lib/typescript/types.d.ts.map +1 -0
  800. package/nitro.json +53 -0
  801. package/nitrogen/generated/android/c++/JAudioCategoryOptions.hpp +65 -0
  802. package/nitrogen/generated/android/c++/JAudioCodec.hpp +73 -0
  803. package/nitrogen/generated/android/c++/JAudioContainer.hpp +76 -0
  804. package/nitrogen/generated/android/c++/JAudioContentType.hpp +58 -0
  805. package/nitrogen/generated/android/c++/JAudioRoute.hpp +75 -0
  806. package/nitrogen/generated/android/c++/JAudioRouteKind.hpp +91 -0
  807. package/nitrogen/generated/android/c++/JBrowseItem.hpp +78 -0
  808. package/nitrogen/generated/android/c++/JBrowseSection.hpp +97 -0
  809. package/nitrogen/generated/android/c++/JBrowseSnapshot.hpp +87 -0
  810. package/nitrogen/generated/android/c++/JBufferState.hpp +64 -0
  811. package/nitrogen/generated/android/c++/JCacheStatus.hpp +92 -0
  812. package/nitrogen/generated/android/c++/JCastConfigureOptions.hpp +62 -0
  813. package/nitrogen/generated/android/c++/JCastConnectOptions.hpp +57 -0
  814. package/nitrogen/generated/android/c++/JCastDeviceKind.hpp +70 -0
  815. package/nitrogen/generated/android/c++/JCastDiscoveryState.hpp +57 -0
  816. package/nitrogen/generated/android/c++/JCastLocalNetworkPermission.hpp +61 -0
  817. package/nitrogen/generated/android/c++/JCastLocalNetworkPermissionEvent.hpp +58 -0
  818. package/nitrogen/generated/android/c++/JCastProtocol.hpp +67 -0
  819. package/nitrogen/generated/android/c++/JCastReceiver.hpp +89 -0
  820. package/nitrogen/generated/android/c++/JCastReceiverCapabilities.hpp +66 -0
  821. package/nitrogen/generated/android/c++/JCastRoute.hpp +85 -0
  822. package/nitrogen/generated/android/c++/JCastSessionDiedEvent.hpp +63 -0
  823. package/nitrogen/generated/android/c++/JCastSessionEndReason.hpp +76 -0
  824. package/nitrogen/generated/android/c++/JCastStreamingModel.hpp +58 -0
  825. package/nitrogen/generated/android/c++/JEqualizerBand.hpp +61 -0
  826. package/nitrogen/generated/android/c++/JEqualizerPreset.hpp +76 -0
  827. package/nitrogen/generated/android/c++/JEvictionPolicy.hpp +58 -0
  828. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__vector_BrowseItem______std__string.hpp +146 -0
  829. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__vector_TrackItem______MediaSearchRequest.hpp +161 -0
  830. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__vector_TrackItem______std__string.hpp +147 -0
  831. package/nitrogen/generated/android/c++/JFunc_void.hpp +75 -0
  832. package/nitrogen/generated/android/c++/JFunc_void_AudioRoute.hpp +80 -0
  833. package/nitrogen/generated/android/c++/JFunc_void_BufferState.hpp +77 -0
  834. package/nitrogen/generated/android/c++/JFunc_void_CacheStatus.hpp +79 -0
  835. package/nitrogen/generated/android/c++/JFunc_void_CastDiscoveryState.hpp +77 -0
  836. package/nitrogen/generated/android/c++/JFunc_void_CastLocalNetworkPermissionEvent.hpp +79 -0
  837. package/nitrogen/generated/android/c++/JFunc_void_CastRoute.hpp +86 -0
  838. package/nitrogen/generated/android/c++/JFunc_void_CastSessionDiedEvent.hpp +80 -0
  839. package/nitrogen/generated/android/c++/JFunc_void_PlaybackError.hpp +80 -0
  840. package/nitrogen/generated/android/c++/JFunc_void_PlayerProgress.hpp +77 -0
  841. package/nitrogen/generated/android/c++/JFunc_void_PlayerState_StateChangeReason.hpp +79 -0
  842. package/nitrogen/generated/android/c++/JFunc_void_ServiceReadyReason.hpp +77 -0
  843. package/nitrogen/generated/android/c++/JFunc_void_SkipCapability.hpp +77 -0
  844. package/nitrogen/generated/android/c++/JFunc_void_SleepTimerState.hpp +78 -0
  845. package/nitrogen/generated/android/c++/JFunc_void_VisualizerErrorReason.hpp +77 -0
  846. package/nitrogen/generated/android/c++/JFunc_void_VisualizerFrame.hpp +80 -0
  847. package/nitrogen/generated/android/c++/JFunc_void_bool.hpp +75 -0
  848. package/nitrogen/generated/android/c++/JFunc_void_double_double.hpp +75 -0
  849. package/nitrogen/generated/android/c++/JFunc_void_std__optional_TrackItem__double_TrackChangeReason_std__optional_double_.hpp +82 -0
  850. package/nitrogen/generated/android/c++/JFunc_void_std__optional_std__variant_nitro__NullType__NowPlayingFormat__.hpp +93 -0
  851. package/nitrogen/generated/android/c++/JFunc_void_std__vector_CastReceiver_.hpp +105 -0
  852. package/nitrogen/generated/android/c++/JFunc_void_std__vector_EqualizerBand_.hpp +96 -0
  853. package/nitrogen/generated/android/c++/JHybridCastManagerSpec.cpp +388 -0
  854. package/nitrogen/generated/android/c++/JHybridCastManagerSpec.hpp +84 -0
  855. package/nitrogen/generated/android/c++/JHybridEqualizerSpec.cpp +233 -0
  856. package/nitrogen/generated/android/c++/JHybridEqualizerSpec.hpp +74 -0
  857. package/nitrogen/generated/android/c++/JHybridTrackPlayerSpec.cpp +1052 -0
  858. package/nitrogen/generated/android/c++/JHybridTrackPlayerSpec.hpp +130 -0
  859. package/nitrogen/generated/android/c++/JHybridVisualizerSpec.cpp +84 -0
  860. package/nitrogen/generated/android/c++/JHybridVisualizerSpec.hpp +64 -0
  861. package/nitrogen/generated/android/c++/JLookaheadCacheConfig.hpp +61 -0
  862. package/nitrogen/generated/android/c++/JMediaSearchOrigin.hpp +58 -0
  863. package/nitrogen/generated/android/c++/JMediaSearchQueueLocation.hpp +61 -0
  864. package/nitrogen/generated/android/c++/JMediaSearchReference.hpp +58 -0
  865. package/nitrogen/generated/android/c++/JMediaSearchReleaseDateRange.hpp +61 -0
  866. package/nitrogen/generated/android/c++/JMediaSearchRepeatMode.hpp +61 -0
  867. package/nitrogen/generated/android/c++/JMediaSearchRequest.hpp +126 -0
  868. package/nitrogen/generated/android/c++/JMediaSearchType.hpp +67 -0
  869. package/nitrogen/generated/android/c++/JNowPlayingFormat.hpp +123 -0
  870. package/nitrogen/generated/android/c++/JNowPlayingFormatAndroidExtras.hpp +71 -0
  871. package/nitrogen/generated/android/c++/JNowPlayingFormatIosExtras.hpp +61 -0
  872. package/nitrogen/generated/android/c++/JPitchCorrectionMode.hpp +61 -0
  873. package/nitrogen/generated/android/c++/JPlaybackError.hpp +87 -0
  874. package/nitrogen/generated/android/c++/JPlaybackErrorCode.hpp +88 -0
  875. package/nitrogen/generated/android/c++/JPlaybackMode.hpp +63 -0
  876. package/nitrogen/generated/android/c++/JPlaybackModeKind.hpp +58 -0
  877. package/nitrogen/generated/android/c++/JPlayerConfig.hpp +126 -0
  878. package/nitrogen/generated/android/c++/JPlayerProgress.hpp +65 -0
  879. package/nitrogen/generated/android/c++/JPlayerState.hpp +73 -0
  880. package/nitrogen/generated/android/c++/JRemoteControlOptions.hpp +66 -0
  881. package/nitrogen/generated/android/c++/JRemoteSkipMode.hpp +58 -0
  882. package/nitrogen/generated/android/c++/JRepeatMode.hpp +61 -0
  883. package/nitrogen/generated/android/c++/JReplayGainMode.hpp +61 -0
  884. package/nitrogen/generated/android/c++/JSectionIcon.hpp +91 -0
  885. package/nitrogen/generated/android/c++/JServiceReadyReason.hpp +58 -0
  886. package/nitrogen/generated/android/c++/JShuffleResult.hpp +88 -0
  887. package/nitrogen/generated/android/c++/JSkipCapability.hpp +61 -0
  888. package/nitrogen/generated/android/c++/JSleepTimerState.hpp +69 -0
  889. package/nitrogen/generated/android/c++/JStateChangeReason.hpp +73 -0
  890. package/nitrogen/generated/android/c++/JTrackChangeReason.hpp +73 -0
  891. package/nitrogen/generated/android/c++/JTrackItem.hpp +100 -0
  892. package/nitrogen/generated/android/c++/JTrackSource.hpp +61 -0
  893. package/nitrogen/generated/android/c++/JVariant_NullType_Double.cpp +26 -0
  894. package/nitrogen/generated/android/c++/JVariant_NullType_Double.hpp +69 -0
  895. package/nitrogen/generated/android/c++/JVariant_NullType_NowPlayingFormat.cpp +26 -0
  896. package/nitrogen/generated/android/c++/JVariant_NullType_NowPlayingFormat.hpp +83 -0
  897. package/nitrogen/generated/android/c++/JVariant_NullType_String.cpp +26 -0
  898. package/nitrogen/generated/android/c++/JVariant_NullType_String.hpp +70 -0
  899. package/nitrogen/generated/android/c++/JVisualizerConfig.hpp +65 -0
  900. package/nitrogen/generated/android/c++/JVisualizerErrorReason.hpp +64 -0
  901. package/nitrogen/generated/android/c++/JVisualizerFrame.hpp +67 -0
  902. package/nitrogen/generated/android/c++/JVoiceVocabulary.hpp +98 -0
  903. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/AudioCategoryOptions.kt +61 -0
  904. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/AudioCodec.kt +28 -0
  905. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/AudioContainer.kt +29 -0
  906. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/AudioContentType.kt +23 -0
  907. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/AudioRoute.kt +71 -0
  908. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/AudioRouteKind.kt +34 -0
  909. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/BrowseItem.kt +76 -0
  910. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/BrowseSection.kt +71 -0
  911. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/BrowseSnapshot.kt +56 -0
  912. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/BufferState.kt +25 -0
  913. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/CacheStatus.kt +71 -0
  914. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/CastConfigureOptions.kt +56 -0
  915. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/CastConnectOptions.kt +51 -0
  916. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/CastDeviceKind.kt +27 -0
  917. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/CastDiscoveryState.kt +51 -0
  918. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/CastLocalNetworkPermission.kt +24 -0
  919. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/CastLocalNetworkPermissionEvent.kt +51 -0
  920. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/CastProtocol.kt +26 -0
  921. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/CastReceiver.kt +81 -0
  922. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/CastReceiverCapabilities.kt +61 -0
  923. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/CastRoute.kt +76 -0
  924. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/CastSessionDiedEvent.kt +56 -0
  925. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/CastSessionEndReason.kt +29 -0
  926. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/CastStreamingModel.kt +23 -0
  927. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/EqualizerBand.kt +56 -0
  928. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/EqualizerPreset.kt +61 -0
  929. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/EvictionPolicy.kt +23 -0
  930. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__vector_BrowseItem______std__string.kt +80 -0
  931. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__vector_TrackItem______MediaSearchRequest.kt +80 -0
  932. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__vector_TrackItem______std__string.kt +80 -0
  933. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/Func_void.kt +80 -0
  934. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/Func_void_AudioRoute.kt +80 -0
  935. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/Func_void_BufferState.kt +80 -0
  936. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/Func_void_CacheStatus.kt +80 -0
  937. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/Func_void_CastDiscoveryState.kt +80 -0
  938. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/Func_void_CastLocalNetworkPermissionEvent.kt +80 -0
  939. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/Func_void_CastRoute.kt +80 -0
  940. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/Func_void_CastSessionDiedEvent.kt +80 -0
  941. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/Func_void_PlaybackError.kt +80 -0
  942. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/Func_void_PlayerProgress.kt +80 -0
  943. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/Func_void_PlayerState_StateChangeReason.kt +80 -0
  944. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/Func_void_ServiceReadyReason.kt +80 -0
  945. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/Func_void_SkipCapability.kt +80 -0
  946. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/Func_void_SleepTimerState.kt +80 -0
  947. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/Func_void_VisualizerErrorReason.kt +80 -0
  948. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/Func_void_VisualizerFrame.kt +80 -0
  949. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/Func_void_bool.kt +80 -0
  950. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/Func_void_double_double.kt +80 -0
  951. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/Func_void_std__optional_TrackItem__double_TrackChangeReason_std__optional_double_.kt +80 -0
  952. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/Func_void_std__optional_std__variant_nitro__NullType__NowPlayingFormat__.kt +80 -0
  953. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/Func_void_std__vector_CastReceiver_.kt +80 -0
  954. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/Func_void_std__vector_EqualizerBand_.kt +80 -0
  955. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/HybridCastManagerSpec.kt +169 -0
  956. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/HybridEqualizerSpec.kt +109 -0
  957. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/HybridTrackPlayerSpec.kt +419 -0
  958. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/HybridVisualizerSpec.kt +63 -0
  959. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/LookaheadCacheConfig.kt +56 -0
  960. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/MediaSearchOrigin.kt +23 -0
  961. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/MediaSearchQueueLocation.kt +24 -0
  962. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/MediaSearchReference.kt +23 -0
  963. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/MediaSearchReleaseDateRange.kt +56 -0
  964. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/MediaSearchRepeatMode.kt +24 -0
  965. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/MediaSearchRequest.kt +121 -0
  966. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/MediaSearchType.kt +26 -0
  967. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/NowPlayingFormat.kt +116 -0
  968. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/NowPlayingFormatAndroidExtras.kt +61 -0
  969. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/NowPlayingFormatIosExtras.kt +51 -0
  970. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/PitchCorrectionMode.kt +24 -0
  971. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/PlaybackError.kt +86 -0
  972. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/PlaybackErrorCode.kt +33 -0
  973. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/PlaybackMode.kt +56 -0
  974. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/PlaybackModeKind.kt +23 -0
  975. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/PlayerConfig.kt +111 -0
  976. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/PlayerProgress.kt +61 -0
  977. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/PlayerState.kt +28 -0
  978. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/RemoteControlOptions.kt +61 -0
  979. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/RemoteSkipMode.kt +23 -0
  980. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/RepeatMode.kt +24 -0
  981. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/ReplayGainMode.kt +24 -0
  982. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/SectionIcon.kt +34 -0
  983. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/ServiceReadyReason.kt +23 -0
  984. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/ShuffleResult.kt +61 -0
  985. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/SkipCapability.kt +56 -0
  986. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/SleepTimerState.kt +66 -0
  987. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/StateChangeReason.kt +28 -0
  988. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/TrackChangeReason.kt +28 -0
  989. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/TrackItem.kt +86 -0
  990. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/TrackSource.kt +24 -0
  991. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/Variant_NullType_Double.kt +62 -0
  992. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/Variant_NullType_NowPlayingFormat.kt +62 -0
  993. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/Variant_NullType_String.kt +62 -0
  994. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/VisualizerConfig.kt +61 -0
  995. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/VisualizerErrorReason.kt +25 -0
  996. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/VisualizerFrame.kt +61 -0
  997. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/VoiceVocabulary.kt +56 -0
  998. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/queueplayerOnLoad.kt +35 -0
  999. package/nitrogen/generated/android/queueplayer+autolinking.cmake +90 -0
  1000. package/nitrogen/generated/android/queueplayer+autolinking.gradle +27 -0
  1001. package/nitrogen/generated/android/queueplayerOnLoad.cpp +152 -0
  1002. package/nitrogen/generated/android/queueplayerOnLoad.hpp +34 -0
  1003. package/nitrogen/generated/ios/QueuePlayer+autolinking.rb +62 -0
  1004. package/nitrogen/generated/ios/QueuePlayer-Swift-Cxx-Bridge.cpp +343 -0
  1005. package/nitrogen/generated/ios/QueuePlayer-Swift-Cxx-Bridge.hpp +1831 -0
  1006. package/nitrogen/generated/ios/QueuePlayer-Swift-Cxx-Umbrella.hpp +256 -0
  1007. package/nitrogen/generated/ios/QueuePlayerAutolinking.mm +57 -0
  1008. package/nitrogen/generated/ios/QueuePlayerAutolinking.swift +62 -0
  1009. package/nitrogen/generated/ios/c++/HybridCastManagerSpecSwift.cpp +11 -0
  1010. package/nitrogen/generated/ios/c++/HybridCastManagerSpecSwift.hpp +298 -0
  1011. package/nitrogen/generated/ios/c++/HybridEqualizerSpecSwift.cpp +11 -0
  1012. package/nitrogen/generated/ios/c++/HybridEqualizerSpecSwift.hpp +178 -0
  1013. package/nitrogen/generated/ios/c++/HybridTrackPlayerSpecSwift.cpp +11 -0
  1014. package/nitrogen/generated/ios/c++/HybridTrackPlayerSpecSwift.hpp +749 -0
  1015. package/nitrogen/generated/ios/c++/HybridVisualizerSpecSwift.cpp +11 -0
  1016. package/nitrogen/generated/ios/c++/HybridVisualizerSpecSwift.hpp +103 -0
  1017. package/nitrogen/generated/ios/swift/AudioCategoryOptions.swift +78 -0
  1018. package/nitrogen/generated/ios/swift/AudioCodec.swift +60 -0
  1019. package/nitrogen/generated/ios/swift/AudioContainer.swift +64 -0
  1020. package/nitrogen/generated/ios/swift/AudioContentType.swift +40 -0
  1021. package/nitrogen/generated/ios/swift/AudioRoute.swift +49 -0
  1022. package/nitrogen/generated/ios/swift/AudioRouteKind.swift +84 -0
  1023. package/nitrogen/generated/ios/swift/BrowseItem.swift +93 -0
  1024. package/nitrogen/generated/ios/swift/BrowseSection.swift +74 -0
  1025. package/nitrogen/generated/ios/swift/BrowseSnapshot.swift +40 -0
  1026. package/nitrogen/generated/ios/swift/BufferState.swift +48 -0
  1027. package/nitrogen/generated/ios/swift/CacheStatus.swift +55 -0
  1028. package/nitrogen/generated/ios/swift/CastConfigureOptions.swift +47 -0
  1029. package/nitrogen/generated/ios/swift/CastConnectOptions.swift +29 -0
  1030. package/nitrogen/generated/ios/swift/CastDeviceKind.swift +56 -0
  1031. package/nitrogen/generated/ios/swift/CastDiscoveryState.swift +29 -0
  1032. package/nitrogen/generated/ios/swift/CastLocalNetworkPermission.swift +44 -0
  1033. package/nitrogen/generated/ios/swift/CastLocalNetworkPermissionEvent.swift +29 -0
  1034. package/nitrogen/generated/ios/swift/CastProtocol.swift +52 -0
  1035. package/nitrogen/generated/ios/swift/CastReceiver.swift +59 -0
  1036. package/nitrogen/generated/ios/swift/CastReceiverCapabilities.swift +39 -0
  1037. package/nitrogen/generated/ios/swift/CastRoute.swift +54 -0
  1038. package/nitrogen/generated/ios/swift/CastSessionDiedEvent.swift +34 -0
  1039. package/nitrogen/generated/ios/swift/CastSessionEndReason.swift +64 -0
  1040. package/nitrogen/generated/ios/swift/CastStreamingModel.swift +40 -0
  1041. package/nitrogen/generated/ios/swift/EqualizerBand.swift +34 -0
  1042. package/nitrogen/generated/ios/swift/EqualizerPreset.swift +45 -0
  1043. package/nitrogen/generated/ios/swift/EvictionPolicy.swift +40 -0
  1044. package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__vector_BrowseItem______std__string.swift +67 -0
  1045. package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__vector_TrackItem______MediaSearchRequest.swift +67 -0
  1046. package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__vector_TrackItem______std__string.swift +67 -0
  1047. package/nitrogen/generated/ios/swift/Func_void.swift +46 -0
  1048. package/nitrogen/generated/ios/swift/Func_void_AudioRoute.swift +46 -0
  1049. package/nitrogen/generated/ios/swift/Func_void_BufferState.swift +46 -0
  1050. package/nitrogen/generated/ios/swift/Func_void_CacheStatus.swift +46 -0
  1051. package/nitrogen/generated/ios/swift/Func_void_CastDiscoveryState.swift +46 -0
  1052. package/nitrogen/generated/ios/swift/Func_void_CastLocalNetworkPermission.swift +46 -0
  1053. package/nitrogen/generated/ios/swift/Func_void_CastLocalNetworkPermissionEvent.swift +46 -0
  1054. package/nitrogen/generated/ios/swift/Func_void_CastRoute.swift +46 -0
  1055. package/nitrogen/generated/ios/swift/Func_void_CastSessionDiedEvent.swift +46 -0
  1056. package/nitrogen/generated/ios/swift/Func_void_PlaybackError.swift +46 -0
  1057. package/nitrogen/generated/ios/swift/Func_void_PlayerProgress.swift +46 -0
  1058. package/nitrogen/generated/ios/swift/Func_void_PlayerState_StateChangeReason.swift +46 -0
  1059. package/nitrogen/generated/ios/swift/Func_void_ServiceReadyReason.swift +46 -0
  1060. package/nitrogen/generated/ios/swift/Func_void_ShuffleResult.swift +46 -0
  1061. package/nitrogen/generated/ios/swift/Func_void_SkipCapability.swift +46 -0
  1062. package/nitrogen/generated/ios/swift/Func_void_SleepTimerState.swift +46 -0
  1063. package/nitrogen/generated/ios/swift/Func_void_VisualizerErrorReason.swift +46 -0
  1064. package/nitrogen/generated/ios/swift/Func_void_VisualizerFrame.swift +46 -0
  1065. package/nitrogen/generated/ios/swift/Func_void_bool.swift +46 -0
  1066. package/nitrogen/generated/ios/swift/Func_void_double_double.swift +46 -0
  1067. package/nitrogen/generated/ios/swift/Func_void_std__exception_ptr.swift +46 -0
  1068. package/nitrogen/generated/ios/swift/Func_void_std__optional_TrackItem__double_TrackChangeReason_std__optional_double_.swift +53 -0
  1069. package/nitrogen/generated/ios/swift/Func_void_std__optional_std__variant_nitro__NullType__NowPlayingFormat__.swift +65 -0
  1070. package/nitrogen/generated/ios/swift/Func_void_std__shared_ptr_Promise_std__vector_BrowseItem___.swift +66 -0
  1071. package/nitrogen/generated/ios/swift/Func_void_std__shared_ptr_Promise_std__vector_TrackItem___.swift +66 -0
  1072. package/nitrogen/generated/ios/swift/Func_void_std__vector_BrowseItem_.swift +46 -0
  1073. package/nitrogen/generated/ios/swift/Func_void_std__vector_CastReceiver_.swift +46 -0
  1074. package/nitrogen/generated/ios/swift/Func_void_std__vector_EqualizerBand_.swift +46 -0
  1075. package/nitrogen/generated/ios/swift/Func_void_std__vector_TrackItem_.swift +46 -0
  1076. package/nitrogen/generated/ios/swift/HybridCastManagerSpec.swift +76 -0
  1077. package/nitrogen/generated/ios/swift/HybridCastManagerSpec_cxx.swift +519 -0
  1078. package/nitrogen/generated/ios/swift/HybridEqualizerSpec.swift +66 -0
  1079. package/nitrogen/generated/ios/swift/HybridEqualizerSpec_cxx.swift +353 -0
  1080. package/nitrogen/generated/ios/swift/HybridTrackPlayerSpec.swift +122 -0
  1081. package/nitrogen/generated/ios/swift/HybridTrackPlayerSpec_cxx.swift +1430 -0
  1082. package/nitrogen/generated/ios/swift/HybridVisualizerSpec.swift +56 -0
  1083. package/nitrogen/generated/ios/swift/HybridVisualizerSpec_cxx.swift +163 -0
  1084. package/nitrogen/generated/ios/swift/LookaheadCacheConfig.swift +34 -0
  1085. package/nitrogen/generated/ios/swift/MediaSearchOrigin.swift +40 -0
  1086. package/nitrogen/generated/ios/swift/MediaSearchQueueLocation.swift +44 -0
  1087. package/nitrogen/generated/ios/swift/MediaSearchReference.swift +40 -0
  1088. package/nitrogen/generated/ios/swift/MediaSearchReleaseDateRange.swift +60 -0
  1089. package/nitrogen/generated/ios/swift/MediaSearchRepeatMode.swift +44 -0
  1090. package/nitrogen/generated/ios/swift/MediaSearchRequest.swift +239 -0
  1091. package/nitrogen/generated/ios/swift/MediaSearchType.swift +52 -0
  1092. package/nitrogen/generated/ios/swift/NowPlayingFormat.swift +394 -0
  1093. package/nitrogen/generated/ios/swift/NowPlayingFormatAndroidExtras.swift +135 -0
  1094. package/nitrogen/generated/ios/swift/NowPlayingFormatIosExtras.swift +61 -0
  1095. package/nitrogen/generated/ios/swift/PitchCorrectionMode.swift +44 -0
  1096. package/nitrogen/generated/ios/swift/PlaybackError.swift +64 -0
  1097. package/nitrogen/generated/ios/swift/PlaybackErrorCode.swift +80 -0
  1098. package/nitrogen/generated/ios/swift/PlaybackMode.swift +47 -0
  1099. package/nitrogen/generated/ios/swift/PlaybackModeKind.swift +40 -0
  1100. package/nitrogen/generated/ios/swift/PlayerConfig.swift +251 -0
  1101. package/nitrogen/generated/ios/swift/PlayerProgress.swift +39 -0
  1102. package/nitrogen/generated/ios/swift/PlayerState.swift +60 -0
  1103. package/nitrogen/generated/ios/swift/RemoteControlOptions.swift +39 -0
  1104. package/nitrogen/generated/ios/swift/RemoteSkipMode.swift +40 -0
  1105. package/nitrogen/generated/ios/swift/RepeatMode.swift +44 -0
  1106. package/nitrogen/generated/ios/swift/ReplayGainMode.swift +44 -0
  1107. package/nitrogen/generated/ios/swift/SectionIcon.swift +84 -0
  1108. package/nitrogen/generated/ios/swift/ServiceReadyReason.swift +40 -0
  1109. package/nitrogen/generated/ios/swift/ShuffleResult.swift +51 -0
  1110. package/nitrogen/generated/ios/swift/SkipCapability.swift +34 -0
  1111. package/nitrogen/generated/ios/swift/SleepTimerState.swift +70 -0
  1112. package/nitrogen/generated/ios/swift/StateChangeReason.swift +60 -0
  1113. package/nitrogen/generated/ios/swift/TrackChangeReason.swift +60 -0
  1114. package/nitrogen/generated/ios/swift/TrackItem.swift +169 -0
  1115. package/nitrogen/generated/ios/swift/TrackSource.swift +44 -0
  1116. package/nitrogen/generated/ios/swift/Variant_NullType_Double.swift +30 -0
  1117. package/nitrogen/generated/ios/swift/Variant_NullType_NowPlayingFormat.swift +30 -0
  1118. package/nitrogen/generated/ios/swift/Variant_NullType_String.swift +30 -0
  1119. package/nitrogen/generated/ios/swift/VisualizerConfig.swift +52 -0
  1120. package/nitrogen/generated/ios/swift/VisualizerErrorReason.swift +48 -0
  1121. package/nitrogen/generated/ios/swift/VisualizerFrame.swift +52 -0
  1122. package/nitrogen/generated/ios/swift/VoiceVocabulary.swift +46 -0
  1123. package/nitrogen/generated/shared/c++/AudioCategoryOptions.hpp +91 -0
  1124. package/nitrogen/generated/shared/c++/AudioCodec.hpp +96 -0
  1125. package/nitrogen/generated/shared/c++/AudioContainer.hpp +100 -0
  1126. package/nitrogen/generated/shared/c++/AudioContentType.hpp +76 -0
  1127. package/nitrogen/generated/shared/c++/AudioRoute.hpp +101 -0
  1128. package/nitrogen/generated/shared/c++/AudioRouteKind.hpp +120 -0
  1129. package/nitrogen/generated/shared/c++/BrowseItem.hpp +104 -0
  1130. package/nitrogen/generated/shared/c++/BrowseSection.hpp +106 -0
  1131. package/nitrogen/generated/shared/c++/BrowseSnapshot.hpp +90 -0
  1132. package/nitrogen/generated/shared/c++/BufferState.hpp +84 -0
  1133. package/nitrogen/generated/shared/c++/CacheStatus.hpp +100 -0
  1134. package/nitrogen/generated/shared/c++/CastConfigureOptions.hpp +88 -0
  1135. package/nitrogen/generated/shared/c++/CastConnectOptions.hpp +83 -0
  1136. package/nitrogen/generated/shared/c++/CastDeviceKind.hpp +92 -0
  1137. package/nitrogen/generated/shared/c++/CastDiscoveryState.hpp +83 -0
  1138. package/nitrogen/generated/shared/c++/CastLocalNetworkPermission.hpp +80 -0
  1139. package/nitrogen/generated/shared/c++/CastLocalNetworkPermissionEvent.hpp +84 -0
  1140. package/nitrogen/generated/shared/c++/CastProtocol.hpp +88 -0
  1141. package/nitrogen/generated/shared/c++/CastReceiver.hpp +115 -0
  1142. package/nitrogen/generated/shared/c++/CastReceiverCapabilities.hpp +92 -0
  1143. package/nitrogen/generated/shared/c++/CastRoute.hpp +111 -0
  1144. package/nitrogen/generated/shared/c++/CastSessionDiedEvent.hpp +89 -0
  1145. package/nitrogen/generated/shared/c++/CastSessionEndReason.hpp +100 -0
  1146. package/nitrogen/generated/shared/c++/CastStreamingModel.hpp +76 -0
  1147. package/nitrogen/generated/shared/c++/EqualizerBand.hpp +87 -0
  1148. package/nitrogen/generated/shared/c++/EqualizerPreset.hpp +92 -0
  1149. package/nitrogen/generated/shared/c++/EvictionPolicy.hpp +76 -0
  1150. package/nitrogen/generated/shared/c++/HybridCastManagerSpec.cpp +42 -0
  1151. package/nitrogen/generated/shared/c++/HybridCastManagerSpec.hpp +115 -0
  1152. package/nitrogen/generated/shared/c++/HybridEqualizerSpec.cpp +32 -0
  1153. package/nitrogen/generated/shared/c++/HybridEqualizerSpec.hpp +81 -0
  1154. package/nitrogen/generated/shared/c++/HybridTrackPlayerSpec.cpp +88 -0
  1155. package/nitrogen/generated/shared/c++/HybridTrackPlayerSpec.hpp +209 -0
  1156. package/nitrogen/generated/shared/c++/HybridVisualizerSpec.cpp +22 -0
  1157. package/nitrogen/generated/shared/c++/HybridVisualizerSpec.hpp +71 -0
  1158. package/nitrogen/generated/shared/c++/LookaheadCacheConfig.hpp +87 -0
  1159. package/nitrogen/generated/shared/c++/MediaSearchOrigin.hpp +76 -0
  1160. package/nitrogen/generated/shared/c++/MediaSearchQueueLocation.hpp +80 -0
  1161. package/nitrogen/generated/shared/c++/MediaSearchReference.hpp +76 -0
  1162. package/nitrogen/generated/shared/c++/MediaSearchReleaseDateRange.hpp +87 -0
  1163. package/nitrogen/generated/shared/c++/MediaSearchRepeatMode.hpp +80 -0
  1164. package/nitrogen/generated/shared/c++/MediaSearchRequest.hpp +157 -0
  1165. package/nitrogen/generated/shared/c++/MediaSearchType.hpp +88 -0
  1166. package/nitrogen/generated/shared/c++/NowPlayingFormat.hpp +149 -0
  1167. package/nitrogen/generated/shared/c++/NowPlayingFormatAndroidExtras.hpp +94 -0
  1168. package/nitrogen/generated/shared/c++/NowPlayingFormatIosExtras.hpp +85 -0
  1169. package/nitrogen/generated/shared/c++/PitchCorrectionMode.hpp +80 -0
  1170. package/nitrogen/generated/shared/c++/PlaybackError.hpp +113 -0
  1171. package/nitrogen/generated/shared/c++/PlaybackErrorCode.hpp +116 -0
  1172. package/nitrogen/generated/shared/c++/PlaybackMode.hpp +89 -0
  1173. package/nitrogen/generated/shared/c++/PlaybackModeKind.hpp +76 -0
  1174. package/nitrogen/generated/shared/c++/PlayerConfig.hpp +141 -0
  1175. package/nitrogen/generated/shared/c++/PlayerProgress.hpp +91 -0
  1176. package/nitrogen/generated/shared/c++/PlayerState.hpp +96 -0
  1177. package/nitrogen/generated/shared/c++/RemoteControlOptions.hpp +92 -0
  1178. package/nitrogen/generated/shared/c++/RemoteSkipMode.hpp +76 -0
  1179. package/nitrogen/generated/shared/c++/RepeatMode.hpp +80 -0
  1180. package/nitrogen/generated/shared/c++/ReplayGainMode.hpp +80 -0
  1181. package/nitrogen/generated/shared/c++/SectionIcon.hpp +120 -0
  1182. package/nitrogen/generated/shared/c++/ServiceReadyReason.hpp +76 -0
  1183. package/nitrogen/generated/shared/c++/ShuffleResult.hpp +94 -0
  1184. package/nitrogen/generated/shared/c++/SkipCapability.hpp +87 -0
  1185. package/nitrogen/generated/shared/c++/SleepTimerState.hpp +95 -0
  1186. package/nitrogen/generated/shared/c++/StateChangeReason.hpp +96 -0
  1187. package/nitrogen/generated/shared/c++/TrackChangeReason.hpp +96 -0
  1188. package/nitrogen/generated/shared/c++/TrackItem.hpp +113 -0
  1189. package/nitrogen/generated/shared/c++/TrackSource.hpp +80 -0
  1190. package/nitrogen/generated/shared/c++/VisualizerConfig.hpp +91 -0
  1191. package/nitrogen/generated/shared/c++/VisualizerErrorReason.hpp +84 -0
  1192. package/nitrogen/generated/shared/c++/VisualizerFrame.hpp +92 -0
  1193. package/nitrogen/generated/shared/c++/VoiceVocabulary.hpp +88 -0
  1194. package/package.json +167 -0
  1195. package/src/CastManager.nitro.ts +206 -0
  1196. package/src/Equalizer.nitro.ts +37 -0
  1197. package/src/TrackPlayer.nitro.ts +667 -0
  1198. package/src/Visualizer.nitro.ts +48 -0
  1199. package/src/cast/index.ts +224 -0
  1200. package/src/clients.ts +50 -0
  1201. package/src/equalizer.ts +86 -0
  1202. package/src/hooks/index.ts +33 -0
  1203. package/src/hooks/useActiveTrack.ts +55 -0
  1204. package/src/hooks/useAudioRoute.ts +69 -0
  1205. package/src/hooks/useBufferState.ts +35 -0
  1206. package/src/hooks/useCanSkip.ts +92 -0
  1207. package/src/hooks/useCast.ts +121 -0
  1208. package/src/hooks/useEqualizer.ts +111 -0
  1209. package/src/hooks/useFullyBuffered.ts +32 -0
  1210. package/src/hooks/useLookaheadCache.ts +54 -0
  1211. package/src/hooks/useNowPlayingFormat.ts +43 -0
  1212. package/src/hooks/usePlaybackState.ts +34 -0
  1213. package/src/hooks/useProgress.ts +36 -0
  1214. package/src/hooks/useSleepTimer.ts +63 -0
  1215. package/src/hooks/useVisualizerState.ts +121 -0
  1216. package/src/index.ts +125 -0
  1217. package/src/playbackService.ts +304 -0
  1218. package/src/types.ts +1387 -0
@@ -0,0 +1,1350 @@
1
+ package com.margelo.nitro.queueplayer
2
+
3
+ import android.content.Context
4
+ import android.media.AudioFocusRequest
5
+ import android.media.AudioManager
6
+ import android.os.Build
7
+ import androidx.annotation.MainThread
8
+ import androidx.annotation.RequiresApi
9
+ import androidx.media3.common.AudioAttributes
10
+ import androidx.media3.common.C
11
+ import androidx.media3.common.MediaItem
12
+ import androidx.media3.common.Metadata
13
+ import androidx.media3.common.PlaybackException
14
+ import androidx.media3.common.Player
15
+ import androidx.media3.common.Tracks
16
+ import androidx.media3.common.audio.AudioProcessor
17
+ import androidx.media3.common.util.UnstableApi
18
+ import androidx.media3.exoplayer.DefaultLoadControl
19
+ import androidx.media3.exoplayer.ExoPlayer
20
+ import androidx.media3.exoplayer.LoadControl
21
+ import androidx.media3.exoplayer.RenderersFactory
22
+ import androidx.media3.exoplayer.analytics.AnalyticsListener
23
+ import androidx.media3.exoplayer.audio.TeeAudioProcessor
24
+ import androidx.media3.exoplayer.source.MediaSource
25
+ import kotlinx.coroutines.CoroutineScope
26
+ import kotlinx.coroutines.Dispatchers
27
+ import kotlinx.coroutines.Job
28
+ import kotlinx.coroutines.SupervisorJob
29
+ import kotlinx.coroutines.cancel
30
+ import kotlinx.coroutines.delay
31
+ import kotlinx.coroutines.isActive
32
+ import kotlinx.coroutines.launch
33
+ import java.util.concurrent.CopyOnWriteArrayList
34
+ import kotlin.math.PI
35
+ import kotlin.math.cos
36
+ import kotlin.math.min
37
+ import kotlin.math.sin
38
+
39
+ /**
40
+ * Dual-`ExoPlayer` engine implementing equal-power crossfade at
41
+ * track boundaries.
42
+ *
43
+ * Two ExoPlayer instances rotate roles: the **leading** player is
44
+ * the one currently audible to the listener; the **standby**
45
+ * player prerolls the next queue item ahead of the fade window
46
+ * and ramps up from silence as the leading ramps down. At
47
+ * fade-complete the roles swap.
48
+ *
49
+ * Build constraints (per platform research):
50
+ * - Per-player [MediaSource.Factory]: sharing a factory across
51
+ * two `ExoPlayer` instances is documented as an anti-pattern
52
+ * (see `androidx.media` issue #9099 + ExoPlayer #3438) — DRM
53
+ * provider state and `MediaSource.Factory` configuration
54
+ * couple to a single playback Looper. Each player must own its
55
+ * own factory; the underlying `SimpleCache` is shared via the
56
+ * factory's `CacheDataSource.Factory` so cache reads benefit
57
+ * from prior downloads.
58
+ * - Per-player [LoadControl]: standby uses a smaller buffer
59
+ * window so it doesn't compete with the active player for
60
+ * memory. Defaults align with the leading player.
61
+ * - `handleAudioFocus = false` on BOTH legs: two simultaneously-
62
+ * active Media3 focus requests fight each other (each
63
+ * `AudioFocusManager$AudioFocusListener` is a distinct
64
+ * listener instance from AudioFlinger's perspective even
65
+ * within the same UID — a second request fires
66
+ * `AUDIOFOCUS_LOSS` to the first). The engine instead owns
67
+ * one [AudioManager.OnAudioFocusChangeListener] that
68
+ * coordinates pause/duck across both players.
69
+ *
70
+ * Fade timing:
71
+ * - Position-poll on the leading player at 200ms tick fires
72
+ * when `currentPosition >= duration - crossfadeDurationMs - 100ms`.
73
+ * - The execute coroutine runs on `Dispatchers.Main` at 20ms tick
74
+ * computing equal-power gains (`cos(t·π/2)` outgoing,
75
+ * `sin(t·π/2)` incoming) — `Choreographer.FrameCallback` is
76
+ * unsuitable for audio-only playback (VSYNC pauses when no
77
+ * Surface is rendering, which would freeze the ramp).
78
+ *
79
+ * Edge cases handled:
80
+ * - Manual skip / pause / seek mid-fade: cancel the execute job,
81
+ * snap leading to volume 1.0, release standby's item.
82
+ * - Active player ends before fade completes (duration metadata
83
+ * wrong / network truncation): `STATE_ENDED` listener cancels
84
+ * the poll, snaps standby to volume 1.0, swaps roles
85
+ * immediately so playback continues.
86
+ * - Auto-clamp `crossfadeDurationMs` to `min(configured,
87
+ * leadingDuration/2, standbyDuration/2)` at fade-arm time so
88
+ * short tracks never start a fade that can't complete.
89
+ */
90
+ @UnstableApi
91
+ @RequiresApi(Build.VERSION_CODES.O) // AudioFocusRequest is API 26+
92
+ internal class CrossfadeEngine(
93
+ private val context: Context,
94
+ /**
95
+ * Provider invoked once per leg at construction so each
96
+ * `ExoPlayer` instance receives its own `MediaSource.Factory`
97
+ * (sharing factories across players is a documented Media3
98
+ * anti-pattern — see `androidx.media #9099`). The provider may
99
+ * close over a shared `SimpleCache` so cache hits are reused
100
+ * across legs, which is the safe + recommended composition.
101
+ */
102
+ private val mediaSourceFactoryProvider: (() -> MediaSource.Factory)? = null,
103
+ private val audioContentType: AudioContentType? = null,
104
+ private val crossfadeDurationMs: Long,
105
+ ) : PlaybackEngine {
106
+
107
+ init {
108
+ require(crossfadeDurationMs >= 0L) { "crossfadeDurationMs must be non-negative" }
109
+ // Defence-in-depth: a remote PcmStream sink (AirPlay 1/2) can only
110
+ // accept input from ONE ExoPlayer at a time. CrossfadeEngine drives
111
+ // two players, so AirPlay streams through the dedicated single-player
112
+ // AirPlayEngine instead while a push-PCM route is active — the engine
113
+ // selector never builds a CrossfadeEngine then. This `check` catches a
114
+ // regression in that gating loud.
115
+ check(!com.margelo.nitro.queueplayer.cast.CastSinkRouter.isRemoteActive()) {
116
+ "CrossfadeEngine instantiated while a cast push-PCM session is active; " +
117
+ "the dedicated AirPlayEngine handles push-PCM routes."
118
+ }
119
+ }
120
+
121
+ override var delegate: PlaybackEngineDelegate? = null
122
+
123
+ // --- Visualizer audio chain (declared before players so buildPlayer
124
+ // can reference them; the engine owns the always-on Tee and exposes
125
+ // attach via the bufferSinks accumulator) ---
126
+
127
+ private val bufferSinks = CopyOnWriteArrayList<TeeAudioProcessor.AudioBufferSink>()
128
+
129
+ /**
130
+ * One [VisualizerTeeBuilder] per ExoPlayer leg — sharing a single
131
+ * Tee across two AudioSinks would interleave its `flush` +
132
+ * `handleBuffer` state. Both legs feed the same shared
133
+ * [bufferSinks] accumulator so a visualizer subscriber sees PCM
134
+ * from whichever leg is currently audible. Null when
135
+ * `VisualizationGate.isEnabled()` is false at construction time.
136
+ * See [GaplessEngine.visualizerTeeBuilder] for the orthogonality
137
+ * rationale with EQ.
138
+ */
139
+ private val visualizerTeeBuilderA: VisualizerTeeBuilder? =
140
+ if (VisualizationGate.isEnabled()) VisualizerTeeBuilder(bufferSinks) else null
141
+ private val visualizerTeeBuilderB: VisualizerTeeBuilder? =
142
+ if (VisualizationGate.isEnabled()) VisualizerTeeBuilder(bufferSinks) else null
143
+
144
+ /**
145
+ * One [ReplayGainAudioProcessor] per leg — each leg's
146
+ * [Player.Listener.onMetadata] pushes ONLY to its own processor so
147
+ * mid-fade tag arrival on the standby leg cannot stomp the leading
148
+ * leg's gain. The crossfade volume ramp (player.volume) is a
149
+ * separate layer; RG composes multiplicatively underneath.
150
+ */
151
+ private val replayGainProcessorA = ReplayGainAudioProcessor()
152
+ private val replayGainProcessorB = ReplayGainAudioProcessor()
153
+
154
+ /**
155
+ * Per-leg cached [ReplayGainData]. Mirror the iOS per-item
156
+ * `ItemRGState` cache: each leg owns its own data + processor +
157
+ * extraction lifecycle.
158
+ *
159
+ * ReplayGain recompute paths (per-leg listener parse → cache +
160
+ * push, JS-driven mode flip → both legs' cache snapshot + push)
161
+ * all run on the application main thread (Media3 dispatches
162
+ * `Player.Listener` callbacks on the application looper;
163
+ * [TrackPlayer.setReplayGainMode] hops to main before invoking
164
+ * [recomputeReplayGainFromConfig]). The @Volatile fields +
165
+ * @Volatile gain on each [ReplayGainAudioProcessor] are sufficient
166
+ * because there's only one writer per leg's cache + processor at
167
+ * any time.
168
+ */
169
+ @Volatile
170
+ private var cachedReplayGainDataA: ReplayGainData? = null
171
+ @Volatile
172
+ private var cachedReplayGainDataB: ReplayGainData? = null
173
+
174
+ // One mode-gated pitch-correction chain PER LEG — each holds its own
175
+ // (stateful) music time-stretcher, mirroring the per-leg RG + viz Tee rule.
176
+ private val pitchChainA: PitchAwareAudioProcessorChain = run {
177
+ // Order: RG runs FIRST (pre-viz) so the visualizer + downstream
178
+ // pipeline see post-RG samples — matches "what the user hears".
179
+ val procs = mutableListOf<AudioProcessor>(replayGainProcessorA)
180
+ visualizerTeeBuilderA?.audioProcessor?.let { procs += it }
181
+ PitchAwareAudioProcessorChain(procs.toTypedArray())
182
+ }
183
+ private val pitchChainB: PitchAwareAudioProcessorChain = run {
184
+ val procs = mutableListOf<AudioProcessor>(replayGainProcessorB)
185
+ visualizerTeeBuilderB?.audioProcessor?.let { procs += it }
186
+ PitchAwareAudioProcessorChain(procs.toTypedArray())
187
+ }
188
+
189
+ private val renderersFactoryA: RenderersFactory =
190
+ AudioPipelineRenderersFactory(context, pitchChainA)
191
+ private val renderersFactoryB: RenderersFactory =
192
+ AudioPipelineRenderersFactory(context, pitchChainB)
193
+
194
+ // --- Players ---
195
+
196
+ internal val playerA: ExoPlayer = buildPlayer(isStandby = false, renderersFactory = renderersFactoryA)
197
+ internal val playerB: ExoPlayer = buildPlayer(isStandby = true, renderersFactory = renderersFactoryB)
198
+
199
+ /** `true` when [playerA] is the leading (currently audible) leg. */
200
+ @Volatile
201
+ internal var currentRoleIsA: Boolean = true
202
+ private set
203
+
204
+ /** Leading leg — the player currently producing audible audio. */
205
+ internal val leadingPlayer: ExoPlayer
206
+ get() = if (currentRoleIsA) playerA else playerB
207
+
208
+ /** Standby leg — prerolls the next queue item; volume 0 outside fade window. */
209
+ internal val standbyPlayer: ExoPlayer
210
+ get() = if (currentRoleIsA) playerB else playerA
211
+
212
+ /**
213
+ * Service-level wiring binds `MediaSession` + `audioFocusListener`
214
+ * to the leading leg. Mid-fade role swap doesn't update this
215
+ * field; `CrossfadeForwardingPlayer` is the layer that hides
216
+ * the rotation from `MediaSession`.
217
+ */
218
+ override val mediaSessionPlayer: ExoPlayer get() = leadingPlayer
219
+
220
+ // --- Listener registries ---
221
+
222
+ private val sessionIdListeners = CopyOnWriteArrayList<(IntArray) -> Unit>()
223
+
224
+ private var sessionIdA: Int = C.AUDIO_SESSION_ID_UNSET
225
+ private var sessionIdB: Int = C.AUDIO_SESSION_ID_UNSET
226
+
227
+ // --- Fade state ---
228
+
229
+ private val engineScope = CoroutineScope(Dispatchers.Main + SupervisorJob())
230
+
231
+ /** Active fade job; null outside fade window. */
232
+ private var fadeJob: Job? = null
233
+
234
+ /**
235
+ * Position-poll Job — watches the leading leg's `currentPosition`
236
+ * every 200ms while playback is active and arms the fade when the
237
+ * window approaches. Cancelled on pause / stop / seek / skip /
238
+ * release. Restarted when [play] resumes.
239
+ */
240
+ private var armingJob: Job? = null
241
+
242
+ /** True after [armCrossfade] has prerolled standby for the upcoming fade. */
243
+ private var standbyArmed: Boolean = false
244
+
245
+ /**
246
+ * User-set volume for the leading leg, preserved across
247
+ * fade-cancel paths so manual `setVolume(v)` survives a
248
+ * subsequent skip / pause / seek that resets the fade.
249
+ * Standby leg is always at 0.0 outside the fade window.
250
+ */
251
+ private var userVolume: Float = 1f
252
+
253
+ /** Pitch-correction mode, applied to both legs' PlaybackParameters. */
254
+ private var pitchCorrectionMode: PitchCorrectionMode = PitchCorrectionMode.VOICE
255
+
256
+ /** Lib-level audio focus owner (replaces per-player handleAudioFocus = true). */
257
+ private val audioManager: AudioManager =
258
+ context.getSystemService(Context.AUDIO_SERVICE) as AudioManager
259
+
260
+ /**
261
+ * Tracks whether the engine was actively playing at the moment
262
+ * of an `AUDIOFOCUS_LOSS_TRANSIENT` so the matching `_GAIN`
263
+ * resumes only when the user hadn't already paused us.
264
+ * `false` when the user paused before focus was lost — in that
265
+ * case the gain is a no-op.
266
+ */
267
+ private var pausedByFocusLoss: Boolean = false
268
+
269
+ /**
270
+ * `true` while focus duck is active. The fade tick reads
271
+ * [effectiveUserVolume] so an in-flight ramp respects the duck;
272
+ * outside the fade window, the duck path sets player volumes
273
+ * directly. Cleared on `AUDIOFOCUS_GAIN`.
274
+ */
275
+ private var duckActive: Boolean = false
276
+
277
+ /** Pre-duck multiplier baked into the running fade, so the
278
+ * fade tick + the standalone-duck path agree on the target
279
+ * volume. */
280
+ private fun effectiveUserVolume(): Float =
281
+ if (duckActive) userVolume * DUCK_MULTIPLIER else userVolume
282
+
283
+ /**
284
+ * Threading: AudioManager dispatches the focus callback on the
285
+ * Looper attached to the main thread by default (no Handler
286
+ * passed to the builder), so this lands on the same dispatcher
287
+ * the engine expects for every other call.
288
+ */
289
+ private val focusListener = AudioManager.OnAudioFocusChangeListener { focusChange ->
290
+ when (focusChange) {
291
+ AudioManager.AUDIOFOCUS_LOSS -> {
292
+ pausedByFocusLoss = false
293
+ duckActive = false
294
+ playerA.pause()
295
+ playerB.pause()
296
+ }
297
+ AudioManager.AUDIOFOCUS_LOSS_TRANSIENT -> {
298
+ pausedByFocusLoss = leadingPlayer.isPlaying
299
+ duckActive = false
300
+ playerA.pause()
301
+ playerB.pause()
302
+ }
303
+ AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK -> {
304
+ // Notification ping over media etc. — Media3's
305
+ // AudioFocusManager would lower the volume rather than
306
+ // pause; mirror that since we own the policy now.
307
+ // Toggling [duckActive] makes the fade tick honour the
308
+ // duck via [effectiveUserVolume]; for the standalone case
309
+ // (no fade in flight) the player volumes are set directly
310
+ // so the duck takes effect immediately.
311
+ duckActive = true
312
+ if (fadeJob?.isActive != true) {
313
+ leadingPlayer.volume = effectiveUserVolume()
314
+ standbyPlayer.volume = 0f
315
+ }
316
+ }
317
+ AudioManager.AUDIOFOCUS_GAIN -> {
318
+ if (duckActive) {
319
+ duckActive = false
320
+ if (fadeJob?.isActive != true) {
321
+ leadingPlayer.volume = effectiveUserVolume()
322
+ standbyPlayer.volume = 0f
323
+ }
324
+ }
325
+ if (pausedByFocusLoss) {
326
+ pausedByFocusLoss = false
327
+ // Resume via the engine's own [play] so the boundary-arming
328
+ // poll restarts; calling `leadingPlayer.play()` directly
329
+ // would resume audio but leave the next fade boundary
330
+ // un-armed. Audio focus is already granted on this branch
331
+ // so the inner requestAudioFocus is a no-op.
332
+ play()
333
+ }
334
+ }
335
+ }
336
+ }
337
+ private val focusRequest: AudioFocusRequest = AudioFocusRequest
338
+ .Builder(AudioManager.AUDIOFOCUS_GAIN)
339
+ .setAudioAttributes(buildPlatformAudioAttributes())
340
+ .setOnAudioFocusChangeListener(focusListener)
341
+ .setAcceptsDelayedFocusGain(false)
342
+ .build()
343
+
344
+ private var released: Boolean = false
345
+
346
+ // --- Player listeners ---
347
+
348
+ private val leadingPlayerListener = object : Player.Listener {
349
+ override fun onPlaybackStateChanged(playbackState: Int) {
350
+ if (released) return
351
+ delegate?.onStateMaybeChanged(this@CrossfadeEngine, playWhenReadyReason = null)
352
+ if (playbackState == Player.STATE_ENDED) {
353
+ // Leading player ended naturally — if a fade was in flight
354
+ // it didn't complete in time. Cancel the ramp, snap
355
+ // standby to full volume, swap roles immediately so
356
+ // playback continues without a silent gap.
357
+ if (fadeJob?.isActive == true) {
358
+ cancelFadeAndPromoteStandby()
359
+ }
360
+ delegate?.onPlaybackEnded(this@CrossfadeEngine)
361
+ }
362
+ }
363
+
364
+ override fun onPlayWhenReadyChanged(playWhenReady: Boolean, reason: Int) {
365
+ if (released) return
366
+ delegate?.onStateMaybeChanged(this@CrossfadeEngine, playWhenReadyReason = reason)
367
+ }
368
+
369
+ override fun onIsPlayingChanged(isPlaying: Boolean) {
370
+ if (released) return
371
+ delegate?.onIsPlayingChanged(this@CrossfadeEngine, isPlaying)
372
+ delegate?.onStateMaybeChanged(this@CrossfadeEngine, playWhenReadyReason = null)
373
+ }
374
+
375
+ override fun onMediaItemTransition(mediaItem: MediaItem?, reason: Int) {
376
+ if (released) return
377
+ delegate?.onTrackTransition(this@CrossfadeEngine, reason)
378
+ }
379
+
380
+ override fun onTracksChanged(tracks: Tracks) {
381
+ if (released) return
382
+ delegate?.onActiveItemFormatChanged(this@CrossfadeEngine)
383
+ }
384
+
385
+ override fun onPositionDiscontinuity(
386
+ oldPosition: Player.PositionInfo,
387
+ newPosition: Player.PositionInfo,
388
+ reason: Int,
389
+ ) {
390
+ if (released) return
391
+ if (reason == Player.DISCONTINUITY_REASON_AUTO_TRANSITION) {
392
+ delegate?.onAutoTransitionDiscontinuity(this@CrossfadeEngine)
393
+ }
394
+ }
395
+
396
+ override fun onPlayerError(error: PlaybackException) {
397
+ if (released) return
398
+ delegate?.onError(this@CrossfadeEngine, error)
399
+ }
400
+ }
401
+
402
+ /**
403
+ * Standby leg listener — only forwards format-change signals so
404
+ * a cached prerolled item's audio session ID is observable
405
+ * before fade-start. Track-transition / playback-state events
406
+ * from the standby leg are filtered out: they aren't observable
407
+ * to the listener until the standby promotes to leading.
408
+ */
409
+ private val standbyPlayerListener = object : Player.Listener {
410
+ override fun onTracksChanged(tracks: Tracks) {
411
+ // No delegate fire — the active item is the leading leg's,
412
+ // not the standby's. Standby format becomes relevant only
413
+ // post-promotion, at which point the leading-listener fires.
414
+ }
415
+
416
+ override fun onPlayerError(error: PlaybackException) {
417
+ // Standby errors during preroll abort the upcoming fade.
418
+ // Surface as a normal engine error so the consumer can
419
+ // decide whether to skip / retry; the leading leg keeps
420
+ // playing.
421
+ if (released) return
422
+ cancelFade()
423
+ delegate?.onError(this@CrossfadeEngine, error)
424
+ }
425
+ }
426
+
427
+ private val analyticsListenerA = makeSessionIdListener(isA = true)
428
+ private val analyticsListenerB = makeSessionIdListener(isA = false)
429
+
430
+ private fun makeSessionIdListener(isA: Boolean) = object : AnalyticsListener {
431
+ override fun onAudioSessionIdChanged(
432
+ eventTime: AnalyticsListener.EventTime,
433
+ audioSessionId: Int,
434
+ ) {
435
+ if (isA) sessionIdA = audioSessionId else sessionIdB = audioSessionId
436
+ val ids = currentAudioSessionIds()
437
+ sessionIdListeners.forEach { it(ids) }
438
+ }
439
+ }
440
+
441
+ /**
442
+ * Per-leg ReplayGain listener bound to the leg identity (NOT the
443
+ * role). [swapRoles] migrates [leadingPlayerListener] /
444
+ * [standbyPlayerListener] across legs because they are role-shaped
445
+ * (forward-to-delegate vs filter-everything-but-error); the RG
446
+ * listener is leg-shaped and stays attached to its own leg through
447
+ * every role swap. Each leg's `onMetadata` pushes ONLY to its own
448
+ * processor / cache.
449
+ */
450
+ private val replayGainListenerA = makeReplayGainListener(isA = true)
451
+ private val replayGainListenerB = makeReplayGainListener(isA = false)
452
+
453
+ private fun makeReplayGainListener(isA: Boolean) = object : Player.Listener {
454
+ override fun onMediaItemTransition(mediaItem: MediaItem?, reason: Int) {
455
+ if (isA) {
456
+ cachedReplayGainDataA = null
457
+ replayGainProcessorA.setLinearGain(1.0f)
458
+ } else {
459
+ cachedReplayGainDataB = null
460
+ replayGainProcessorB.setLinearGain(1.0f)
461
+ }
462
+ }
463
+
464
+ override fun onTracksChanged(tracks: Tracks) {
465
+ // Container-level metadata (`Format.metadata` populated by
466
+ // Mp3Extractor / FlacExtractor / Mp4Extractor / OggExtractor)
467
+ // surfaces here, not via `onMetadata` — the latter only fires
468
+ // for in-stream metadata samples (HLS in-stream events, ICY
469
+ // shoutcast) routed through `MetadataRenderer`. `onTracksChanged`
470
+ // fires both at initial track-selection AND on auto-advance.
471
+ val (format, mimeType) = pickSelectedAudioFormat(tracks) ?: return
472
+ val parsed = ReplayGainExtractor.extract(format.metadata, mimeType)
473
+ handleReplayGainParse(isA = isA, parsed = parsed)
474
+ // Re-signal the format change AFTER the RG parse. The same leg's
475
+ // leadingPlayerListener.onTracksChanged already fired
476
+ // onActiveItemFormatChanged (it is registered first), but with an
477
+ // empty RG cache — so the now-playing snapshot would carry null
478
+ // replayGain*Db. Re-fire so it picks up the freshly-parsed tags.
479
+ // Mirrors GaplessEngine.onTracksChanged, which parses THEN signals
480
+ // the format change within a single listener.
481
+ delegate?.onActiveItemFormatChanged(this@CrossfadeEngine)
482
+ }
483
+
484
+ override fun onMetadata(metadata: Metadata) {
485
+ // Defensive path for in-stream metadata samples (HLS in-stream
486
+ // RG tags, ICY shoutcast). The container-level path runs via
487
+ // `onTracksChanged` above.
488
+ val player = if (isA) playerA else playerB
489
+ val mimeType = currentSampleMimeType(player)
490
+ val parsed = ReplayGainExtractor.extract(metadata, mimeType)
491
+ handleReplayGainParse(isA = isA, parsed = parsed)
492
+ delegate?.onActiveItemFormatChanged(this@CrossfadeEngine)
493
+ }
494
+ }
495
+
496
+ init {
497
+ playerA.addListener(leadingPlayerListener)
498
+ playerA.addListener(replayGainListenerA)
499
+ playerA.addAnalyticsListener(analyticsListenerA)
500
+ playerB.addListener(standbyPlayerListener)
501
+ playerB.addListener(replayGainListenerB)
502
+ playerB.addAnalyticsListener(analyticsListenerB)
503
+ // Standby starts at volume 0 — it should not contribute to
504
+ // the audible mix until the fade arms.
505
+ playerB.volume = 0f
506
+ }
507
+
508
+ // --- PlaybackEngine: lifecycle ---
509
+
510
+ override suspend fun prepare(
511
+ mediaItems: List<MediaItem>,
512
+ startIndex: Int,
513
+ startPositionMs: Long,
514
+ ) {
515
+ leadingPlayer.setMediaItems(mediaItems, startIndex, startPositionMs)
516
+ leadingPlayer.prepare()
517
+ }
518
+
519
+ override fun release() {
520
+ if (released) return
521
+ released = true
522
+ // Release runs as part of an engine swap or destroy; the new
523
+ // engine has already taken over the canonical active-track
524
+ // state, so a mid-fade revert emit here would surface a
525
+ // spurious onTrackChange to the OUTGOING leg of a fade that
526
+ // the consumer no longer cares about.
527
+ cancelFade(emitRevert = false)
528
+ stopArmingPoll()
529
+ audioManager.abandonAudioFocusRequest(focusRequest)
530
+ // [leadingPlayerListener] / [standbyPlayerListener] are
531
+ // role-shaped: [swapRoles] migrates them across legs on every
532
+ // fade. Read them off the current role at release-time so the
533
+ // remove call lands on the leg that actually owns each listener
534
+ // — `Player.removeListener` is a no-op against an unattached
535
+ // listener so a stale call wouldn't leak, but the role-shaped
536
+ // form is what the listeners actually wire to.
537
+ leadingPlayer.removeListener(leadingPlayerListener)
538
+ standbyPlayer.removeListener(standbyPlayerListener)
539
+ // RG listeners + analytics listeners are leg-shaped — they stay
540
+ // attached to their construction-time leg through every swap.
541
+ playerA.removeListener(replayGainListenerA)
542
+ playerA.removeAnalyticsListener(analyticsListenerA)
543
+ playerB.removeListener(replayGainListenerB)
544
+ playerB.removeAnalyticsListener(analyticsListenerB)
545
+ sessionIdListeners.clear()
546
+ bufferSinks.clear()
547
+ delegate = null
548
+ engineScope.cancel()
549
+ playerA.release()
550
+ playerB.release()
551
+ }
552
+
553
+ // --- PlaybackEngine: queue mutation ---
554
+ //
555
+ // Single-item-per-leg model. The engine's queue is the lib-side
556
+ // canonical model owned by `TrackPlayer`; the engine receives
557
+ // pre-built `MediaItem` snapshots and either installs them on
558
+ // the leading leg directly (gapless-equivalent path while no
559
+ // fade is in flight) or queues them for the standby preroll.
560
+
561
+ override fun setMediaItems(
562
+ items: List<MediaItem>,
563
+ startIndex: Int,
564
+ startPositionMs: Long,
565
+ ) {
566
+ // emitRevert=false: the caller (setQueue / engine swap) sets the
567
+ // canonical active index itself, so a mid-fade revert here would
568
+ // clobber it with the pre-mutation leading index + emit a spurious
569
+ // crossfade-cancelled track-change.
570
+ cancelFade(emitRevert = false)
571
+ // Reset arming state — the previous queue's preroll-armed
572
+ // standby is stale once the queue is replaced. Without this,
573
+ // [standbyArmed] could remain true against an empty / unrelated
574
+ // queue and [maybeArmCrossfade] would early-return forever.
575
+ standbyArmed = false
576
+ leadingPlayer.setMediaItems(items, startIndex, startPositionMs)
577
+ leadingPlayer.prepare()
578
+ standbyPlayer.stop()
579
+ standbyPlayer.clearMediaItems()
580
+ standbyPlayer.volume = 0f
581
+ // Empty queue — no boundaries to arm. Stop the poll until
582
+ // play() restarts it.
583
+ if (items.isEmpty()) {
584
+ stopArmingPoll()
585
+ }
586
+ }
587
+
588
+ override fun addMediaItems(items: List<MediaItem>, insertBefore: Int) {
589
+ // Queue mutation invalidates the standby leg's pre-loaded
590
+ // future. Cancel any in-flight fade before mutating the
591
+ // leading queue so the standby's stale mediaItems don't race
592
+ // a swapRoles against the post-mutation index space.
593
+ // emitRevert=false: the TrackPlayer mutation body recomputes the
594
+ // canonical index, so a mid-fade revert here would clobber it.
595
+ cancelFade(emitRevert = false)
596
+ leadingPlayer.addMediaItems(insertBefore, items)
597
+ }
598
+
599
+ override fun removeMediaItems(indices: IntArray) {
600
+ cancelFade(emitRevert = false)
601
+ val sorted = indices.toMutableList().apply { sortDescending() }
602
+ for (i in sorted) leadingPlayer.removeMediaItem(i)
603
+ }
604
+
605
+ override fun moveMediaItem(fromIndex: Int, toIndex: Int) {
606
+ cancelFade(emitRevert = false)
607
+ leadingPlayer.moveMediaItem(fromIndex, toIndex)
608
+ }
609
+
610
+ // --- PlaybackEngine: transport ---
611
+
612
+ override fun play() {
613
+ // Request audio focus so the focusListener gets duck / loss
614
+ // callbacks for as long as we're playing, but do NOT gate the
615
+ // actual play on the grant result. AudioManager can briefly
616
+ // return DENIED right after a sibling engine release abandons
617
+ // focus (e.g. during a mid-play setPlaybackMode → swap →
618
+ // play sequence) — gating would silently leave the user
619
+ // paused. Media3's AudioFocusManager (used by GaplessEngine)
620
+ // takes the same approach: focus is best-effort, playback
621
+ // proceeds.
622
+ audioManager.requestAudioFocus(focusRequest)
623
+ leadingPlayer.play()
624
+ startArmingPoll()
625
+ }
626
+
627
+ override fun pause() {
628
+ cancelFade()
629
+ stopArmingPoll()
630
+ leadingPlayer.pause()
631
+ standbyPlayer.pause()
632
+ }
633
+
634
+ override fun stop() {
635
+ cancelFade()
636
+ stopArmingPoll()
637
+ leadingPlayer.stop()
638
+ standbyPlayer.stop()
639
+ audioManager.abandonAudioFocusRequest(focusRequest)
640
+ }
641
+
642
+ override fun seekTo(index: Int, positionMs: Long) {
643
+ // emitRevert=false: every JS-facing seek + skip routes through here
644
+ // with an explicit target index already written to currentTrackIndex
645
+ // by the caller, so a mid-fade revert would clobber it back to the
646
+ // outgoing leg + emit a spurious crossfade-cancelled track-change.
647
+ cancelFade(emitRevert = false)
648
+ leadingPlayer.seekTo(index, positionMs)
649
+ standbyArmed = false
650
+ }
651
+
652
+ override fun skipToNext() {
653
+ cancelFade()
654
+ leadingPlayer.seekToNextMediaItem()
655
+ standbyArmed = false
656
+ }
657
+
658
+ override fun skipToPrevious() {
659
+ cancelFade()
660
+ leadingPlayer.seekToPreviousMediaItem()
661
+ standbyArmed = false
662
+ }
663
+
664
+ // --- PlaybackEngine: config ---
665
+
666
+ override fun setVolume(volume: Float) {
667
+ userVolume = volume
668
+ leadingPlayer.volume = volume
669
+ }
670
+
671
+ override fun setPlaybackSpeed(speed: Float) {
672
+ // Both legs carry the active pitch-correction mode's pitch; the
673
+ // standby prerolls at the same params so the fade-in is already at
674
+ // the right pitch.
675
+ val params = PitchCorrection.playbackParameters(pitchCorrectionMode, speed)
676
+ leadingPlayer.playbackParameters = params
677
+ standbyPlayer.playbackParameters = params
678
+ }
679
+
680
+ override fun setRepeatMode(mode: RepeatMode) {
681
+ val media3Mode = when (mode) {
682
+ RepeatMode.OFF -> Player.REPEAT_MODE_OFF
683
+ RepeatMode.TRACK -> Player.REPEAT_MODE_ONE
684
+ RepeatMode.QUEUE -> Player.REPEAT_MODE_ALL
685
+ }
686
+ leadingPlayer.repeatMode = media3Mode
687
+ standbyPlayer.repeatMode = media3Mode
688
+ }
689
+
690
+ override fun setPitchCorrectionMode(mode: PitchCorrectionMode) {
691
+ pitchCorrectionMode = mode
692
+ // Route both legs' chains to the matching stretcher BEFORE re-applying
693
+ // params, so applyPlaybackParameters sends the speed to the active one.
694
+ pitchChainA.setMode(mode)
695
+ pitchChainB.setMode(mode)
696
+ // Recompute against the current speed (both legs share it) so the
697
+ // pitch field flips immediately.
698
+ val speed = leadingPlayer.playbackParameters.speed
699
+ val params = PitchCorrection.playbackParameters(mode, speed)
700
+ leadingPlayer.playbackParameters = params
701
+ standbyPlayer.playbackParameters = params
702
+ }
703
+
704
+ override fun setWakeMode(mode: Int) {
705
+ // Both legs share the wake-mode policy: the standby leg also holds a
706
+ // wake/network lock while prerolling + fading in, so it must match
707
+ // the leading leg. Applying only to the leading leg would leave the
708
+ // post-swap leg on a stale (network) wake lock for an all-local queue.
709
+ leadingPlayer.setWakeMode(mode)
710
+ standbyPlayer.setWakeMode(mode)
711
+ }
712
+
713
+ // --- PlaybackEngine: state ---
714
+
715
+ /**
716
+ * During a crossfade the conceptual "active" track flips to the
717
+ * standby leg the moment the fade begins (matches the JS-facing
718
+ * `onTrackChange` + lock-screen / Now Playing flip the delegate
719
+ * performs in response to `onCrossfadeBegin`). The protocol
720
+ * accessors below honour this: when [fadeJob] is active they
721
+ * read from [standbyPlayer] (the incoming leg) so `useProgress`,
722
+ * seek clamps, preserve-current, and index lookups all see the
723
+ * incoming track. Engine-internal code reaches [leadingPlayer]
724
+ * directly. [isPlaying] continues to read [leadingPlayer] —
725
+ * during a fade the leading leg's `isPlaying` is the audible
726
+ * truth (the standby is also playing but at a fading-in volume).
727
+ */
728
+ private val activePlayer: ExoPlayer
729
+ get() = if (fadeJob?.isActive == true) standbyPlayer else leadingPlayer
730
+
731
+ override val currentMediaItemIndex: Int
732
+ get() {
733
+ val count = activePlayer.mediaItemCount
734
+ if (count == 0) return -1
735
+ return activePlayer.currentMediaItemIndex
736
+ }
737
+
738
+ override val currentPositionMs: Long
739
+ get() = activePlayer.currentPosition
740
+
741
+ override val currentDurationMs: Long
742
+ get() {
743
+ val d = activePlayer.duration
744
+ return if (d == C.TIME_UNSET) 0L else d
745
+ }
746
+
747
+ override val bufferedPositionMs: Long
748
+ get() = activePlayer.bufferedPosition
749
+
750
+ override val isPlaying: Boolean
751
+ get() = leadingPlayer.isPlaying
752
+
753
+ override val currentMediaItem: MediaItem?
754
+ get() = activePlayer.currentMediaItem
755
+
756
+ override val allMediaItems: List<MediaItem>
757
+ get() {
758
+ val count = leadingPlayer.mediaItemCount
759
+ if (count == 0) return emptyList()
760
+ val out = ArrayList<MediaItem>(count)
761
+ for (i in 0 until count) out.add(leadingPlayer.getMediaItemAt(i))
762
+ return out
763
+ }
764
+
765
+ // --- PlaybackEngine: effect chain ---
766
+
767
+ override fun currentAudioSessionIds(): IntArray {
768
+ val fadeActive = fadeJob?.isActive == true
769
+ val leading = if (currentRoleIsA) sessionIdA else sessionIdB
770
+ val standby = if (currentRoleIsA) sessionIdB else sessionIdA
771
+ return when {
772
+ fadeActive && leading != C.AUDIO_SESSION_ID_UNSET && standby != C.AUDIO_SESSION_ID_UNSET ->
773
+ intArrayOf(leading, standby)
774
+ leading != C.AUDIO_SESSION_ID_UNSET -> intArrayOf(leading)
775
+ else -> IntArray(0)
776
+ }
777
+ }
778
+
779
+ override fun addAudioSessionIdListener(listener: (IntArray) -> Unit): () -> Unit {
780
+ sessionIdListeners.add(listener)
781
+ listener(currentAudioSessionIds())
782
+ return { sessionIdListeners.remove(listener) }
783
+ }
784
+
785
+ override fun attachAudioBufferSink(sink: TeeAudioProcessor.AudioBufferSink) {
786
+ // No Tee to fan out to when viz was disabled at engine
787
+ // construction (PlayerConfig.visualizationEnabled = false).
788
+ val teeA = visualizerTeeBuilderA
789
+ val teeB = visualizerTeeBuilderB
790
+ if (teeA == null && teeB == null) return
791
+ // Mirrors `GaplessEngine`: accumulate the sink for the
792
+ // visualizer to consume. Both legs share the same accumulator;
793
+ // each leg's mux fans out independently when its AudioSink
794
+ // produces a buffer.
795
+ bufferSinks.addIfAbsent(sink)
796
+ // Replay the most recent flush params from every produced mux
797
+ // onto the new sink so it has its encoding context the moment
798
+ // it attaches, regardless of which leg has already flushed.
799
+ teeA?.primeNewSink(sink)
800
+ teeB?.primeNewSink(sink)
801
+ }
802
+
803
+ override fun detachAudioBufferSink(sink: TeeAudioProcessor.AudioBufferSink) {
804
+ bufferSinks.remove(sink)
805
+ }
806
+
807
+ // --- ReplayGain — engine-internal accessors ---
808
+
809
+ /**
810
+ * Recompute BOTH legs' processor gain from each leg's cached data
811
+ * + the current [ReplayGainConfig.getMode]. Called from
812
+ * [TrackPlayer.setReplayGainMode] when the user flips mode
813
+ * mid-track. Per-leg recompute on listener fires uses
814
+ * [recomputeLegFromConfig] internally.
815
+ *
816
+ * Main thread only — Media3 dispatches `Player.Listener`
817
+ * callbacks on the application looper and
818
+ * [TrackPlayer.setReplayGainMode] hops to main before calling.
819
+ */
820
+ @MainThread
821
+ internal fun recomputeReplayGainFromConfig() {
822
+ recomputeLegFromConfig(isA = true)
823
+ recomputeLegFromConfig(isA = false)
824
+ }
825
+
826
+ @MainThread
827
+ private fun recomputeLegFromConfig(isA: Boolean) {
828
+ val mode = ReplayGainConfig.getMode()
829
+ if (isA) {
830
+ replayGainProcessorA.setLinearGain(computeLinearGain(cachedReplayGainDataA, mode))
831
+ } else {
832
+ replayGainProcessorB.setLinearGain(computeLinearGain(cachedReplayGainDataB, mode))
833
+ }
834
+ }
835
+
836
+ /**
837
+ * Cache + recompute entry point shared by both per-leg listener
838
+ * paths. Called with the `ReplayGainData` produced by
839
+ * [ReplayGainExtractor] from either `Format.metadata`
840
+ * (container-level via `onTracksChanged`) or in-stream `Metadata`
841
+ * samples (via `onMetadata`). A `null` parse leaves the cache
842
+ * untouched — `onTracksChanged` fires for unrelated track-set
843
+ * changes too, and `onMetadata` fires for non-RG frames (TIT2
844
+ * title events, ICY now-playing, etc.).
845
+ *
846
+ * Per-leg shape: the listener routes to ONLY its own leg's cache
847
+ * + processor (never the other leg's), so a tag arrival on the
848
+ * standby leg cannot stomp the leading leg's gain mid-fade.
849
+ *
850
+ * Main thread only — Media3 dispatches `Player.Listener`
851
+ * callbacks on the application looper.
852
+ */
853
+ @MainThread
854
+ internal fun handleReplayGainParse(isA: Boolean, parsed: ReplayGainData?) {
855
+ if (parsed != null) {
856
+ if (isA) cachedReplayGainDataA = parsed else cachedReplayGainDataB = parsed
857
+ }
858
+ recomputeLegFromConfig(isA)
859
+ }
860
+
861
+ /**
862
+ * Snapshot the LEADING leg's cached [ReplayGainData] for the
863
+ * [NowPlayingFormatExtractor] surface. The active item from JS's
864
+ * point of view is always the leading leg's current item except
865
+ * during the fade window — at which point [activePlayer] flips to
866
+ * standby and this read should follow. Returns `null` when no
867
+ * usable RG tags have been parsed yet for the active leg's track.
868
+ */
869
+ override fun currentReplayGainData(): ReplayGainData? =
870
+ if (activePlayer === playerA) cachedReplayGainDataA else cachedReplayGainDataB
871
+
872
+ /**
873
+ * `true` when the active leg's cached data carries a tag for the
874
+ * current [ReplayGainConfig.getMode]. Used by the NowPlayingFormat
875
+ * path to populate `replayGainActive`.
876
+ */
877
+ override fun currentReplayGainActive(): Boolean {
878
+ val data = currentReplayGainData() ?: return false
879
+ val (gainDb, _) = data.selectGain(ReplayGainConfig.getMode())
880
+ return gainDb != null
881
+ }
882
+
883
+ /**
884
+ * Pick the first selected audio [androidx.media3.common.Format]
885
+ * out of [tracks]. Used by the per-leg
886
+ * [Player.Listener.onTracksChanged] to route `Format.metadata` +
887
+ * `Format.sampleMimeType` into [ReplayGainExtractor.extract]
888
+ * directly from the listener's live payload. Falls back to the
889
+ * first audio track in any group when nothing is currently
890
+ * selected. Returns `null` when no audio track exists.
891
+ */
892
+ private fun pickSelectedAudioFormat(
893
+ tracks: Tracks
894
+ ): Pair<androidx.media3.common.Format, String?>? {
895
+ var firstAudioFormat: androidx.media3.common.Format? = null
896
+ for (group in tracks.groups) {
897
+ if (group.type != C.TRACK_TYPE_AUDIO) continue
898
+ val mediaGroup = group.mediaTrackGroup
899
+ for (i in 0 until mediaGroup.length) {
900
+ val format = group.getTrackFormat(i)
901
+ if (firstAudioFormat == null) firstAudioFormat = format
902
+ if (group.isTrackSelected(i)) {
903
+ return format to format.sampleMimeType
904
+ }
905
+ }
906
+ }
907
+ val fallback = firstAudioFormat ?: return null
908
+ return fallback to fallback.sampleMimeType
909
+ }
910
+
911
+ /**
912
+ * Best-effort sample-MIME-type read from [player]'s currently-
913
+ * selected audio track. Used by the in-stream
914
+ * [Player.Listener.onMetadata] path (HLS / ICY) to gate the
915
+ * Opus-container guard in [ReplayGainExtractor.extract]. The
916
+ * container-level [Player.Listener.onTracksChanged] path reads
917
+ * the sample MIME directly from the listener's [Tracks] payload
918
+ * via [pickSelectedAudioFormat].
919
+ */
920
+ private fun currentSampleMimeType(player: ExoPlayer): String? {
921
+ for (group in player.currentTracks.groups) {
922
+ if (group.type != C.TRACK_TYPE_AUDIO) continue
923
+ val mediaGroup = group.mediaTrackGroup
924
+ for (i in 0 until mediaGroup.length) {
925
+ val format = group.getTrackFormat(i)
926
+ format.sampleMimeType?.let { return it }
927
+ }
928
+ }
929
+ return null
930
+ }
931
+
932
+ // --- PlaybackEngine: handoff ---
933
+
934
+ override suspend fun handoff(to: PlaybackEngine, atTrackBoundary: Boolean) {
935
+ // Engine handoff (gapless ↔ crossfade swap at TrackPlayer
936
+ // level) is wired in the swapEngine path on PlaybackService
937
+ // alongside this engine's own boundary detection. The
938
+ // crossfade-to-other-engine handoff lives at PlaybackService
939
+ // because TrackPlayer holds the canonical queue model that
940
+ // the receiving engine needs.
941
+ throw NotImplementedError(
942
+ "PlaybackEngine.handoff is driven by PlaybackService.swapEngine; do not call directly"
943
+ )
944
+ }
945
+
946
+ // --- Fade orchestration ---
947
+
948
+ /**
949
+ * Cancel any in-flight fade and snap the leading leg back to
950
+ * full volume + drop the standby leg's item. Called from manual
951
+ * skip / pause / seek paths and the route-degradation callback.
952
+ */
953
+ internal fun cancelFade(emitRevert: Boolean = true) {
954
+ val job = fadeJob
955
+ val wasMidFade = job?.isActive == true
956
+ val leadingIdx = leadingPlayer.currentMediaItemIndex
957
+ fadeJob = null
958
+ job?.cancel()
959
+ leadingPlayer.volume = userVolume
960
+ standbyPlayer.volume = 0f
961
+ standbyPlayer.stop()
962
+ standbyPlayer.clearMediaItems()
963
+ if (wasMidFade && emitRevert) {
964
+ // Mid-fade cancel: fade-start fired `onCrossfadeBegin` →
965
+ // delegate moved JS-facing state to the incoming leg. Revert
966
+ // to the leading leg now: re-bind the wrapper back to
967
+ // leadingPlayer so MediaSession metadata reverts; fire the
968
+ // delegate so JS gets a `crossfade-cancelled` track-change
969
+ // for the leading track. `emitRevert: false` is for callers
970
+ // that will immediately set a new active track themselves
971
+ // (e.g. engine release during a setPlaybackMode swap — the
972
+ // new engine has already taken over the canonical active-
973
+ // track state, so an intermediate revert here would surface
974
+ // a spurious onTrackChange to the OUTGOING leg of a fade
975
+ // the consumer no longer cares about).
976
+ onCrossfadeCancel?.invoke()
977
+ delegate?.onCrossfadeCancel(this, leadingIdx)
978
+ }
979
+ }
980
+
981
+ /**
982
+ * Cancel the in-flight fade and immediately swap the standby
983
+ * leg to leading at the user's chosen volume. Used when the
984
+ * leading leg ends naturally before the fade completes
985
+ * (truncated track, wrong duration metadata).
986
+ */
987
+ internal fun cancelFadeAndPromoteStandby() {
988
+ val job = fadeJob
989
+ fadeJob = null
990
+ job?.cancel()
991
+ leadingPlayer.volume = 0f
992
+ standbyPlayer.volume = userVolume
993
+ swapRoles()
994
+ }
995
+
996
+ /**
997
+ * Compute the effective fade duration for a transition,
998
+ * clamping to half of each leg's playable duration so the
999
+ * ramp never overflows track boundaries.
1000
+ */
1001
+ internal fun effectiveCrossfadeMs(leadingDurationMs: Long, standbyDurationMs: Long): Long {
1002
+ val configured = crossfadeDurationMs
1003
+ val leadingHalf = if (leadingDurationMs > 0) leadingDurationMs / 2 else configured
1004
+ val standbyHalf = if (standbyDurationMs > 0) standbyDurationMs / 2 else configured
1005
+ return min(min(configured, leadingHalf), standbyHalf).coerceAtLeast(0L)
1006
+ }
1007
+
1008
+ /**
1009
+ * Equal-power gain pair for the given fade progress
1010
+ * `t ∈ [0, 1]`. `(outgoing, incoming)` summed power stays at
1011
+ * 1.0 across the ramp, avoiding the perceptible -3dB midpoint
1012
+ * dip that linear ramps produce on uncorrelated content.
1013
+ */
1014
+ internal fun equalPowerGains(t: Float): Pair<Float, Float> {
1015
+ val clamped = t.coerceIn(0f, 1f)
1016
+ val angle = clamped * (PI / 2.0).toFloat()
1017
+ return cos(angle) to sin(angle)
1018
+ }
1019
+
1020
+ /**
1021
+ * Callback fired on every role swap so [CrossfadeForwardingPlayer]
1022
+ * (when bound by [PlaybackService.swapEngine]) can invalidate
1023
+ * its cached state + re-target `MediaSession.setPlayer` to the
1024
+ * new leading leg. Set by `PlaybackService` post-construction;
1025
+ * `null` when no wrapper is bound (e.g. headless tests).
1026
+ */
1027
+ internal var onRoleSwap: (() -> Unit)? = null
1028
+
1029
+ /**
1030
+ * Callback fired the instant a crossfade begins ramping. Lets
1031
+ * [CrossfadeForwardingPlayer] re-bind `MediaSession` to the
1032
+ * standby (incoming) leg so the lock-screen / Auto / BT
1033
+ * scrubber + metadata flip to the incoming track from 00:00 the
1034
+ * moment it begins audibly playing. The standby's `ExoPlayer`
1035
+ * instance becomes the new leading on [swapRoles] at fade-end,
1036
+ * so the [onRoleSwap] re-bind a moment later is a no-op (already
1037
+ * pointing at the same instance).
1038
+ */
1039
+ internal var onCrossfadeBegin: (() -> Unit)? = null
1040
+
1041
+ /**
1042
+ * Callback fired when an in-flight crossfade is cancelled
1043
+ * before [swapRoles] runs. Lets [CrossfadeForwardingPlayer]
1044
+ * re-bind `MediaSession` back to the leading leg so the lock-
1045
+ * screen / Auto / BT scrubber + metadata revert from the
1046
+ * incoming-track view that fade-start had pinned. Pairs with
1047
+ * [onCrossfadeBegin]: only fires when a `Begin` was fired
1048
+ * earlier and the fade did not complete.
1049
+ */
1050
+ internal var onCrossfadeCancel: (() -> Unit)? = null
1051
+
1052
+ private fun swapRoles() {
1053
+ // Migrate listeners to follow the role swap so the leading-leg
1054
+ // listener (which forwards onTrackTransition / onPlaybackStateChanged
1055
+ // / onIsPlayingChanged / onPlayerError to the engine delegate)
1056
+ // fires from the player that's now leading. Without this the
1057
+ // listeners stay glued to playerA / playerB and post-swap events
1058
+ // route to the wrong listener, swallowing track transitions on
1059
+ // the new leading leg.
1060
+ //
1061
+ // Threading: this method runs from the runFade coroutine on
1062
+ // Dispatchers.Main, which is also the application looper for
1063
+ // both ExoPlayer instances. addListener / removeListener +
1064
+ // CrossfadeForwardingPlayer.setPlayer (via onRoleSwap) all
1065
+ // require the application looper.
1066
+ val oldLeading = leadingPlayer
1067
+ val oldStandby = standbyPlayer
1068
+ oldLeading.removeListener(leadingPlayerListener)
1069
+ oldStandby.removeListener(standbyPlayerListener)
1070
+ currentRoleIsA = !currentRoleIsA
1071
+ leadingPlayer.addListener(leadingPlayerListener)
1072
+ standbyPlayer.addListener(standbyPlayerListener)
1073
+ val newStandby = standbyPlayer
1074
+ newStandby.stop()
1075
+ newStandby.clearMediaItems()
1076
+ newStandby.volume = 0f
1077
+ standbyArmed = false
1078
+ // Notify the MediaSession-binding wrapper so the lock-screen
1079
+ // scrubber retargets to the now-leading leg.
1080
+ onRoleSwap?.invoke()
1081
+ }
1082
+
1083
+ /**
1084
+ * Boundary-arming position-poll. Runs every
1085
+ * [POSITION_POLL_INTERVAL_MS] while playback is active. When the
1086
+ * leading leg's `currentPosition` approaches
1087
+ * `duration - effectiveCrossfadeMs - PREROLL_LEAD_MS`, prerolls
1088
+ * standby with the next item from the leading leg's queue and
1089
+ * fires [runFade].
1090
+ *
1091
+ * Cancellation: `pause` / `stop` / `seekTo` / `skipToNext` /
1092
+ * `skipToPrevious` / `release` all stop the poll. `play` restarts
1093
+ * it. The poll itself cancels when the engine's coroutine scope
1094
+ * is cancelled (in `release`).
1095
+ */
1096
+ private fun startArmingPoll() {
1097
+ if (armingJob?.isActive == true) return
1098
+ armingJob = engineScope.launch {
1099
+ while (isActive) {
1100
+ delay(POSITION_POLL_INTERVAL_MS)
1101
+ try {
1102
+ maybeArmCrossfade()
1103
+ } catch (_: IllegalStateException) {
1104
+ // ExoPlayer state read off main looper or post-release;
1105
+ // skip this tick. The next tick will re-evaluate.
1106
+ }
1107
+ }
1108
+ }
1109
+ }
1110
+
1111
+ private fun stopArmingPoll() {
1112
+ val job = armingJob
1113
+ job?.cancel()
1114
+ armingJob = null
1115
+ }
1116
+
1117
+ /**
1118
+ * Decide whether to arm the standby preroll + run the fade based
1119
+ * on the leading leg's current position relative to its
1120
+ * track-end. Idempotent — repeat fires within the same boundary
1121
+ * window are no-ops because [standbyArmed] tracks per-track.
1122
+ */
1123
+ private fun maybeArmCrossfade() {
1124
+ if (standbyArmed) return
1125
+ if (fadeJob?.isActive == true) return
1126
+ if (!leadingPlayer.isPlaying) return
1127
+ if (crossfadeDurationMs <= 0L) return
1128
+ // Repeat-one loops the current item natively (REPEAT_MODE_ONE on the
1129
+ // leading leg). Never arm a look-ahead fade, which would advance past
1130
+ // the track the user asked to repeat — matches the gapless engine,
1131
+ // where the same native repeat loops the item in place.
1132
+ if (leadingPlayer.repeatMode == Player.REPEAT_MODE_ONE) return
1133
+ val currentIdx = leadingPlayer.currentMediaItemIndex
1134
+ val itemCount = leadingPlayer.mediaItemCount
1135
+ if (currentIdx < 0 || currentIdx >= itemCount - 1) return // last track or empty
1136
+ val duration = leadingPlayer.duration
1137
+ if (duration == C.TIME_UNSET || duration <= 0L) return
1138
+ val position = leadingPlayer.currentPosition
1139
+ // Best-effort lookahead: leading's queue has the next item but
1140
+ // its duration isn't known until prepared. Passing 0 falls
1141
+ // through to the configured value via [effectiveCrossfadeMs]
1142
+ // with the leading-half clamp only.
1143
+ val standbyDurationMs = 0L
1144
+ val effective = effectiveCrossfadeMs(duration, standbyDurationMs)
1145
+ val armThreshold = duration - effective - PREROLL_LEAD_MS
1146
+ if (position < armThreshold) return
1147
+ standbyArmed = true
1148
+ armCrossfade(effective)
1149
+ }
1150
+
1151
+ /**
1152
+ * Preroll the standby leg with the leading leg's tail (next item
1153
+ * onward) so Media3 auto-advance can take over after the fade
1154
+ * completes + role swap, then start the fade ramp.
1155
+ */
1156
+ private fun armCrossfade(durationMs: Long) {
1157
+ val nextIdx = leadingPlayer.currentMediaItemIndex + 1
1158
+ val itemCount = leadingPlayer.mediaItemCount
1159
+ if (nextIdx >= itemCount) {
1160
+ standbyArmed = false
1161
+ return
1162
+ }
1163
+ // Load the FULL queue onto standby (not just the tail) so the
1164
+ // standby's `currentMediaItemIndex` is in the same global index
1165
+ // space as the consumer-supplied queue. After [swapRoles] flips
1166
+ // standby into leading, JS-facing reads of `currentMediaItemIndex`
1167
+ // remain meaningful and the lock-screen / Android Auto scrubber
1168
+ // sees the right "track N of M" — loading a tail with startIndex=0
1169
+ // collapses the index to 0 every swap.
1170
+ val full = ArrayList<MediaItem>(itemCount)
1171
+ for (i in 0 until itemCount) full.add(leadingPlayer.getMediaItemAt(i))
1172
+ standbyPlayer.setMediaItems(full, /* startIndex = */ nextIdx, /* startPositionMs = */ 0L)
1173
+ standbyPlayer.prepare()
1174
+ standbyPlayer.volume = 0f
1175
+ standbyPlayer.play()
1176
+ // Tiny settle so the standby's audio output graph is hot when
1177
+ // the volume ramp begins. The N-tick poll catches the case
1178
+ // where standby buffering is slow + falls back to STATE_ENDED
1179
+ // safety on the leading leg.
1180
+ engineScope.launch {
1181
+ delay(PREROLL_SETTLE_MS)
1182
+ runFade(durationMs)
1183
+ }
1184
+ }
1185
+
1186
+ /**
1187
+ * Schedule the equal-power fade ramp between [leadingPlayer] and
1188
+ * [standbyPlayer] over [durationMs] wall-clock. Caller (the
1189
+ * boundary-arming poll on `TrackPlayer`) prerolls the standby
1190
+ * leg and starts its playback at volume 0 before invoking.
1191
+ * Coroutine on `Dispatchers.Main` at 20ms tick; pause naturally
1192
+ * halts via `playWhenReady=false` because the leading player's
1193
+ * `isPlaying` flips false.
1194
+ */
1195
+ private fun runFade(durationMs: Long) {
1196
+ // Cancel any prior in-flight ramp coroutine. Do NOT call
1197
+ // [cancelFade] here — it would also `clearMediaItems()` on the
1198
+ // standby leg, destroying the preroll [armCrossfade] just set up
1199
+ // and forcing an early-return below.
1200
+ fadeJob?.cancel()
1201
+ fadeJob = null
1202
+ // Standby must already hold the next item — caller prerolls
1203
+ // before invoking. Defensive guard: nothing prepared, nothing
1204
+ // to swap to. Reset `standbyArmed` so the next [maybeArmCrossfade]
1205
+ // tick can re-arm cleanly if a future caller invokes runFade
1206
+ // without an intervening [swapRoles].
1207
+ if (standbyPlayer.mediaItemCount == 0) {
1208
+ standbyArmed = false
1209
+ return
1210
+ }
1211
+ if (durationMs <= 0L) {
1212
+ // Hard-cut path — no perceptible fade requested. Snap
1213
+ // volumes + swap roles synchronously, preserving the
1214
+ // user's volume choice on the new leading leg.
1215
+ leadingPlayer.volume = 0f
1216
+ standbyPlayer.volume = effectiveUserVolume()
1217
+ swapRoles()
1218
+ return
1219
+ }
1220
+ val durationNs = durationMs * 1_000_000L
1221
+ val startNs = System.nanoTime()
1222
+ val incomingIdx = standbyPlayer.currentMediaItemIndex
1223
+ fadeJob = engineScope.launch {
1224
+ while (isActive) {
1225
+ val elapsedNs = System.nanoTime() - startNs
1226
+ val t = (elapsedNs.toFloat() / durationNs.toFloat()).coerceIn(0f, 1f)
1227
+ val (outVol, inVol) = equalPowerGains(t)
1228
+ // [effectiveUserVolume] honours an in-flight focus duck so
1229
+ // the fade ramp doesn't overwrite the duck on the next tick.
1230
+ val target = effectiveUserVolume()
1231
+ leadingPlayer.volume = outVol * target
1232
+ standbyPlayer.volume = inVol * target
1233
+ if (t >= 1f) break
1234
+ delay(20L)
1235
+ }
1236
+ // Fade complete — promote standby to leading at the
1237
+ // user's chosen (duck-aware) volume; the swap below resets
1238
+ // standby volume to 0.
1239
+ leadingPlayer.volume = 0f
1240
+ standbyPlayer.volume = effectiveUserVolume()
1241
+ swapRoles()
1242
+ fadeJob = null
1243
+ }
1244
+ // Active-track flip: standby leg has launched its fade-in (the
1245
+ // launch above schedules the coroutine onto Dispatchers.Main —
1246
+ // the assignment to `fadeJob` already published the in-flight
1247
+ // marker so the protocol accessors retarget to the standby leg
1248
+ // for any state read the delegate triggers here). Re-bind the
1249
+ // forwarding wrapper to the standby `ExoPlayer` so MediaSession's
1250
+ // auto-published metadata + scrubber flip to the incoming
1251
+ // track from 00:00 the moment it begins audibly playing. Then
1252
+ // notify the delegate to fire JS-facing `onTrackChange` +
1253
+ // refresh `MediaSessionCompat` extras.
1254
+ onCrossfadeBegin?.invoke()
1255
+ delegate?.onCrossfadeBegin(this, incomingIdx)
1256
+ }
1257
+
1258
+ // --- Builders ---
1259
+
1260
+ private fun buildAudioAttributes(): AudioAttributes {
1261
+ val contentType = if (audioContentType == AudioContentType.SPEECH) {
1262
+ C.AUDIO_CONTENT_TYPE_SPEECH
1263
+ } else {
1264
+ C.AUDIO_CONTENT_TYPE_MUSIC
1265
+ }
1266
+ return AudioAttributes.Builder()
1267
+ .setUsage(C.USAGE_MEDIA)
1268
+ .setContentType(contentType)
1269
+ .build()
1270
+ }
1271
+
1272
+ /**
1273
+ * Platform [android.media.AudioAttributes] that mirrors the
1274
+ * Media3 [AudioAttributes] above. The platform type is what
1275
+ * [AudioFocusRequest.Builder.setAudioAttributes] consumes;
1276
+ * we construct it directly rather than reaching into Media3's
1277
+ * deprecated `audioAttributesV21` accessor.
1278
+ */
1279
+ private fun buildPlatformAudioAttributes(): android.media.AudioAttributes {
1280
+ val contentType = if (audioContentType == AudioContentType.SPEECH) {
1281
+ android.media.AudioAttributes.CONTENT_TYPE_SPEECH
1282
+ } else {
1283
+ android.media.AudioAttributes.CONTENT_TYPE_MUSIC
1284
+ }
1285
+ return android.media.AudioAttributes.Builder()
1286
+ .setUsage(android.media.AudioAttributes.USAGE_MEDIA)
1287
+ .setContentType(contentType)
1288
+ .build()
1289
+ }
1290
+
1291
+ private fun buildPlayer(isStandby: Boolean, renderersFactory: RenderersFactory): ExoPlayer {
1292
+ val builder = ExoPlayer.Builder(context)
1293
+ builder.setRenderersFactory(renderersFactory)
1294
+ val factory = mediaSourceFactoryProvider?.invoke()
1295
+ if (factory != null) {
1296
+ builder.setMediaSourceFactory(factory)
1297
+ }
1298
+ val loadControl: LoadControl = DefaultLoadControl.Builder()
1299
+ .setBufferDurationsMs(
1300
+ if (isStandby) STANDBY_MIN_BUFFER_MS else DEFAULT_MIN_BUFFER_MS,
1301
+ if (isStandby) STANDBY_MAX_BUFFER_MS else DEFAULT_MAX_BUFFER_MS,
1302
+ if (isStandby) STANDBY_BUFFER_FOR_PLAYBACK_MS else DEFAULT_BUFFER_FOR_PLAYBACK_MS,
1303
+ if (isStandby) STANDBY_BUFFER_FOR_PLAYBACK_AFTER_REBUFFER_MS
1304
+ else DEFAULT_BUFFER_FOR_PLAYBACK_AFTER_REBUFFER_MS,
1305
+ )
1306
+ .build()
1307
+ builder.setLoadControl(loadControl)
1308
+ val player = builder.build()
1309
+ player.pauseAtEndOfMediaItems = false
1310
+ player.setAudioAttributes(buildAudioAttributes(), /* handleAudioFocus = */ false)
1311
+ player.setHandleAudioBecomingNoisy(true)
1312
+ player.setWakeMode(C.WAKE_MODE_NETWORK)
1313
+ return player
1314
+ }
1315
+
1316
+ internal companion object {
1317
+ // Defaults match Media3 DefaultLoadControl.
1318
+ internal const val DEFAULT_MIN_BUFFER_MS: Int = 50_000
1319
+ internal const val DEFAULT_MAX_BUFFER_MS: Int = 50_000
1320
+ internal const val DEFAULT_BUFFER_FOR_PLAYBACK_MS: Int = 1_000
1321
+ internal const val DEFAULT_BUFFER_FOR_PLAYBACK_AFTER_REBUFFER_MS: Int = 2_000
1322
+
1323
+ // Standby leg: keep just enough for a few seconds of preroll
1324
+ // so it doesn't compete with the leading leg's lookahead
1325
+ // cache for memory headroom.
1326
+ internal const val STANDBY_MIN_BUFFER_MS: Int = 15_000
1327
+ internal const val STANDBY_MAX_BUFFER_MS: Int = 15_000
1328
+ internal const val STANDBY_BUFFER_FOR_PLAYBACK_MS: Int = 2_000
1329
+ internal const val STANDBY_BUFFER_FOR_PLAYBACK_AFTER_REBUFFER_MS: Int = 2_000
1330
+
1331
+ // Volume multiplier applied during AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK.
1332
+ // Matches Media3's `AudioFocusManager` default duck behaviour.
1333
+ internal const val DUCK_MULTIPLIER: Float = 0.2f
1334
+
1335
+ /** Boundary-arming poll cadence. 200ms is a good balance between
1336
+ * responsiveness (we won't miss the arm window even on a 12s
1337
+ * fade) and battery cost. */
1338
+ internal const val POSITION_POLL_INTERVAL_MS: Long = 200L
1339
+
1340
+ /** Lead time before fade-start to begin standby preroll. The
1341
+ * AudioSink needs ~50-100ms to warm up; 500ms gives comfortable
1342
+ * margin without the standby being ready way too early. */
1343
+ internal const val PREROLL_LEAD_MS: Long = 500L
1344
+
1345
+ /** Settle delay between standby.play() and fade-ramp start.
1346
+ * Lets the AudioSink ready up so the first ramp tick lands on
1347
+ * audible bytes. */
1348
+ internal const val PREROLL_SETTLE_MS: Long = 150L
1349
+ }
1350
+ }