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,1343 @@
1
+ import AVFoundation
2
+ import Foundation
3
+
4
+ /// Dual-`AVPlayer` engine implementing equal-power crossfade at
5
+ /// track boundaries.
6
+ ///
7
+ /// Two `AVPlayer` instances rotate roles per fade: the leading
8
+ /// leg is currently audible; the standby leg prerolls the next
9
+ /// queue item ahead of the fade window and ramps up from silence
10
+ /// as the leading ramps down.
11
+ ///
12
+ /// Architecture (per platform research):
13
+ /// - Single-item per `AVPlayer` (NOT `AVQueuePlayer`) so each
14
+ /// leg's `AVMutableAudioMixInputParameters.setVolumeRamp` is
15
+ /// independently scheduled. The lib-side queue model on
16
+ /// `TrackPlayer` is the canonical position; the engine
17
+ /// advances the standby leg's currentItem to the next queue
18
+ /// position ahead of fade-start.
19
+ /// - Equal-power curve approximated via N short linear
20
+ /// `setVolumeRamp` sub-ramps. `setVolumeRamp` is linear-only
21
+ /// per the AVFoundation API; ~50 sub-ramps over a fade window
22
+ /// is auditorily indistinguishable from true `cos(t·π/2)` /
23
+ /// `sin(t·π/2)`.
24
+ /// - Standby preroll via `AVPlayer.preroll(atRate: 1.0)` ~500ms
25
+ /// before fade-start so the audio output graph is hot when
26
+ /// its volume ramp begins.
27
+ /// - Backward seek through a scheduled ramp window corrupts the
28
+ /// mix per Wade Tregaskis's `setVolumeRamp` findings —
29
+ /// recovery is `audioMix = nil` + `volume = userVolume`.
30
+ /// - Per-boundary route check via `OutputRouteMonitor`: if the
31
+ /// active route is `.airPlay` / `.carAudio`, the boundary
32
+ /// hard-cuts (no fade) for that transition. Mid-fade route
33
+ /// change cancels the fade synchronously.
34
+ ///
35
+ /// Runtime fade execution (multi-second `setVolumeRamp` schedule
36
+ /// + standby promotion to leading at fade-end) is exercised at
37
+ /// the demo-app integration layer; the engine's deterministic
38
+ /// primitives (curve math, sub-ramp count, route classification,
39
+ /// boundary fade-vs-cut decision) are unit-tested.
40
+ final class CrossfadeEngine: PlaybackEngine {
41
+
42
+ // MARK: - Construction
43
+
44
+ /// User-set fade duration captured at construction time. Both
45
+ /// `AVAudioMix` ramp scheduling and the role-swap timer
46
+ /// coordinate against this value; runtime duration changes
47
+ /// require a fresh engine instance via `handoff`.
48
+ private let crossfadeDurationSeconds: TimeInterval
49
+
50
+ /// Pre-fade preroll lead so the standby leg's audio output
51
+ /// graph is hot when its first ramp starts. 500ms matches the
52
+ /// platform research recommendation.
53
+ static let prerollLeadSeconds: TimeInterval = 0.5
54
+
55
+ /// Equal-power approximation step count. ~50 sub-ramps over a
56
+ /// 6-second fade is below the audibility threshold for the
57
+ /// difference between staircased and continuous cos/sin.
58
+ static let subRampCount: Int = 50
59
+
60
+ /// Volume multiplier applied to both legs during the fade.
61
+ /// Tracked so manual `setVolume(v)` survives a subsequent
62
+ /// fade cancel / handoff.
63
+ private var userVolume: Float = 1.0
64
+
65
+ /// Tracked so the user's playback speed survives a crossfade
66
+ /// transition: the standby leg prerolls/plays at the configured
67
+ /// rate and is re-set to this when promoted to leading. Without it
68
+ /// every fade resets the rate to 1.0.
69
+ private var userPlaybackSpeed: Float = 1.0
70
+
71
+ /// Persisted pitch-correction mode, stamped as `audioTimePitchAlgorithm`
72
+ /// on both legs' items. The resolved algorithm depends on
73
+ /// `userPlaybackSpeed` (the intended rate), not the live leg rate
74
+ /// (0 while paused / on the silent standby).
75
+ private var pitchCorrectionMode: PitchCorrectionMode = .voice
76
+
77
+ weak var delegate: PlaybackEngineDelegate?
78
+
79
+ /// Owns the route monitor instead of relying on a shared one
80
+ /// — the engine starts/stops monitoring with its own
81
+ /// lifecycle.
82
+ private let routeMonitor: OutputRouteMonitor
83
+
84
+ // MARK: - Players
85
+
86
+ private let playerA: AVPlayer
87
+ private let playerB: AVPlayer
88
+
89
+ /// `true` when [leadingPlayer] is `playerA` (the engine's
90
+ /// first-built player). Flips on every fade-complete role
91
+ /// swap. Read by the test surface to verify role-swap
92
+ /// arithmetic without driving a real fade.
93
+ private(set) var currentRoleIsA: Bool = true
94
+
95
+ /// Leading leg — currently audible.
96
+ var leadingPlayer: AVPlayer { currentRoleIsA ? playerA : playerB }
97
+
98
+ /// Standby leg — prerolls the next queue item ahead of fade-start.
99
+ var standbyPlayer: AVPlayer { currentRoleIsA ? playerB : playerA }
100
+
101
+ // MARK: - Queue model
102
+
103
+ /// Engine-internal queue snapshot — caller sets via
104
+ /// `setItems`; engine advances `currentIndex` on user skip /
105
+ /// auto-advance. Each `AVPlayer` instance holds at most one
106
+ /// item from this list at a time.
107
+ private var queue: [AVPlayerItem] = []
108
+ private var currentIndex: Int = -1
109
+
110
+ /// Active repeat mode. AVPlayer has no native repeat, so the engine
111
+ /// implements repeat-one itself: it suppresses the look-ahead fade
112
+ /// and loops the current item on natural end (see `maybeArmCrossfade`
113
+ /// + `handleItemDidPlayToEnd`). `.queue` wrap is driven by TrackPlayer
114
+ /// rebuilding the queue, same as the gapless engine.
115
+ private var repeatMode: RepeatMode = .off
116
+
117
+ /// `true` while a fade ramp is scheduled / in flight.
118
+ private var fadeInFlight: Bool = false
119
+
120
+ /// Periodic-time-observer + the AVPlayer it was registered
121
+ /// against. `AVPlayer.removeTimeObserver` raises
122
+ /// `NSInvalidArgumentException` when called on a different
123
+ /// instance than the one that issued the token, so the player
124
+ /// is captured alongside the token. Removed on pause / stop /
125
+ /// seek / skip / role-swap / release; re-installed on play.
126
+ private var armingObserver: (player: AVPlayer, token: Any)?
127
+
128
+ /// `true` after [armCrossfade] has prerolled standby for the
129
+ /// upcoming fade.
130
+ private var standbyArmed: Bool = false
131
+
132
+ /// Wall-clock task that fires `completeCrossfade` after the
133
+ /// fade duration. Stored so `cancelFadeInternal` /
134
+ /// `release` can cancel it before a stale completion runs
135
+ /// against a fresh fade.
136
+ private var fadeCompletionTask: Task<Void, Never>?
137
+
138
+ /// Audio-mix provider supplied by `Equalizer` (and future
139
+ /// `Visualizer`). Per-AVPlayerItem `AVAudioMix` is built
140
+ /// per-item via the provider's `audioMix(for:)`.
141
+ private var mixProvider: AudioMixProvider?
142
+
143
+ /// Resolves a track's source URL to its lookahead-cache local file
144
+ /// URL when fully cached, else nil. Supplied by `TrackPlayer` (reads
145
+ /// `LookaheadCache.cachedURL(forUrl:)` lazily so it always sees the
146
+ /// current cache). The engine re-resolves at every late item attach
147
+ /// (skip cross-attach, fade-arm preroll) so a track that finished
148
+ /// caching AFTER its queue item was first built from the remote URL
149
+ /// is played from the local file — instead of re-loading the remote
150
+ /// asset, whose `.tracks` round-trip can fail the now-playing format
151
+ /// extractor.
152
+ private var cachedURLResolver: ((String) -> URL?)?
153
+
154
+ /// Released-once flag so `release()` is idempotent.
155
+ private var released: Bool = false
156
+
157
+ /// One-shot KVO on the standby `AVPlayer.status`. Set during
158
+ /// [armCrossfade] when `replaceCurrentItem` was just called and
159
+ /// the asset hasn't reached `.readyToPlay` yet — `preroll(atRate:)`
160
+ /// raises `NSInternalInconsistencyException` if invoked before
161
+ /// the status flip per `AVPlayer.h`. Invalidated on
162
+ /// [cancelFadeInternal] / [release] / when the readiness fires.
163
+ private var standbyReadyObserver: NSKeyValueObservation?
164
+
165
+ /// Wall-clock fallback used when standby never reaches
166
+ /// `.readyToPlay` (asset load failure / network error). Lets the
167
+ /// arm path bail cleanly instead of stranding `standbyArmed = true`
168
+ /// against a broken standby. 5s covers local + warm cache; for
169
+ /// streaming the consumer would have already failed by then via
170
+ /// the leading-leg error path.
171
+ private var standbyReadyTimeout: DispatchWorkItem?
172
+
173
+ /// Generation counter incremented at every [awaitStandbyReady]
174
+ /// entry. Closures captured by the KVO observer + the timeout
175
+ /// `DispatchWorkItem` carry their generation value — if a new
176
+ /// arm cycle increments the counter while a stale main-async
177
+ /// hop is pending, the gate inside the closure short-circuits.
178
+ /// Defends against a narrow race where the original arm's
179
+ /// `.readyToPlay` callback fires AFTER `cancelFadeInternal` +
180
+ /// a fresh `armCrossfade` re-flipped `standbyArmed` to true.
181
+ private var standbyReadyGen: Int = 0
182
+
183
+ // MARK: - Engine event observers
184
+
185
+ /// `\.timeControlStatus` KVO on the leading leg + the player it
186
+ /// was registered against. Re-installed on every role swap.
187
+ /// Fires `engineStateMaybeChanged` + `engineIsPlayingChanged`.
188
+ private var leadingTimeControlObserver: NSKeyValueObservation?
189
+
190
+ /// `\.currentItem.tracks` KVO on the leading leg's currentItem.
191
+ /// Fires `engineActiveItemFormatChanged` once tracks populate.
192
+ /// Re-installed on role swap and on `setItems`.
193
+ private var leadingItemTracksObserver: NSKeyValueObservation?
194
+
195
+ /// `\.currentItem.status` KVO on the leading leg's currentItem.
196
+ /// Routes `.failed` through `engineDidFailWithError`.
197
+ private var leadingItemStatusObserver: NSKeyValueObservation?
198
+
199
+ /// Block-based `NotificationCenter` observer tokens for the
200
+ /// AVPlayerItem lifecycle notifications. Filtered inside the
201
+ /// block to leading-leg only. Removed in `release`.
202
+ private var itemDidPlayToEndToken: NSObjectProtocol?
203
+ private var itemFailedToPlayToEndToken: NSObjectProtocol?
204
+
205
+ // MARK: - Init
206
+
207
+ init(crossfadeDurationSeconds: TimeInterval) {
208
+ precondition(
209
+ crossfadeDurationSeconds >= 0,
210
+ "crossfadeDurationSeconds must be non-negative"
211
+ )
212
+ self.crossfadeDurationSeconds = crossfadeDurationSeconds
213
+
214
+ let p1 = AVPlayer()
215
+ p1.automaticallyWaitsToMinimizeStalling = true
216
+ p1.volume = userVolume
217
+ let p2 = AVPlayer()
218
+ p2.automaticallyWaitsToMinimizeStalling = true
219
+ p2.volume = 0 // standby starts silent
220
+
221
+ self.playerA = p1
222
+ self.playerB = p2
223
+
224
+ let monitor = OutputRouteMonitor()
225
+ self.routeMonitor = monitor
226
+ monitor.start()
227
+ monitor.onRouteBecameNonMixable = { [weak self] in
228
+ // Mid-fade route change: cancel the in-flight fade so iOS
229
+ // doesn't arbitrarily silence one of the two players. The
230
+ // outgoing leg snaps to userVolume; the standby drops its
231
+ // item.
232
+ DispatchQueue.main.async { [weak self] in
233
+ self?.cancelFade()
234
+ }
235
+ }
236
+
237
+ // Lib-wide notifications fire for any AVPlayerItem; the
238
+ // closure filters by `object === leadingPlayer.currentItem`
239
+ // so events on the standby leg's preroll item don't surface.
240
+ itemDidPlayToEndToken = NotificationCenter.default.addObserver(
241
+ forName: .AVPlayerItemDidPlayToEndTime,
242
+ object: nil,
243
+ queue: .main
244
+ ) { [weak self] note in
245
+ self?.handleItemDidPlayToEnd(note)
246
+ }
247
+ itemFailedToPlayToEndToken = NotificationCenter.default.addObserver(
248
+ forName: .AVPlayerItemFailedToPlayToEndTime,
249
+ object: nil,
250
+ queue: .main
251
+ ) { [weak self] note in
252
+ self?.handleItemFailedToPlayToEnd(note)
253
+ }
254
+
255
+ // iOS 26+ AVRoutingPlaybackArbiter would let the engine name
256
+ // the preferred participant for non-mixable routes (AirPlay
257
+ // 2 / wireless CarPlay) so iOS doesn't arbitrarily silence
258
+ // one of two playing AVPlayer instances during the
259
+ // engagement transient. The current iOS SDK in this build
260
+ // ships AVRoutingPlaybackArbiter but the
261
+ // `preferredParticipantForNonMixableAudioRoutes` property
262
+ // marker is unavailable on iOS at the SDK header level —
263
+ // tracked as a follow-up once the SDK exposes it on iOS or
264
+ // an alternative API surface lands.
265
+ }
266
+
267
+ /// No-op placeholder — see init comment for the iOS 26+
268
+ /// AVRoutingPlaybackArbiter follow-up.
269
+ private func updateRoutingArbiter() {
270
+ // Intentional no-op pending SDK availability.
271
+ }
272
+
273
+ // MARK: - Lifecycle
274
+
275
+ func prepare(
276
+ items: [AVPlayerItem],
277
+ startIndex: Int,
278
+ startPositionSeconds: TimeInterval
279
+ ) async {
280
+ setItems(items, startIndex: startIndex, startPositionSeconds: startPositionSeconds)
281
+ }
282
+
283
+ func release() {
284
+ guard !released else { return }
285
+ released = true
286
+ // Release runs as part of an engine swap or destroy; the new
287
+ // engine has already taken over the canonical active-track
288
+ // state, so a mid-fade revert emit here would surface a
289
+ // spurious onTrackChange to the OUTGOING leg of a fade that
290
+ // the consumer no longer cares about.
291
+ cancelFadeInternal(emitRevert: false)
292
+ stopArmingObserver()
293
+ teardownLeadingObservers()
294
+ if let token = itemDidPlayToEndToken {
295
+ NotificationCenter.default.removeObserver(token)
296
+ itemDidPlayToEndToken = nil
297
+ }
298
+ if let token = itemFailedToPlayToEndToken {
299
+ NotificationCenter.default.removeObserver(token)
300
+ itemFailedToPlayToEndToken = nil
301
+ }
302
+ routeMonitor.stop()
303
+ leadingPlayer.replaceCurrentItem(with: nil)
304
+ standbyPlayer.replaceCurrentItem(with: nil)
305
+ queue.removeAll()
306
+ currentIndex = -1
307
+ mixProvider = nil
308
+ delegate = nil
309
+ }
310
+
311
+ // MARK: - Queue mutation
312
+
313
+ func setItems(
314
+ _ items: [AVPlayerItem],
315
+ startIndex: Int,
316
+ startPositionSeconds: TimeInterval
317
+ ) {
318
+ cancelFadeInternal()
319
+ queue = items
320
+ teardownLeadingObservers()
321
+ if items.isEmpty || startIndex < 0 || startIndex >= items.count {
322
+ currentIndex = -1
323
+ leadingPlayer.replaceCurrentItem(with: nil)
324
+ standbyPlayer.replaceCurrentItem(with: nil)
325
+ return
326
+ }
327
+ currentIndex = startIndex
328
+ let activeItem = items[startIndex]
329
+ applyMixIfNeeded(to: activeItem)
330
+ applyPitchAlgorithm(to: activeItem)
331
+ leadingPlayer.replaceCurrentItem(with: activeItem)
332
+ standbyPlayer.replaceCurrentItem(with: nil)
333
+ if startPositionSeconds > 0 {
334
+ activeItem.seek(
335
+ to: CMTime(seconds: startPositionSeconds, preferredTimescale: 600),
336
+ completionHandler: nil
337
+ )
338
+ }
339
+ installLeadingObservers()
340
+ updateRoutingArbiter()
341
+ delegate?.engineDidTransitionTrack(self)
342
+ }
343
+
344
+ @discardableResult
345
+ func insertItems(
346
+ _ items: [AVPlayerItem],
347
+ after: AVPlayerItem?
348
+ ) -> Bool {
349
+ if items.isEmpty { return true }
350
+ // Queue mutation invalidates the standby leg's pre-loaded
351
+ // future. Cancel any in-flight fade before mutating so the
352
+ // standby's stale state doesn't race a swap against the
353
+ // post-mutation index space.
354
+ cancelFadeInternal()
355
+ let insertOffset: Int
356
+ if let after, let idx = queue.firstIndex(where: { $0 === after }) {
357
+ insertOffset = idx + 1
358
+ } else if after == nil {
359
+ insertOffset = queue.count
360
+ } else {
361
+ // Reference item not in the engine's queue — fall back to
362
+ // a full rebuild signal so the caller can call setItems.
363
+ return false
364
+ }
365
+ queue.insert(contentsOf: items, at: insertOffset)
366
+ return true
367
+ }
368
+
369
+ func remove(_ item: AVPlayerItem) {
370
+ guard let idx = queue.firstIndex(where: { $0 === item }) else { return }
371
+ cancelFadeInternal()
372
+ queue.remove(at: idx)
373
+ if idx == currentIndex {
374
+ // Removing the leading leg's current item — auto-advance
375
+ // to whatever follows or drain.
376
+ if currentIndex >= queue.count {
377
+ currentIndex = queue.count - 1
378
+ }
379
+ if currentIndex < 0 {
380
+ leadingPlayer.replaceCurrentItem(with: nil)
381
+ } else {
382
+ let next = queue[currentIndex]
383
+ applyMixIfNeeded(to: next)
384
+ applyPitchAlgorithm(to: next)
385
+ leadingPlayer.replaceCurrentItem(with: next)
386
+ }
387
+ } else if idx < currentIndex {
388
+ currentIndex -= 1
389
+ }
390
+ }
391
+
392
+ func removeAllItems() {
393
+ cancelFadeInternal()
394
+ queue.removeAll()
395
+ currentIndex = -1
396
+ leadingPlayer.replaceCurrentItem(with: nil)
397
+ standbyPlayer.replaceCurrentItem(with: nil)
398
+ }
399
+
400
+ func canInsert(_ item: AVPlayerItem, after: AVPlayerItem?) -> Bool {
401
+ if let after {
402
+ return queue.contains(where: { $0 === after })
403
+ }
404
+ return true // append-at-end always permitted
405
+ }
406
+
407
+ // MARK: - Transport
408
+
409
+ func play() {
410
+ // Resume at the user's speed (AVPlayer.play() resets rate to 1.0).
411
+ leadingPlayer.rate = userPlaybackSpeed
412
+ startArmingObserver()
413
+ }
414
+
415
+ func pause() {
416
+ cancelFadeInternal()
417
+ stopArmingObserver()
418
+ leadingPlayer.pause()
419
+ standbyPlayer.pause()
420
+ }
421
+
422
+ func stop() {
423
+ cancelFadeInternal()
424
+ stopArmingObserver()
425
+ leadingPlayer.pause()
426
+ standbyPlayer.pause()
427
+ // Match GaplessEngine.stop(): pause + seek the CURRENT (leading) item to 0
428
+ // and KEEP it. Replacing it with nil leaves no currentItem — so position
429
+ // never resets to observe, the periodic time observer never fires the
430
+ // post-stop progress tick consumers wait for, and getState() drops to NONE
431
+ // instead of PAUSED. Drain only the standby (prerolled next-track) leg;
432
+ // it's stale once stopped and re-arms on the next play.
433
+ leadingPlayer.currentItem?.seek(to: .zero, completionHandler: nil)
434
+ standbyPlayer.replaceCurrentItem(with: nil)
435
+ }
436
+
437
+ func seek(toIndex index: Int, position: TimeInterval) {
438
+ guard index >= 0, index < queue.count else { return }
439
+ // Capture playing intent before the fade-cancel: a cross-attach
440
+ // (replaceCurrentItem) drops the leading player to rate 0, so the
441
+ // new leg must be resumed at the user's speed below to match the
442
+ // gapless skip (which restores rate across its queue rebuild).
443
+ let wasPlaying = isPlaying
444
+ // Seek is itself a track-change: the engineDidTransitionTrack
445
+ // fire at the end of this method is the authoritative active-
446
+ // track flip for the new index. Suppress the cancel-revert
447
+ // emit so a mid-fade seek doesn't dispatch an intermediate
448
+ // engineCrossfadeDidCancel(revertedIndex: outgoing) event
449
+ // before the seek's own track-change lands.
450
+ cancelFadeInternal(emitRevert: false)
451
+ teardownLeadingObservers()
452
+ currentIndex = index
453
+ let existing = queue[index]
454
+ // Same-instance no-op: target is already leadingPlayer's
455
+ // currentItem (seek-within-current-track, or seekTo right
456
+ // after setItems). Calling replaceCurrentItem with the same
457
+ // instance triggers a redundant KVO cascade and delays
458
+ // duration re-propagation by seconds; skip the re-attach.
459
+ if leadingPlayer.currentItem === existing {
460
+ if position > 0 {
461
+ existing.seek(
462
+ to: CMTime(seconds: position, preferredTimescale: 600),
463
+ completionHandler: nil
464
+ )
465
+ } else {
466
+ // Same-instance keeps any prior playhead; force-reset to
467
+ // zero to honour the seek contract.
468
+ existing.seek(to: .zero, completionHandler: nil)
469
+ }
470
+ standbyArmed = false
471
+ installLeadingObservers()
472
+ updateRoutingArbiter()
473
+ delegate?.engineDidTransitionTrack(self)
474
+ return
475
+ }
476
+ // Cross-attach case: target is associated with another
477
+ // AVPlayer (typically standbyPlayer post fade-arm). Rebuild
478
+ // as a fresh AVPlayerItem on the existing asset.
479
+ // AVPlayer.replaceCurrentItem(with:) raises NSException
480
+ // (uncatchable in Swift → process abort) if the item is still
481
+ // associated with another AVPlayer; AVPlayerItem.player
482
+ // releases asynchronously after the previous player calls
483
+ // replaceCurrentItem(with: nil) and there's no synchronous
484
+ // way to wait for the release, no public API to inspect the
485
+ // association. Mirror AVQueueBuilder.makeItem's construction
486
+ // (`automaticallyLoadedAssetKeys` + buffer pin) and carry
487
+ // queueItemId across so TrackPlayer.matchTrackIndex can still
488
+ // resolve the new item back to its queue position.
489
+ let target = AVPlayerItem(
490
+ // Prefer the lookahead cache's local file when the track has
491
+ // cached since the queue item was built from its remote URL —
492
+ // otherwise this fresh item re-loads the remote asset and the
493
+ // `.tracks` round-trip can fail the now-playing format extractor.
494
+ asset: cacheResolvedAsset(for: existing),
495
+ // Mirror AVQueueBuilder.makeItem fully — including "tracks". A forward
496
+ // skip to a cached track rebuilds the incoming leg here; without the
497
+ // tracks key auto-loading, the `.new`-only tracks KVO never fires for
498
+ // the fresh item and the now-playing format never resolves.
499
+ automaticallyLoadedAssetKeys: ["playable", "duration", "tracks"]
500
+ )
501
+ target.preferredForwardBufferDuration = 0.0
502
+ target.queueItemId = existing.queueItemId
503
+ target.sourceURL = existing.sourceURL
504
+ // Replace the queue slot with the rebuilt item — any cached
505
+ // AVPlayerItem reference held by a future callsite (e.g. an
506
+ // armCrossfade re-arming on this index) must read queue[index]
507
+ // afresh; the prior `existing` instance is now orphaned and
508
+ // its prior-player association will release asynchronously.
509
+ queue[index] = target
510
+ applyMixIfNeeded(to: target)
511
+ applyPitchAlgorithm(to: target)
512
+ leadingPlayer.replaceCurrentItem(with: target)
513
+ if position > 0 {
514
+ target.seek(
515
+ to: CMTime(seconds: position, preferredTimescale: 600),
516
+ completionHandler: nil
517
+ )
518
+ }
519
+ if wasPlaying {
520
+ // replaceCurrentItem leaves the player at rate 0 — resume at the
521
+ // user's speed (mirrors play() / completeCrossfade) so a skip while
522
+ // playing at a non-default speed doesn't fall back to 1.0x.
523
+ leadingPlayer.rate = userPlaybackSpeed
524
+ }
525
+ standbyArmed = false
526
+ installLeadingObservers()
527
+ updateRoutingArbiter()
528
+ delegate?.engineDidTransitionTrack(self)
529
+ }
530
+
531
+ func skipToNext() {
532
+ let next = currentIndex + 1
533
+ if next < queue.count {
534
+ seek(toIndex: next, position: 0)
535
+ }
536
+ }
537
+
538
+ func skipToPrevious() {
539
+ let prev = currentIndex - 1
540
+ if prev >= 0 {
541
+ seek(toIndex: prev, position: 0)
542
+ } else {
543
+ leadingPlayer.currentItem?.seek(to: .zero, completionHandler: nil)
544
+ }
545
+ }
546
+
547
+ // MARK: - Config
548
+
549
+ func setVolume(_ volume: Float) {
550
+ userVolume = volume
551
+ leadingPlayer.volume = volume
552
+ // Standby stays silent outside fade window.
553
+ }
554
+
555
+ func setPlaybackSpeed(_ speed: Float) {
556
+ userPlaybackSpeed = speed
557
+ leadingPlayer.rate = speed
558
+ // Crossing the 1.0 boundary changes the resolved algorithm; restamp
559
+ // both legs (standby prerolls at this rate).
560
+ reapplyPitchToCurrentLegs()
561
+ }
562
+
563
+ func seedPlaybackSpeed(_ speed: Float) {
564
+ // Persist only; `play()` applies it. Does not touch the leg rate,
565
+ // so it won't start a paused engine.
566
+ userPlaybackSpeed = speed
567
+ reapplyPitchToCurrentLegs()
568
+ }
569
+
570
+ func setRepeatMode(_ mode: RepeatMode) {
571
+ // `.queue` wrap is still driven by TrackPlayer rebuilding the queue
572
+ // (as on gapless). `.track` (repeat-one) is handled here because
573
+ // AVPlayer has no native repeat: the engine suppresses the fade and
574
+ // loops the current item on natural end.
575
+ repeatMode = mode
576
+ }
577
+
578
+ // MARK: - State
579
+
580
+ /// During a crossfade the conceptual "active" track flips to the
581
+ /// standby leg the moment the fade begins (matches the JS-facing
582
+ /// `onTrackChange` + lock-screen / Now Playing flip the delegate
583
+ /// performs in response to `engineCrossfadeDidBegin`). All four
584
+ /// accessors below honour this: when `fadeInFlight`, they read
585
+ /// from `standbyPlayer` (the incoming leg) so `useProgress`,
586
+ /// seek clamps, preserve-current, and index lookups all see the
587
+ /// incoming track. Engine-internal code reaches `leadingPlayer`
588
+ /// / `currentIndex` directly.
589
+ var currentMediaItemIndex: Int {
590
+ if queue.isEmpty { return -1 }
591
+ return fadeInFlight ? currentIndex + 1 : currentIndex
592
+ }
593
+
594
+ var currentPositionSeconds: TimeInterval {
595
+ let player = fadeInFlight ? standbyPlayer : leadingPlayer
596
+ let t = player.currentTime()
597
+ return t.isNumeric ? CMTimeGetSeconds(t) : 0
598
+ }
599
+
600
+ var currentDurationSeconds: TimeInterval {
601
+ let player = fadeInFlight ? standbyPlayer : leadingPlayer
602
+ guard let d = player.currentItem?.duration, d.isNumeric else { return 0 }
603
+ return CMTimeGetSeconds(d)
604
+ }
605
+
606
+ var bufferedPositionSeconds: TimeInterval {
607
+ let player = fadeInFlight ? standbyPlayer : leadingPlayer
608
+ guard let ranges = player.currentItem?.loadedTimeRanges,
609
+ let last = ranges.last?.timeRangeValue else { return 0 }
610
+ return CMTimeGetSeconds(last.start + last.duration)
611
+ }
612
+
613
+ var isPlaying: Bool {
614
+ // Reads the leading leg unconditionally (both legs play mid-fade); the
615
+ // `timeControlStatus` accessor below deliberately reads the active leg
616
+ // (standby while fading) to match `currentMediaItem` for state derivation.
617
+ leadingPlayer.timeControlStatus == .playing
618
+ }
619
+
620
+ var timeControlStatus: AVPlayer.TimeControlStatus {
621
+ // Mirror `currentMediaItem`'s leg selection: during a fade the standby
622
+ // (incoming) leg is the conceptually-active track, so its status is the
623
+ // one a consumer's spinner/state should reflect.
624
+ let player = fadeInFlight ? standbyPlayer : leadingPlayer
625
+ return player.timeControlStatus
626
+ }
627
+
628
+ var currentMediaItem: AVPlayerItem? {
629
+ let player = fadeInFlight ? standbyPlayer : leadingPlayer
630
+ return player.currentItem
631
+ }
632
+
633
+ var allMediaItems: [AVPlayerItem] {
634
+ queue
635
+ }
636
+
637
+ // MARK: - Effect chain
638
+
639
+ func setAudioMixProvider(_ provider: AudioMixProvider?) {
640
+ mixProvider = provider
641
+ refreshAllItemMixes()
642
+ }
643
+
644
+ func setCachedURLResolver(_ resolver: ((String) -> URL?)?) {
645
+ cachedURLResolver = resolver
646
+ }
647
+
648
+ /// The lookahead cache's local file URL for [item]'s source track,
649
+ /// when it has fully cached since the item was built; nil when no
650
+ /// resolver is wired, the item carries no source URL, or the cache
651
+ /// misses. Keyed by the verbatim `sourceURL` the cache was keyed
652
+ /// with — never the asset URL (already `file://` once local).
653
+ private func cachedLocalURL(for item: AVPlayerItem) -> URL? {
654
+ guard let resolver = cachedURLResolver, let url = item.sourceURL else {
655
+ return nil
656
+ }
657
+ return resolver(url)
658
+ }
659
+
660
+ /// The asset a queue item should be (re)built from at a late attach:
661
+ /// the lookahead cache's local file when [existing]'s track has
662
+ /// since cached, else [existing]'s own asset. Re-resolving here lets
663
+ /// a forward/back skip to a now-cached track play from local disk
664
+ /// rather than re-loading the remote asset.
665
+ private func cacheResolvedAsset(for existing: AVPlayerItem) -> AVAsset {
666
+ // Reuse the existing asset when it's already this cache file (built
667
+ // cached at queue-build time) — the cross-attach rebuilds the item
668
+ // regardless, so there's nothing to upgrade and a fresh AVURLAsset
669
+ // on the same file would just be a wasted allocation.
670
+ guard let cachedURL = cachedLocalURL(for: existing),
671
+ (existing.asset as? AVURLAsset)?.url != cachedURL else {
672
+ return existing.asset
673
+ }
674
+ return AVURLAsset(url: cachedURL)
675
+ }
676
+
677
+ /// If [index]'s queue item was built from a remote URL whose track
678
+ /// has since fully cached, swap the slot for a fresh item backed by
679
+ /// the local cache file (carrying `queueItemId` + `sourceURL` across)
680
+ /// and return it; otherwise return the existing item unchanged. Lets
681
+ /// the fade-arm preroll pick up a track that cached after the queue
682
+ /// was first built so an auto-advance crossfade plays from local disk.
683
+ private func cacheUpgradedItem(at index: Int) -> AVPlayerItem {
684
+ let existing = queue[index]
685
+ // Only rebuild on the genuine remote→cached transition. When the slot
686
+ // was already built from this cache file (cached at queue-build time),
687
+ // reuse the prepared item rather than discarding its buffers for an
688
+ // identical rebuild + re-preroll.
689
+ guard let cachedURL = cachedLocalURL(for: existing),
690
+ (existing.asset as? AVURLAsset)?.url != cachedURL else {
691
+ return existing
692
+ }
693
+ let upgraded = AVPlayerItem(
694
+ asset: AVURLAsset(url: cachedURL),
695
+ automaticallyLoadedAssetKeys: ["playable", "duration", "tracks"]
696
+ )
697
+ upgraded.preferredForwardBufferDuration = 0.0
698
+ upgraded.queueItemId = existing.queueItemId
699
+ upgraded.sourceURL = existing.sourceURL
700
+ queue[index] = upgraded
701
+ return upgraded
702
+ }
703
+
704
+ func refreshAllItemMixes() {
705
+ // Catch-up walk: only fill items that lack an `audioMix`. Items
706
+ // that already carry a tap are left alone (re-assigning on an
707
+ // already-rendering item allocates fresh `MTAudioProcessingTap`
708
+ // + `EQProcessor` cascade resources that AVPlayer silently
709
+ // drops, leaking them to ARC). See `GaplessEngine.refreshAllItemMixes`
710
+ // for the full rationale.
711
+ if let leading = leadingPlayer.currentItem, leading.audioMix == nil {
712
+ leading.audioMix = mixProvider?.audioMix(for: leading)
713
+ }
714
+ if let standby = standbyPlayer.currentItem, standby.audioMix == nil {
715
+ standby.audioMix = mixProvider?.audioMix(for: standby)
716
+ }
717
+ }
718
+
719
+ private func applyMixIfNeeded(to item: AVPlayerItem) {
720
+ guard let provider = mixProvider,
721
+ let mix = provider.audioMix(for: item) else { return }
722
+ item.audioMix = mix
723
+ }
724
+
725
+ func setPitchCorrectionMode(_ mode: PitchCorrectionMode) {
726
+ pitchCorrectionMode = mode
727
+ reapplyPitchToCurrentLegs()
728
+ }
729
+
730
+ /// Stamp the resolved algorithm on `item`. Idempotent: a no-op when
731
+ /// the item already carries it, so re-applying on a rendering item
732
+ /// doesn't churn the audio graph.
733
+ private func applyPitchAlgorithm(to item: AVPlayerItem) {
734
+ let algo = PitchAlgorithm.resolve(
735
+ mode: pitchCorrectionMode,
736
+ speed: userPlaybackSpeed
737
+ )
738
+ if item.audioTimePitchAlgorithm != algo {
739
+ item.audioTimePitchAlgorithm = algo
740
+ }
741
+ }
742
+
743
+ private func reapplyPitchToCurrentLegs() {
744
+ if let leading = leadingPlayer.currentItem { applyPitchAlgorithm(to: leading) }
745
+ if let standby = standbyPlayer.currentItem { applyPitchAlgorithm(to: standby) }
746
+ }
747
+
748
+ // MARK: - Handoff
749
+
750
+ func handoff(to nextEngine: PlaybackEngine, atTrackBoundary: Bool) async {
751
+ // Engine handoff (gapless ↔ crossfade) is driven by
752
+ // TrackPlayer.swift's mode-switch path which holds the
753
+ // canonical queue model. The engine's own `release()` is
754
+ // the caller's responsibility AFTER the swap.
755
+ return
756
+ }
757
+
758
+ // MARK: - Equal-power gain math
759
+
760
+ /// Equal-power gain pair for fade progress `t ∈ [0, 1]`.
761
+ /// `(outgoing, incoming)` — sum-of-squares stays at 1.0
762
+ /// across the ramp so perceived loudness is constant.
763
+ static func equalPowerGains(t: Float) -> (Float, Float) {
764
+ let clamped = max(0, min(1, t))
765
+ let angle = clamped * Float.pi / 2
766
+ return (cos(angle), sin(angle))
767
+ }
768
+
769
+ /// Approximate the equal-power curve via [subRampCount]
770
+ /// short linear segments. Returns the gain pair at each
771
+ /// step's start. Caller schedules each segment via
772
+ /// `setVolumeRamp(fromStartVolume:toEndVolume:timeRange:)`.
773
+ ///
774
+ /// `setVolumeRamp` is linear-only per the AVFoundation API;
775
+ /// staircasing the cos/sin curve into N segments is the
776
+ /// supported approximation.
777
+ static func equalPowerSubRamps(
778
+ durationSeconds: TimeInterval,
779
+ steps: Int = subRampCount
780
+ ) -> [(timeRange: CMTimeRange, outgoing: (start: Float, end: Float), incoming: (start: Float, end: Float))] {
781
+ guard steps > 0, durationSeconds > 0 else { return [] }
782
+ let stepSeconds = durationSeconds / Double(steps)
783
+ var ramps: [(CMTimeRange, (Float, Float), (Float, Float))] = []
784
+ for i in 0 ..< steps {
785
+ let tStart = Float(i) / Float(steps)
786
+ let tEnd = Float(i + 1) / Float(steps)
787
+ let (outStart, inStart) = equalPowerGains(t: tStart)
788
+ let (outEnd, inEnd) = equalPowerGains(t: tEnd)
789
+ let cmStart = CMTime(seconds: Double(i) * stepSeconds, preferredTimescale: 600)
790
+ let cmEnd = CMTime(seconds: Double(i + 1) * stepSeconds, preferredTimescale: 600)
791
+ let range = CMTimeRange(start: cmStart, end: cmEnd)
792
+ ramps.append((range, (outStart, outEnd), (inStart, inEnd)))
793
+ }
794
+ return ramps
795
+ }
796
+
797
+ /// Auto-clamp the configured fade duration so the ramp never
798
+ /// overflows either leg's track length. Mirrors the Android
799
+ /// `effectiveCrossfadeMs`.
800
+ func effectiveCrossfadeSeconds(
801
+ leadingDurationSeconds: TimeInterval,
802
+ standbyDurationSeconds: TimeInterval
803
+ ) -> TimeInterval {
804
+ let configured = crossfadeDurationSeconds
805
+ let leadingHalf = leadingDurationSeconds > 0
806
+ ? leadingDurationSeconds / 2 : configured
807
+ let standbyHalf = standbyDurationSeconds > 0
808
+ ? standbyDurationSeconds / 2 : configured
809
+ return max(0, min(min(configured, leadingHalf), standbyHalf))
810
+ }
811
+
812
+ // MARK: - Fade cancel
813
+
814
+ /// Cancel any in-flight fade — strip the volume ramp from
815
+ /// both legs' current `audioMix`, snap leading to userVolume,
816
+ /// drop the standby's currentItem so its preroll bytes are
817
+ /// released. Internal entry point used by `pause` / `seek` /
818
+ /// `setItems` and by the route-monitor non-mixable callback.
819
+ func cancelFade() {
820
+ cancelFadeInternal()
821
+ }
822
+
823
+ // MARK: - Boundary arming
824
+
825
+ /// Boundary-arming periodic time observer. Watches the leading
826
+ /// leg's time at 200ms cadence; when within
827
+ /// `effectiveCrossfadeSeconds + prerollLeadSeconds` of track end,
828
+ /// prerolls standby + schedules the equal-power ramp on both
829
+ /// legs' `AVMutableAudioMixInputParameters`.
830
+ ///
831
+ /// Cancellation: `pause` / `stop` / `seek` / `skipToNext` /
832
+ /// `skipToPrevious` / `release` all remove the observer. `play`
833
+ /// re-installs it.
834
+ private func startArmingObserver() {
835
+ if armingObserver != nil { return }
836
+ let player = leadingPlayer
837
+ let interval = CMTime(seconds: 0.2, preferredTimescale: CMTimeScale(NSEC_PER_SEC))
838
+ let token = player.addPeriodicTimeObserver(
839
+ forInterval: interval,
840
+ queue: .main
841
+ ) { [weak self] _ in
842
+ self?.maybeArmCrossfade()
843
+ }
844
+ armingObserver = (player, token)
845
+ }
846
+
847
+ private func stopArmingObserver() {
848
+ if let observer = armingObserver {
849
+ observer.player.removeTimeObserver(observer.token)
850
+ }
851
+ armingObserver = nil
852
+ }
853
+
854
+ private func maybeArmCrossfade() {
855
+ if standbyArmed { return }
856
+ if fadeInFlight { return }
857
+ if !routeMonitor.isCurrentRouteMixable { return } // hard-cut on AirPlay/CarPlay
858
+ if crossfadeDurationSeconds <= 0 { return }
859
+ // Repeat-one loops the current item in place (see
860
+ // `handleItemDidPlayToEnd`); never arm a look-ahead fade, which
861
+ // would advance past the track the user asked to repeat.
862
+ if repeatMode == .track { return }
863
+ if currentIndex < 0 || currentIndex >= queue.count - 1 { return } // last track or empty
864
+ guard let leading = leadingPlayer.currentItem else { return }
865
+ let duration = leading.duration
866
+ if !duration.isNumeric { return }
867
+ let durationSeconds = CMTimeGetSeconds(duration)
868
+ if durationSeconds <= 0 { return }
869
+ let position = CMTimeGetSeconds(leading.currentTime())
870
+ // Standby duration unknown until prepared — pass 0 so
871
+ // effectiveCrossfadeSeconds falls through to the configured
872
+ // value with leading-half clamp only.
873
+ let effective = effectiveCrossfadeSeconds(
874
+ leadingDurationSeconds: durationSeconds,
875
+ standbyDurationSeconds: 0
876
+ )
877
+ let armThreshold = durationSeconds - effective - Self.prerollLeadSeconds
878
+ if position < armThreshold { return }
879
+ standbyArmed = true
880
+ armCrossfade(durationSeconds: effective)
881
+ }
882
+
883
+ /// Preload the next queue item onto standby + schedule the
884
+ /// equal-power N-sub-ramp `setVolumeRamp` schedule on both legs'
885
+ /// `AVMutableAudioMixInputParameters`. Caller (the periodic
886
+ /// observer) has already validated route + index + arming state.
887
+ ///
888
+ /// `AVPlayer.preroll(atRate:)` has TWO documented preconditions
889
+ /// per Apple's `AVPlayer.h`:
890
+ /// 1. `AVPlayer.status == .readyToPlay`
891
+ /// 2. `automaticallyWaitsToMinimizeStalling == false`
892
+ ///
893
+ /// Violating either raises `NSInternalInconsistencyException`
894
+ /// synchronously. After `replaceCurrentItem` the status flip is
895
+ /// asynchronous — the asset has to load tracks/duration. KVO-
896
+ /// wait until the status reaches `.readyToPlay` before invoking
897
+ /// `preroll`; `runFade` chains through the readiness callback so
898
+ /// the timing semantics (preroll → ramp schedule → wall-clock
899
+ /// completion) are preserved. The pre-attach `seek(to: .zero)`
900
+ /// on the prior implementation was redundant — `replaceCurrentItem`
901
+ /// resets the item's playhead — and was masking the readiness
902
+ /// race because seek-on-detached-item is a documented no-op on
903
+ /// modern iOS.
904
+ private func armCrossfade(durationSeconds: TimeInterval) {
905
+ let nextIdx = currentIndex + 1
906
+ guard nextIdx < queue.count else {
907
+ standbyArmed = false
908
+ return
909
+ }
910
+ // Re-resolve against the cache: a track that finished caching after
911
+ // the queue was built is swapped for its local file here so the
912
+ // auto-advance fade plays from local disk, not the remote URL.
913
+ let nextItem = cacheUpgradedItem(at: nextIdx)
914
+ applyMixIfNeeded(to: nextItem)
915
+ applyPitchAlgorithm(to: nextItem)
916
+ let standby = standbyPlayer
917
+ standby.replaceCurrentItem(with: nextItem)
918
+ let priorAutoStall = standby.automaticallyWaitsToMinimizeStalling
919
+ awaitStandbyReady(standby) { [weak self] in
920
+ guard let self else { return }
921
+ if self.released || !self.standbyArmed { return }
922
+ // Explicit `tracks` key load on the freshly-replaced standby
923
+ // asset BEFORE preroll. `AVPlayerItem.status == .readyToPlay`
924
+ // does NOT guarantee the asset's tracks key is loaded —
925
+ // that's a separate async load. `runFade` requires the
926
+ // tracks to be present so it can attach the volume-ramp
927
+ // audioMix to the standby item.
928
+ let nextAsset = nextItem.asset
929
+ Task { @MainActor [weak self] in
930
+ do {
931
+ _ = try await nextAsset.load(.tracks)
932
+ } catch {
933
+ self?.cancelFadeInternal()
934
+ return
935
+ }
936
+ guard let self else { return }
937
+ if self.released || !self.standbyArmed { return }
938
+ standby.automaticallyWaitsToMinimizeStalling = false
939
+ // Await preroll via a checked continuation so the rest of
940
+ // the chain stays on @MainActor. Spawning a fresh Task
941
+ // inside `preroll`'s @escaping completion would create a
942
+ // @Sendable-closure-captures-non-Sendable-self warning
943
+ // because preroll's callback queue is unspecified.
944
+ _ = await withCheckedContinuation { (cont: CheckedContinuation<Bool, Never>) in
945
+ standby.preroll(atRate: 1.0) { ready in
946
+ cont.resume(returning: ready)
947
+ }
948
+ }
949
+ if self.released || !self.standbyArmed { return }
950
+ // Best-effort restore: cancel/release paths drop the
951
+ // standby item entirely, so a missed restore here is
952
+ // bounded by the next replaceCurrentItem.
953
+ standby.automaticallyWaitsToMinimizeStalling = priorAutoStall
954
+ self.runFade(durationSeconds: durationSeconds)
955
+ }
956
+ }
957
+ }
958
+
959
+ /// One-shot KVO on `standby.status`. Fires [ready] once status
960
+ /// reaches `.readyToPlay`; fires immediately on the calling
961
+ /// runloop turn if already `.readyToPlay`. On `.failed` the
962
+ /// callback fires too — caller must check `released` /
963
+ /// `standbyArmed` before acting. Backed by a 5s wall-clock
964
+ /// timeout that calls `cancelFadeInternal` if the status never
965
+ /// flips (stuck-load defence).
966
+ private func awaitStandbyReady(_ player: AVPlayer, ready: @escaping () -> Void) {
967
+ standbyReadyObserver?.invalidate()
968
+ standbyReadyObserver = nil
969
+ standbyReadyTimeout?.cancel()
970
+ standbyReadyTimeout = nil
971
+ standbyReadyGen &+= 1
972
+ let myGen = standbyReadyGen
973
+
974
+ if player.status == .readyToPlay {
975
+ ready()
976
+ return
977
+ }
978
+
979
+ standbyReadyObserver = player.observe(\.status, options: [.new]) { [weak self] obs, _ in
980
+ let s = obs.status
981
+ // `.unknown` is the start state — wait for the first real flip.
982
+ guard s == .readyToPlay || s == .failed else { return }
983
+ DispatchQueue.main.async { [weak self] in
984
+ guard let self else { return }
985
+ // Cross-cycle race guard: if a new armCrossfade cycle
986
+ // started after this observer queued its main-async hop,
987
+ // the generation counter has advanced — this fire belongs
988
+ // to a stale standby and must not run `ready()` against
989
+ // the new arm's state.
990
+ if self.standbyReadyGen != myGen { return }
991
+ self.standbyReadyObserver?.invalidate()
992
+ self.standbyReadyObserver = nil
993
+ self.standbyReadyTimeout?.cancel()
994
+ self.standbyReadyTimeout = nil
995
+ if s == .readyToPlay {
996
+ ready()
997
+ } else {
998
+ // Standby load failed — drop the arm cleanly so the
999
+ // leading leg keeps playing through to its natural end.
1000
+ self.cancelFadeInternal()
1001
+ }
1002
+ }
1003
+ }
1004
+
1005
+ let timeout = DispatchWorkItem { [weak self] in
1006
+ guard let self else { return }
1007
+ // Same cross-cycle guard for the timeout path.
1008
+ if self.standbyReadyGen != myGen { return }
1009
+ self.standbyReadyObserver?.invalidate()
1010
+ self.standbyReadyObserver = nil
1011
+ self.standbyReadyTimeout = nil
1012
+ self.cancelFadeInternal()
1013
+ }
1014
+ standbyReadyTimeout = timeout
1015
+ DispatchQueue.main.asyncAfter(deadline: .now() + 5.0, execute: timeout)
1016
+ }
1017
+
1018
+ /// Input parameters to drive the fade ramp on [item]. Reuses the item's
1019
+ /// existing tap-bearing parameters when present so the EQ / visualizer /
1020
+ /// ReplayGain tap survives the fade; otherwise a bare ramp-only object
1021
+ /// keyed to [track]. Never re-runs the mix provider — that allocates a
1022
+ /// fresh MTAudioProcessingTap on an already-rendering item and leaks it
1023
+ /// (see refreshAllItemMixes).
1024
+ private func fadeParams(
1025
+ for item: AVPlayerItem,
1026
+ track: AVAssetTrack
1027
+ ) -> AVMutableAudioMixInputParameters {
1028
+ if let existing = item.audioMix?.inputParameters.first
1029
+ as? AVMutableAudioMixInputParameters {
1030
+ return existing
1031
+ }
1032
+ return AVMutableAudioMixInputParameters(track: track)
1033
+ }
1034
+
1035
+ /// Schedule the equal-power N-sub-ramp `setVolumeRamp` schedule
1036
+ /// on both legs' currentItem `audioMix.inputParameters`. Caller
1037
+ /// has already prerolled standby. The fade runs against
1038
+ /// asset-time on each item; the post-fade swap is scheduled via
1039
+ /// a Task that sleeps for `durationSeconds` then promotes
1040
+ /// standby to leading.
1041
+ private func runFade(durationSeconds: TimeInterval) {
1042
+ if released { return }
1043
+ guard let leading = leadingPlayer.currentItem,
1044
+ let standby = standbyPlayer.currentItem else { return }
1045
+
1046
+ // BOTH sides must produce a valid AVAssetTrack; if either is
1047
+ // empty the fade can't ramp evenly and the user hears a hard
1048
+ // transition. armCrossfade has already awaited the standby
1049
+ // asset's tracks key load, so empty here is a real error —
1050
+ // fail loud, cancel cleanly, log via NSLog so the issue isn't
1051
+ // silent (the prior implementation's `if let` guard silently
1052
+ // skipped, which is exactly the failure mode this guard
1053
+ // exists to surface).
1054
+ // Read tracks via the AVPlayerItem.tracks chain — populated
1055
+ // at .readyToPlay and sync-accessible. Avoids the deprecated
1056
+ // sync `asset.tracks(withMediaType:)` (replaced by async
1057
+ // `loadTracks(withMediaType:)` in macOS 13 / iOS 16). The
1058
+ // standby asset's tracks key was already async-loaded in
1059
+ // armCrossfade so the chain is guaranteed populated by here.
1060
+ let leadingTrack = leading.tracks
1061
+ .first(where: { $0.assetTrack?.mediaType == .audio })?.assetTrack
1062
+ let standbyTrack = standby.tracks
1063
+ .first(where: { $0.assetTrack?.mediaType == .audio })?.assetTrack
1064
+ guard let leadingTrack, let standbyTrack else {
1065
+ NSLog("[RNQP-CROSSFADE] runFade aborting — missing audio track (leading=%@ standby=%@); cancelling fade",
1066
+ leadingTrack == nil ? "MISSING" : "ok",
1067
+ standbyTrack == nil ? "MISSING" : "ok")
1068
+ cancelFadeInternal()
1069
+ return
1070
+ }
1071
+
1072
+ fadeInFlight = true
1073
+
1074
+ let leadingFadeStart = leading.currentTime()
1075
+ let ramps = Self.equalPowerSubRamps(durationSeconds: durationSeconds)
1076
+
1077
+ // Reuse each leg's EXISTING tap-bearing input parameters so the EQ /
1078
+ // visualizer / ReplayGain MTAudioProcessingTap keeps processing through
1079
+ // the fade window — the volume ramp and the tap coexist on one
1080
+ // AVMutableAudioMixInputParameters (the tap is pre-effects, so it sees
1081
+ // the track audio and the ramp scales the tapped output). A fresh tap is
1082
+ // never allocated here — re-running the provider on an already-rendering
1083
+ // item leaks tap resources (see refreshAllItemMixes). Falls back to a
1084
+ // bare ramp-only params object only when the leg carries no tap (no
1085
+ // EQ/viz/RG consumer, HLS, or tracks not yet loaded).
1086
+ let leadingParams = fadeParams(for: leading, track: leadingTrack)
1087
+ for ramp in ramps {
1088
+ let absStart = leadingFadeStart + ramp.timeRange.start
1089
+ let timeRange = CMTimeRange(start: absStart, duration: ramp.timeRange.duration)
1090
+ leadingParams.setVolumeRamp(
1091
+ fromStartVolume: ramp.outgoing.start,
1092
+ toEndVolume: ramp.outgoing.end,
1093
+ timeRange: timeRange
1094
+ )
1095
+ }
1096
+ let leadingMix = AVMutableAudioMix()
1097
+ leadingMix.inputParameters = [leadingParams]
1098
+ leading.audioMix = leadingMix
1099
+
1100
+ // Standby ramp anchored at asset-time zero, NOT
1101
+ // `standby.currentTime()`. After `replaceCurrentItem` +
1102
+ // `preroll(atRate:)` the standby's currentTime is unstable
1103
+ // across iOS versions until first decode pull lands; using
1104
+ // kCMTimeZero is the only reliable anchor for the head of a
1105
+ // freshly-attached AVPlayerItem.
1106
+ let standbyParams = fadeParams(for: standby, track: standbyTrack)
1107
+ for ramp in ramps {
1108
+ let timeRange = CMTimeRange(
1109
+ start: ramp.timeRange.start, duration: ramp.timeRange.duration
1110
+ )
1111
+ standbyParams.setVolumeRamp(
1112
+ fromStartVolume: ramp.incoming.start,
1113
+ toEndVolume: ramp.incoming.end,
1114
+ timeRange: timeRange
1115
+ )
1116
+ }
1117
+ let standbyMix = AVMutableAudioMix()
1118
+ standbyMix.inputParameters = [standbyParams]
1119
+ standby.audioMix = standbyMix
1120
+
1121
+ standbyPlayer.volume = userVolume // ramp inside the mix handles the actual envelope
1122
+ standbyPlayer.play()
1123
+
1124
+ // Active-track flip: the standby leg is now audibly playing
1125
+ // (volume 0 → ramping up). Notify the delegate so JS-facing
1126
+ // `onTrackChange` + `MPNowPlayingInfoCenter` retarget to the
1127
+ // incoming track immediately, not at fade-end. The accessor
1128
+ // group above (`currentMediaItem*`, `currentPositionSeconds`,
1129
+ // etc.) also flips at this point because `fadeInFlight = true`
1130
+ // is already set above; the delegate sees consistent state
1131
+ // across the callback.
1132
+ let incomingIdx = currentIndex + 1
1133
+ delegate?.engineCrossfadeDidBegin(self, incomingIndex: incomingIdx)
1134
+
1135
+ // Post-fade swap scheduled in wall-clock — the asset-time-keyed
1136
+ // ramps complete in this many seconds regardless of pause
1137
+ // because pausing also halts the asset clock. The Task handle
1138
+ // is stored so a subsequent `cancelFadeInternal` /
1139
+ // `release` can cancel it; without cancellation a stale
1140
+ // completion can run against a fresh fade after the user
1141
+ // pauses+resumes within one boundary window.
1142
+ fadeCompletionTask?.cancel()
1143
+ let durationNs = UInt64(durationSeconds * 1_000_000_000)
1144
+ fadeCompletionTask = Task { @MainActor [weak self] in
1145
+ do {
1146
+ try await Task.sleep(nanoseconds: durationNs)
1147
+ } catch {
1148
+ return // cancelled
1149
+ }
1150
+ self?.completeCrossfade()
1151
+ }
1152
+ }
1153
+
1154
+ /// Promote standby to leading at fade-end. Drops the old
1155
+ /// leading's currentItem; advances `currentIndex`; resets
1156
+ /// arming markers so the new leading can re-arm for its own
1157
+ /// next-track boundary; fires `engineDidTransitionTrack` so
1158
+ /// `TrackPlayer` can refresh JS-facing state.
1159
+ ///
1160
+ /// Observer cleanup runs BEFORE the role flip so
1161
+ /// `removeTimeObserver` is called against the player that
1162
+ /// issued the token; reinstall runs AFTER the flip so the new
1163
+ /// observer attaches to the new leading. The fade ramp's
1164
+ /// audioMix wiped any provider-supplied EQ params on the new
1165
+ /// leading's currentItem — re-apply via `applyMixIfNeeded`
1166
+ /// after stripping the ramp mix.
1167
+ private func completeCrossfade() {
1168
+ if released { return }
1169
+ if !fadeInFlight { return }
1170
+ fadeInFlight = false
1171
+ fadeCompletionTask = nil
1172
+ stopArmingObserver()
1173
+ teardownLeadingObservers()
1174
+ let oldLeading = leadingPlayer
1175
+ oldLeading.pause()
1176
+ oldLeading.replaceCurrentItem(with: nil)
1177
+ oldLeading.volume = userVolume
1178
+ // The fade ramp's final tick already settled the standby (about
1179
+ // to be promoted to leading) at userVolume; no explicit write
1180
+ // needed across the toggle.
1181
+ currentRoleIsA.toggle()
1182
+ if let newLeading = leadingPlayer.currentItem {
1183
+ newLeading.audioMix = nil
1184
+ applyMixIfNeeded(to: newLeading)
1185
+ }
1186
+ // The promoted standby was prerolled + played at rate 1.0; restore
1187
+ // the user's playback speed so it survives the transition.
1188
+ leadingPlayer.rate = userPlaybackSpeed
1189
+ standbyArmed = false
1190
+ currentIndex += 1
1191
+ startArmingObserver()
1192
+ installLeadingObservers()
1193
+ updateRoutingArbiter()
1194
+ delegate?.engineDidTransitionTrack(self)
1195
+ }
1196
+
1197
+ private func cancelFadeInternal(emitRevert: Bool = true) {
1198
+ fadeCompletionTask?.cancel()
1199
+ fadeCompletionTask = nil
1200
+ standbyReadyObserver?.invalidate()
1201
+ standbyReadyObserver = nil
1202
+ standbyReadyTimeout?.cancel()
1203
+ standbyReadyTimeout = nil
1204
+ // Capture pre-state: if a fade was in flight we already fired
1205
+ // `engineCrossfadeDidBegin` for `currentIndex + 1` — the
1206
+ // delegate believes the incoming is active. We must fire
1207
+ // `engineCrossfadeDidCancel(revertedIndex: currentIndex)` so
1208
+ // the delegate reverts active-track state back to the leading
1209
+ // leg. `emitRevert: false` is for callers that will immediately
1210
+ // set a new active track themselves (e.g. seek to a different
1211
+ // index) — emitting the intermediate revert would surface a
1212
+ // spurious track-change to the outgoing leg before the caller's
1213
+ // own track-change.
1214
+ let wasMidFade = fadeInFlight
1215
+ let leadingIdx = currentIndex
1216
+ fadeInFlight = false
1217
+ standbyArmed = false
1218
+ // Backward seek through a scheduled ramp window leaves the
1219
+ // mix in a wonky state per Wade Tregaskis — strip the mix
1220
+ // and re-apply the EQ-only mix to recover.
1221
+ if let leading = leadingPlayer.currentItem {
1222
+ leading.audioMix = nil
1223
+ applyMixIfNeeded(to: leading)
1224
+ }
1225
+ if let standby = standbyPlayer.currentItem {
1226
+ standby.audioMix = nil
1227
+ }
1228
+ leadingPlayer.volume = userVolume
1229
+ standbyPlayer.volume = 0
1230
+ standbyPlayer.replaceCurrentItem(with: nil)
1231
+ if wasMidFade && emitRevert {
1232
+ delegate?.engineCrossfadeDidCancel(self, revertedIndex: leadingIdx)
1233
+ }
1234
+ }
1235
+
1236
+ // MARK: - Engine event observer install/teardown
1237
+
1238
+ /// Install KVO on the leading leg's `timeControlStatus` (drives
1239
+ /// `engineStateMaybeChanged` + `engineIsPlayingChanged`) and on
1240
+ /// the leading leg's currentItem `tracks` / `status` (drives
1241
+ /// format-ready + failed-to-load delegate fires). Called whenever
1242
+ /// the leading leg or its currentItem changes — i.e. from
1243
+ /// [setItems], [seek], and [completeCrossfade] after the role
1244
+ /// flip. Idempotent — teardown runs first inside.
1245
+ private func installLeadingObservers() {
1246
+ teardownLeadingObservers()
1247
+ let player = leadingPlayer
1248
+ leadingTimeControlObserver = player.observe(
1249
+ \.timeControlStatus, options: [.new]
1250
+ ) { [weak self] obs, _ in
1251
+ let isPlayingNow = obs.timeControlStatus == .playing
1252
+ DispatchQueue.main.async {
1253
+ guard let self else { return }
1254
+ self.delegate?.engineStateMaybeChanged(self, reason: nil)
1255
+ self.delegate?.engineIsPlayingChanged(self, isPlaying: isPlayingNow)
1256
+ }
1257
+ }
1258
+ if let item = player.currentItem {
1259
+ leadingItemTracksObserver = item.observe(
1260
+ \.tracks, options: [.new]
1261
+ ) { [weak self] obs, _ in
1262
+ // tracks fires on every mutation including transient empty
1263
+ // states during seek; only fire format-changed when the
1264
+ // tracks array is populated so the gapless KVO path's
1265
+ // dedup contract is matched.
1266
+ guard !obs.tracks.isEmpty else { return }
1267
+ DispatchQueue.main.async {
1268
+ guard let self else { return }
1269
+ self.delegate?.engineActiveItemFormatChanged(self)
1270
+ }
1271
+ }
1272
+ // Bootstrap: `.new`-only KVO won't fire when the item's tracks are
1273
+ // ALREADY populated at install time — a cached / preloaded asset, e.g. a
1274
+ // skip to a lookahead-cached track. Without this the format-change never
1275
+ // propagates and the now-playing format stays nil. Mirrors what
1276
+ // `.initial` would have delivered.
1277
+ if !item.tracks.isEmpty {
1278
+ DispatchQueue.main.async { [weak self] in
1279
+ guard let self else { return }
1280
+ self.delegate?.engineActiveItemFormatChanged(self)
1281
+ }
1282
+ }
1283
+ leadingItemStatusObserver = item.observe(
1284
+ \.status, options: [.new]
1285
+ ) { [weak self] obs, _ in
1286
+ guard obs.status == .failed else { return }
1287
+ let underlying = obs.error ?? NSError(
1288
+ domain: "CrossfadeEngine", code: -1, userInfo: nil
1289
+ )
1290
+ DispatchQueue.main.async {
1291
+ guard let self else { return }
1292
+ self.delegate?.engineDidFailWithError(self, error: underlying)
1293
+ }
1294
+ }
1295
+ }
1296
+ }
1297
+
1298
+ private func teardownLeadingObservers() {
1299
+ leadingTimeControlObserver?.invalidate()
1300
+ leadingTimeControlObserver = nil
1301
+ leadingItemTracksObserver?.invalidate()
1302
+ leadingItemTracksObserver = nil
1303
+ leadingItemStatusObserver?.invalidate()
1304
+ leadingItemStatusObserver = nil
1305
+ }
1306
+
1307
+ private func handleItemDidPlayToEnd(_ note: Notification) {
1308
+ guard let item = note.object as? AVPlayerItem,
1309
+ item === leadingPlayer.currentItem else { return }
1310
+ delegate?.engineDidPlayItemToEnd(self)
1311
+ // Repeat-one: loop the current item in place instead of advancing
1312
+ // or ending the queue. The fade is suppressed under `.track`, so
1313
+ // the item reaches its true end here; seek to zero + play replays
1314
+ // it, matching the gapless engine's repeat-track replay. Applies on
1315
+ // every track (incl. the last), so it must precede the queue-end check.
1316
+ if repeatMode == .track, !fadeInFlight, currentIndex >= 0 {
1317
+ leadingPlayer.seek(to: .zero)
1318
+ leadingPlayer.play()
1319
+ return
1320
+ }
1321
+ // Queue-end detection: leading played its last item to end
1322
+ // AND no fade is in flight (mid-fade end is normal — the
1323
+ // standby is about to be promoted, not the queue ending).
1324
+ // [currentIndex] is still pre-swap during a fade; gating on
1325
+ // [fadeInFlight] avoids firing enginePlaybackEnded one item
1326
+ // too early when the penultimate track ends naturally during
1327
+ // its outgoing fade.
1328
+ if !fadeInFlight,
1329
+ currentIndex >= 0,
1330
+ currentIndex >= queue.count - 1 {
1331
+ delegate?.enginePlaybackEnded(self)
1332
+ }
1333
+ }
1334
+
1335
+ private func handleItemFailedToPlayToEnd(_ note: Notification) {
1336
+ guard let item = note.object as? AVPlayerItem,
1337
+ item === leadingPlayer.currentItem else { return }
1338
+ let underlying = (note.userInfo?[AVPlayerItemFailedToPlayToEndTimeErrorKey] as? Error)
1339
+ ?? item.error
1340
+ ?? NSError(domain: "CrossfadeEngine", code: -2, userInfo: nil)
1341
+ delegate?.engineDidFailWithError(self, error: underlying)
1342
+ }
1343
+ }