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.
- package/LICENSE +201 -0
- package/QueuePlayer.podspec +114 -0
- package/README.md +194 -0
- package/android/CMakeLists.txt +41 -0
- package/android/build.gradle +257 -0
- package/android/src/androidTest/java/com/margelo/nitro/queueplayer/SignalsmithStretchNativeTest.kt +136 -0
- package/android/src/main/AndroidManifest.xml +173 -0
- package/android/src/main/cpp/CMakeLists.txt +221 -0
- package/android/src/main/cpp/THIRD_PARTY_LICENSES +128 -0
- package/android/src/main/cpp/THIRD_PARTY_VERSIONS.txt +32 -0
- package/android/src/main/cpp/airplay2_audio.c +537 -0
- package/android/src/main/cpp/airplay2_audio.h +66 -0
- package/android/src/main/cpp/airplay2_control.c +680 -0
- package/android/src/main/cpp/airplay2_control.h +101 -0
- package/android/src/main/cpp/airplay2_crypto.c +548 -0
- package/android/src/main/cpp/airplay2_crypto.h +213 -0
- package/android/src/main/cpp/airplay2_dmap.c +81 -0
- package/android/src/main/cpp/airplay2_dmap.h +53 -0
- package/android/src/main/cpp/airplay2_filelog.h +100 -0
- package/android/src/main/cpp/airplay2_jni.cpp +579 -0
- package/android/src/main/cpp/airplay2_ntp.c +203 -0
- package/android/src/main/cpp/airplay2_ntp.h +39 -0
- package/android/src/main/cpp/airplay2_pair.c +653 -0
- package/android/src/main/cpp/airplay2_pair.h +114 -0
- package/android/src/main/cpp/airplay2_plist.c +840 -0
- package/android/src/main/cpp/airplay2_plist.h +184 -0
- package/android/src/main/cpp/airplay2_ptp.c +509 -0
- package/android/src/main/cpp/airplay2_ptp.h +40 -0
- package/android/src/main/cpp/airplay2_rtsp.c +693 -0
- package/android/src/main/cpp/airplay2_rtsp.h +90 -0
- package/android/src/main/cpp/airplay2_session.c +196 -0
- package/android/src/main/cpp/airplay2_session.h +197 -0
- package/android/src/main/cpp/airplay2_tlv.c +135 -0
- package/android/src/main/cpp/airplay2_tlv.h +87 -0
- package/android/src/main/cpp/airplay_jni.cpp +589 -0
- package/android/src/main/cpp/build-openssl-android.sh +94 -0
- package/android/src/main/cpp/cpp-adapter.cpp +11 -0
- package/android/src/main/cpp/prebuilt/libsodium/arm64-v8a/lib/libsodium.a +0 -0
- package/android/src/main/cpp/prebuilt/libsodium/include/sodium/core.h +28 -0
- package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_aead_aegis128l.h +92 -0
- package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_aead_aegis256.h +92 -0
- package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_aead_aes256gcm.h +179 -0
- package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_aead_chacha20poly1305.h +180 -0
- package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_aead_xchacha20poly1305.h +100 -0
- package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_auth.h +46 -0
- package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_auth_hmacsha256.h +70 -0
- package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_auth_hmacsha512.h +68 -0
- package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_auth_hmacsha512256.h +65 -0
- package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_box.h +177 -0
- package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_box_curve25519xchacha20poly1305.h +164 -0
- package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_box_curve25519xsalsa20poly1305.h +112 -0
- package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_core_ed25519.h +104 -0
- package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_core_hchacha20.h +36 -0
- package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_core_hsalsa20.h +36 -0
- package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_core_ristretto255.h +100 -0
- package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_core_salsa20.h +36 -0
- package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_core_salsa2012.h +36 -0
- package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_core_salsa208.h +40 -0
- package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_generichash.h +84 -0
- package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_generichash_blake2b.h +122 -0
- package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_hash.h +40 -0
- package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_hash_sha256.h +60 -0
- package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_hash_sha512.h +60 -0
- package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_kdf.h +53 -0
- package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_kdf_blake2b.h +44 -0
- package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_kdf_hkdf_sha256.h +74 -0
- package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_kdf_hkdf_sha512.h +75 -0
- package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_kx.h +66 -0
- package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_onetimeauth.h +65 -0
- package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_onetimeauth_poly1305.h +72 -0
- package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_pwhash.h +147 -0
- package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_pwhash_argon2i.h +122 -0
- package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_pwhash_argon2id.h +122 -0
- package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_pwhash_scryptsalsa208sha256.h +120 -0
- package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_scalarmult.h +46 -0
- package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_scalarmult_curve25519.h +42 -0
- package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_scalarmult_ed25519.h +51 -0
- package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_scalarmult_ristretto255.h +43 -0
- package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_secretbox.h +93 -0
- package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_secretbox_xchacha20poly1305.h +70 -0
- package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_secretbox_xsalsa20poly1305.h +69 -0
- package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_secretstream_xchacha20poly1305.h +108 -0
- package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_shorthash.h +41 -0
- package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_shorthash_siphash24.h +50 -0
- package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_sign.h +107 -0
- package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_sign_ed25519.h +124 -0
- package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_sign_edwards25519sha512batch.h +55 -0
- package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_stream.h +59 -0
- package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_stream_chacha20.h +106 -0
- package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_stream_salsa20.h +61 -0
- package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_stream_salsa2012.h +53 -0
- package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_stream_salsa208.h +56 -0
- package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_stream_xchacha20.h +61 -0
- package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_stream_xsalsa20.h +61 -0
- package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_verify_16.h +23 -0
- package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_verify_32.h +23 -0
- package/android/src/main/cpp/prebuilt/libsodium/include/sodium/crypto_verify_64.h +23 -0
- package/android/src/main/cpp/prebuilt/libsodium/include/sodium/export.h +57 -0
- package/android/src/main/cpp/prebuilt/libsodium/include/sodium/randombytes.h +72 -0
- package/android/src/main/cpp/prebuilt/libsodium/include/sodium/randombytes_internal_random.h +22 -0
- package/android/src/main/cpp/prebuilt/libsodium/include/sodium/randombytes_sysrandom.h +19 -0
- package/android/src/main/cpp/prebuilt/libsodium/include/sodium/runtime.h +55 -0
- package/android/src/main/cpp/prebuilt/libsodium/include/sodium/utils.h +179 -0
- package/android/src/main/cpp/prebuilt/libsodium/include/sodium/version.h +33 -0
- package/android/src/main/cpp/prebuilt/libsodium/include/sodium.h +75 -0
- package/android/src/main/cpp/prebuilt/libsodium/x86_64/lib/libsodium.a +0 -0
- package/android/src/main/cpp/prebuilt/openssl/arm64-v8a/lib/libcrypto.a +0 -0
- package/android/src/main/cpp/prebuilt/openssl/arm64-v8a/lib/libssl.a +0 -0
- package/android/src/main/cpp/prebuilt/openssl/x86_64/lib/libcrypto.a +0 -0
- package/android/src/main/cpp/prebuilt/openssl/x86_64/lib/libssl.a +0 -0
- package/android/src/main/cpp/stretch_jni.cpp +171 -0
- package/android/src/main/cpp/third_party/alac/addons/alac_wrapper.cpp +198 -0
- package/android/src/main/cpp/third_party/alac/addons/alac_wrapper.h +46 -0
- package/android/src/main/cpp/third_party/alac/codec/ALACAudioTypes.h +197 -0
- package/android/src/main/cpp/third_party/alac/codec/ALACBitUtilities.c +260 -0
- package/android/src/main/cpp/third_party/alac/codec/ALACBitUtilities.h +104 -0
- package/android/src/main/cpp/third_party/alac/codec/ALACDecoder.cpp +730 -0
- package/android/src/main/cpp/third_party/alac/codec/ALACDecoder.h +65 -0
- package/android/src/main/cpp/third_party/alac/codec/ALACEncoder.cpp +1425 -0
- package/android/src/main/cpp/third_party/alac/codec/ALACEncoder.h +92 -0
- package/android/src/main/cpp/third_party/alac/codec/EndianPortable.c +181 -0
- package/android/src/main/cpp/third_party/alac/codec/EndianPortable.h +59 -0
- package/android/src/main/cpp/third_party/alac/codec/ag_dec.c +362 -0
- package/android/src/main/cpp/third_party/alac/codec/ag_enc.c +370 -0
- package/android/src/main/cpp/third_party/alac/codec/aglib.h +81 -0
- package/android/src/main/cpp/third_party/alac/codec/dp_dec.c +381 -0
- package/android/src/main/cpp/third_party/alac/codec/dp_enc.c +386 -0
- package/android/src/main/cpp/third_party/alac/codec/dplib.h +61 -0
- package/android/src/main/cpp/third_party/alac/codec/matrix_dec.c +390 -0
- package/android/src/main/cpp/third_party/alac/codec/matrix_enc.c +342 -0
- package/android/src/main/cpp/third_party/alac/codec/matrixlib.h +80 -0
- package/android/src/main/cpp/third_party/crosstools/cross_log.c +95 -0
- package/android/src/main/cpp/third_party/crosstools/cross_log.h +25 -0
- package/android/src/main/cpp/third_party/crosstools/cross_net.c +1139 -0
- package/android/src/main/cpp/third_party/crosstools/cross_net.h +51 -0
- package/android/src/main/cpp/third_party/crosstools/cross_ssl.c +371 -0
- package/android/src/main/cpp/third_party/crosstools/cross_ssl.h +15 -0
- package/android/src/main/cpp/third_party/crosstools/cross_thread.c +134 -0
- package/android/src/main/cpp/third_party/crosstools/cross_thread.h +20 -0
- package/android/src/main/cpp/third_party/crosstools/cross_util.c +753 -0
- package/android/src/main/cpp/third_party/crosstools/cross_util.h +125 -0
- package/android/src/main/cpp/third_party/crosstools/platform.c +227 -0
- package/android/src/main/cpp/third_party/crosstools/platform.h +127 -0
- package/android/src/main/cpp/third_party/curve25519/include/curve25519_dh.h +53 -0
- package/android/src/main/cpp/third_party/curve25519/include/ed25519_signature.h +98 -0
- package/android/src/main/cpp/third_party/curve25519/include/external_calls.h +36 -0
- package/android/src/main/cpp/third_party/curve25519/source/BaseTypes.h +125 -0
- package/android/src/main/cpp/third_party/curve25519/source/base_folding8.h +1288 -0
- package/android/src/main/cpp/third_party/curve25519/source/curve25519_dh.c +208 -0
- package/android/src/main/cpp/third_party/curve25519/source/curve25519_mehdi.c +410 -0
- package/android/src/main/cpp/third_party/curve25519/source/curve25519_mehdi.h +175 -0
- package/android/src/main/cpp/third_party/curve25519/source/curve25519_order.c +155 -0
- package/android/src/main/cpp/third_party/curve25519/source/curve25519_utils.c +153 -0
- package/android/src/main/cpp/third_party/curve25519/source/custom_blind.c +27 -0
- package/android/src/main/cpp/third_party/curve25519/source/custom_blind.h +11 -0
- package/android/src/main/cpp/third_party/curve25519/source/ed25519_sign.c +419 -0
- package/android/src/main/cpp/third_party/curve25519/source/ed25519_signature.h +98 -0
- package/android/src/main/cpp/third_party/curve25519/source/ed25519_verify.c +313 -0
- package/android/src/main/cpp/third_party/curve25519/source/sha512.c +294 -0
- package/android/src/main/cpp/third_party/curve25519/source/sha512.h +93 -0
- package/android/src/main/cpp/third_party/dmap-parser/dmap_parser.c +545 -0
- package/android/src/main/cpp/third_party/dmap-parser/dmap_parser.h +90 -0
- package/android/src/main/cpp/third_party/libraop/aes.c +863 -0
- package/android/src/main/cpp/third_party/libraop/aes.h +18 -0
- package/android/src/main/cpp/third_party/libraop/aes_ctr.c +89 -0
- package/android/src/main/cpp/third_party/libraop/aes_ctr.h +59 -0
- package/android/src/main/cpp/third_party/libraop/alac.c +1135 -0
- package/android/src/main/cpp/third_party/libraop/alac.h +55 -0
- package/android/src/main/cpp/third_party/libraop/raop_client.c +1500 -0
- package/android/src/main/cpp/third_party/libraop/raop_client.h +178 -0
- package/android/src/main/cpp/third_party/libraop/rtsp_client.c +743 -0
- package/android/src/main/cpp/third_party/libraop/rtsp_client.h +50 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/__DECC_INCLUDE_EPILOGUE.H +22 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/__DECC_INCLUDE_PROLOGUE.H +26 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/aes.h +111 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/asn1.h +1134 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/asn1.h.in +967 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/asn1err.h +142 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/asn1t.h +946 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/asn1t.h.in +923 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/async.h +104 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/asyncerr.h +29 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/bio.h +1022 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/bio.h.in +999 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/bioerr.h +72 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/blowfish.h +78 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/bn.h +590 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/bnerr.h +47 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/buffer.h +62 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/buffererr.h +25 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/byteorder.h +339 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/camellia.h +117 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/cast.h +71 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/cmac.h +52 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/cmp.h +727 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/cmp.h.in +584 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/cmp_util.h +56 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/cmperr.h +134 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/cms.h +511 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/cms.h.in +413 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/cmserr.h +126 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/comp.h +98 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/comp.h.in +76 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/comperr.h +38 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/conf.h +214 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/conf.h.in +177 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/conf_api.h +46 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/conferr.h +52 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/configuration.h +212 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/configuration.h.in +75 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/conftypes.h +44 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/core.h +236 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/core_dispatch.h +1141 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/core_names.h +575 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/core_names.h.in +126 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/core_object.h +41 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/crmf.h +278 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/crmf.h.in +207 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/crmferr.h +57 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/crypto.h +583 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/crypto.h.in +560 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/cryptoerr.h +56 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/cryptoerr_legacy.h +1466 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/ct.h +573 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/ct.h.in +525 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/cterr.h +45 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/decoder.h +133 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/decodererr.h +28 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/des.h +211 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/dh.h +339 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/dherr.h +59 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/dsa.h +280 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/dsaerr.h +44 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/dtls1.h +57 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/e_os2.h +310 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/e_ostime.h +38 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/ebcdic.h +39 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/ec.h +1588 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/ecdh.h +10 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/ecdsa.h +10 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/ecerr.h +104 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/encoder.h +124 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/encodererr.h +28 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/engine.h +833 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/engineerr.h +63 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/err.h +512 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/err.h.in +501 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/ess.h +128 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/ess.h.in +81 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/esserr.h +32 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/evp.h +2310 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/evperr.h +142 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/fips_names.h +50 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/fipskey.h +41 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/fipskey.h.in +40 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/hmac.h +62 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/hpke.h +169 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/http.h +119 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/httperr.h +56 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/idea.h +82 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/indicator.h +31 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/kdf.h +138 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/kdferr.h +16 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/lhash.h +398 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/lhash.h.in +373 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/macros.h +349 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/md2.h +56 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/md4.h +63 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/md5.h +62 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/mdc2.h +55 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/ml_kem.h +31 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/modes.h +219 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/obj_mac.h +6636 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/objects.h +184 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/objectserr.h +28 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/ocsp.h +483 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/ocsp.h.in +387 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/ocsperr.h +53 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/opensslconf.h +17 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/opensslv.h +114 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/opensslv.h.in +113 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/ossl_typ.h +16 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/param_build.h +63 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/params.h +163 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/pem.h +547 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/pem2.h +19 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/pemerr.h +59 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/pkcs12.h +366 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/pkcs12.h.in +343 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/pkcs12err.h +46 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/pkcs7.h +430 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/pkcs7.h.in +359 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/pkcs7err.h +63 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/prov_ssl.h +38 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/proverr.h +169 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/provider.h +94 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/quic.h +75 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/rand.h +131 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/randerr.h +70 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/rc2.h +68 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/rc4.h +47 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/rc5.h +79 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/ripemd.h +59 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/rsa.h +615 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/rsaerr.h +107 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/safestack.h +297 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/safestack.h.in +227 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/seed.h +113 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/self_test.h +112 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/sha.h +139 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/srp.h +285 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/srp.h.in +214 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/srtp.h +68 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/ssl.h +2933 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/ssl.h.in +2886 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/ssl2.h +30 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/ssl3.h +358 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/sslerr.h +382 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/sslerr_legacy.h +467 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/stack.h +90 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/store.h +377 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/storeerr.h +49 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/symhacks.h +39 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/thread.h +31 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/tls1.h +1220 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/trace.h +321 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/ts.h +522 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/tserr.h +67 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/txt_db.h +63 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/types.h +248 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/ui.h +407 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/ui.h.in +384 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/uierr.h +38 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/whrlpool.h +62 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/x509.h +1303 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/x509.h.in +1109 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/x509_acert.h +294 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/x509_acert.h.in +199 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/x509_vfy.h +903 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/x509_vfy.h.in +806 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/x509err.h +70 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/x509v3.h +1968 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/x509v3.h.in +1367 -0
- package/android/src/main/cpp/third_party/openssl/include/openssl/x509v3err.h +97 -0
- package/android/src/main/cpp/third_party/pair_ap/pair-internal.h +390 -0
- package/android/src/main/cpp/third_party/pair_ap/pair-tlv.c +221 -0
- package/android/src/main/cpp/third_party/pair_ap/pair-tlv.h +77 -0
- package/android/src/main/cpp/third_party/pair_ap/pair.c +806 -0
- package/android/src/main/cpp/third_party/pair_ap/pair.h +266 -0
- package/android/src/main/cpp/third_party/pair_ap/pair_fruit_stub.c +36 -0
- package/android/src/main/cpp/third_party/pair_ap/pair_homekit.c +3190 -0
- package/android/src/main/cpp/third_party/signalsmith/LICENSE-signalsmith-linear.txt +21 -0
- package/android/src/main/cpp/third_party/signalsmith/LICENSE-signalsmith-stretch.txt +21 -0
- package/android/src/main/cpp/third_party/signalsmith/THIRD_PARTY_VERSIONS.txt +9 -0
- package/android/src/main/cpp/third_party/signalsmith/include/signalsmith-linear/fft.h +1380 -0
- package/android/src/main/cpp/third_party/signalsmith/include/signalsmith-linear/linear.h +1075 -0
- package/android/src/main/cpp/third_party/signalsmith/include/signalsmith-linear/stft.h +643 -0
- package/android/src/main/cpp/third_party/signalsmith/include/signalsmith-stretch.h +1060 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/AirPlayEngine.kt +314 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/ArtworkContentProvider.kt +124 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/AudioFocusErrorMapping.kt +89 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/AudioPipelineRenderersFactory.kt +60 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/BrowseCallbackRegistry.kt +136 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/BrowseDataProvider.kt +128 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/BufferStateTranslator.kt +35 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/CacheMimeTypes.kt +79 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/CastManager.kt +629 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/CrossfadeEngine.kt +1350 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/CrossfadeForwardingPlayer.kt +66 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/CustomPresetStore.kt +100 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/Equalizer.kt +348 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/EqualizerEngine.kt +222 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/EqualizerLegacyEngine.kt +213 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/EqualizerPresets.kt +45 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/FFTProcessorTee.kt +173 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/FifoCacheEvictor.kt +96 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/GaplessEngine.kt +587 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/HeadlessJsMediaService.kt +220 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/IEqualizerEngine.kt +97 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/ListenerRegistry.kt +59 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/LookaheadCache.kt +343 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/LookaheadCacheWriter.kt +533 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/MediaButtonDispatch.kt +88 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/MediaItemBuilder.kt +281 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/MediaItemMapper.kt +76 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/MilestoneTracker.kt +66 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/MimeCapturingDataSource.kt +64 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/MultiplexingAudioBufferSink.kt +92 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/NotificationProvider.kt +37 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/NowPlayingFormatExtractor.kt +166 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/PendingBrowseRequests.kt +70 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/PendingIntentBuffer.kt +82 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/PitchAwareAudioProcessorChain.kt +69 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/PitchCorrection.kt +27 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/PlaceholderArtwork.kt +65 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/PlaceholderFallbackBitmapLoader.kt +75 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/PlaybackEngine.kt +336 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/PlaybackErrorMapping.kt +175 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/PlaybackModeStateMachine.kt +127 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/PlaybackService.kt +1716 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/PlaybackServiceCallback.kt +755 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/ProgressEmissionGate.kt +70 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/QueueMutationArithmetic.kt +131 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/QueuePlayerPackage.kt +22 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/QueueSkipArithmetic.kt +113 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/RadixTwoFFT.kt +176 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/RemoteCommandDeduper.kt +81 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/ReplayGainAudioProcessor.kt +84 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/ReplayGainConfig.kt +34 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/ReplayGainData.kt +44 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/ReplayGainExtractor.kt +209 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/ReplayGainGain.kt +34 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/SearchResultCache.kt +72 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/SessionCommandForwardingPlayer.kt +167 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/SignalsmithStretchAudioProcessor.kt +225 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/SignalsmithStretchNative.kt +93 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/SleepTimerCore.kt +125 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/TrackPlayer.kt +4242 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/TransportStateTranslator.kt +70 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/UrlSchemes.kt +9 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/VisualizationGate.kt +35 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/Visualizer.kt +240 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/VisualizerTeeBuilder.kt +63 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/VoiceSearchExtrasParser.kt +103 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/cast/AudioRouteState.kt +202 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/cast/AuthRequiredException.kt +14 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/cast/CastBackend.kt +41 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/cast/CastBackends.kt +56 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/cast/CastEventBridge.kt +122 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/cast/CastMediaItem.kt +20 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/cast/CastSession.kt +193 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/cast/CastSinkRouter.kt +95 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/cast/CastTransportRouter.kt +151 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/cast/DiscoveryState.kt +53 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/cast/MetadataAwareSession.kt +17 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/cast/PlaybackStateRouter.kt +65 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/cast/Receiver.kt +35 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/cast/airplay/AirPlay2JNI.kt +129 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/cast/airplay/AirPlay2MetadataSync.kt +189 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/cast/airplay/AirPlay2Session.kt +123 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/cast/airplay/AirPlay2Sink.kt +205 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/cast/airplay/AirPlayBackend.kt +585 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/cast/airplay/AirPlayBackendInitializer.kt +43 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/cast/airplay/AirPlayDiscovery.kt +511 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/cast/airplay/AirPlayDiscoveryLifecycleObserver.kt +57 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/cast/airplay/AirPlayMetadataSync.kt +199 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/cast/airplay/AirPlayReceiverMapper.kt +42 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/cast/airplay/AirPlayRenderersFactory.kt +43 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/cast/airplay/AirPlaySession.kt +101 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/cast/airplay/AirPlaySink.kt +265 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/cast/airplay/AirPlayTxtParser.kt +203 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/cast/airplay/AirplayJNI.kt +106 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/cast/airplay/MulticastLockHolder.kt +75 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/cast/chromecast/CastMediaItemConverter.kt +67 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/cast/chromecast/CastVolumeForwardingPlayer.kt +156 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/cast/chromecast/ChromecastBackend.kt +171 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/cast/chromecast/ChromecastOptionsProvider.kt +51 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/cast/chromecast/ChromecastReceiverMapper.kt +44 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/cast/chromecast/ChromecastSession.kt +544 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/cast/chromecast/MediaInfoBuilder.kt +92 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/cast/chromecast/RemoteMediaCallbacks.kt +113 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/cast/http/LocalMediaServer.kt +160 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/cast/http/LocalMediaServerLifecycle.kt +15 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/cast/http/MediaServerHandle.kt +44 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/cast/http/MediaTokenRegistry.kt +37 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/cast/http/MimeTypes.kt +27 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/cast/net/LocalAddressMonitor.kt +86 -0
- package/android/src/main/res/raw/rnqp_placeholder.jpg +0 -0
- package/android/src/main/res/values/cast_strings.xml +15 -0
- package/android/src/main/res/values/strings.xml +24 -0
- package/android/src/main/res/xml/automotive_app_desc.xml +15 -0
- package/android/src/test/java/androidx/media3/session/MediaSessionControllerRequestTestSeam.kt +27 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/ArtworkContentProviderTest.kt +124 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/AudioFocusErrorMappingTest.kt +122 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/AudioPipelineRenderersFactoryTest.kt +57 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/AvrcpMetadataTest.kt +264 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/BrowseCallbackRegistryTest.kt +104 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/BrowseDataProviderTest.kt +276 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/BufferStateTranslatorTest.kt +58 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/CacheMimeTypesTest.kt +116 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/CrossfadeEngineLifecycleTest.kt +214 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/CrossfadeEngineReplayGainTest.kt +180 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/CustomPresetStoreTest.kt +128 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/EqualizerEngineTest.kt +223 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/EqualizerKtTest.kt +274 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/EqualizerLegacyEngineTest.kt +214 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/EqualizerPresetsTest.kt +89 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/FFTProcessorTeeTest.kt +185 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/FifoCacheEvictorTest.kt +112 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/ForwardingPlayerTestAccess.kt +21 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/GaplessEngineLifecycleTest.kt +65 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/GaplessEngineReplayGainTest.kt +154 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/HeadlessJsMediaServiceTest.kt +106 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/LookaheadCacheTest.kt +183 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/LookaheadCacheWriterTest.kt +649 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/MediaButtonDispatchTest.kt +192 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/MediaItemBuilderTest.kt +389 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/MediaItemMapperTest.kt +145 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/MilestoneTrackerTest.kt +81 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/MultiplexingAudioBufferSinkTest.kt +112 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/NotificationProviderTest.kt +86 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/NowPlayingFormatExtractorTest.kt +106 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/PendingBrowseRequestsTest.kt +82 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/PendingIntentBufferTest.kt +192 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/PitchAwareAudioProcessorChainTest.kt +147 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/PitchCorrectionTest.kt +55 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/PlaceholderFallbackBitmapLoaderTest.kt +187 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/PlaybackEngineInterfaceTest.kt +134 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/PlaybackModeStateMachineTest.kt +157 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/PlaybackServiceArtworkLoaderTest.kt +95 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/PlaybackServiceCallbackBrowseTest.kt +480 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/PlaybackServiceCallbackSearchTest.kt +171 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/PlaybackServiceCallbackTest.kt +773 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/PlaybackServiceCastBindTest.kt +100 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/PlaybackServiceLifecycleTest.kt +315 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/PlaybackServiceSessionActivityTest.kt +121 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/PlayerCommandsForTest.kt +246 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/ProgressEmissionGateTest.kt +113 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/QueueMutationArithmeticTest.kt +252 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/QueueSkipArithmeticTest.kt +343 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/RadixTwoFFTTest.kt +109 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/RemoteCommandDeduperTest.kt +106 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/ReplayGainAudioProcessorTest.kt +141 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/ReplayGainConfigTest.kt +103 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/ReplayGainExtractorTest.kt +469 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/ReplayGainGainTest.kt +129 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/RobolectricServiceBindHelper.kt +83 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/SearchResultCacheTest.kt +128 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/ServiceReadyReasonTest.kt +42 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/SessionCommandForwardingPlayerTest.kt +521 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/SleepTimerCoreTest.kt +125 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/SmokeTest.kt +27 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/TrackPlayerAirPlayMetadataWiringTest.kt +305 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/TrackPlayerAudioFocusTest.kt +179 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/TrackPlayerEventsTest.kt +497 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/TrackPlayerLifecycleTest.kt +209 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/TrackPlayerLookaheadConfigTest.kt +417 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/TrackPlayerMutationTest.kt +473 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/TrackPlayerPitchCorrectionTest.kt +61 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/TrackPlayerPlaybackModeTest.kt +28 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/TrackPlayerProgressThrottleTest.kt +89 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/TrackPlayerQueueTest.kt +290 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/TrackPlayerReadersTest.kt +151 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/TrackPlayerReplayGainTest.kt +69 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/TrackPlayerSkipCapabilityTest.kt +324 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/TrackPlayerSkipTest.kt +287 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/TrackPlayerSourceClassifierTest.kt +82 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/TrackPlayerTransportTest.kt +222 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/TransportStateTranslatorTest.kt +287 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/VisualizationGateTest.kt +96 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/VisualizerKtTest.kt +202 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/VoiceSearchExtrasParserTest.kt +211 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/cast/CastSinkRouterTest.kt +120 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/cast/FakeRemotePlayer.kt +62 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/cast/PlaybackStateRouterTest.kt +43 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/cast/airplay/AirPlayDiscoveryFilterTest.kt +86 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/cast/airplay/AirPlayTxtParserClassificationTest.kt +34 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/cast/chromecast/CastMediaItemConverterTest.kt +78 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/cast/chromecast/CastVolumeForwardingPlayerTest.kt +176 -0
- package/app.plugin.js +466 -0
- package/ios/AVPlayerItemQueueItemId.swift +61 -0
- package/ios/AVQueueBuilder.swift +200 -0
- package/ios/Array+SafeSubscript.swift +6 -0
- package/ios/ArtworkLoader.swift +136 -0
- package/ios/ArtworkResolver.swift +87 -0
- package/ios/AudioCategoryMapping.swift +48 -0
- package/ios/AudioSession.swift +220 -0
- package/ios/AudioSessionError.swift +44 -0
- package/ios/AudioTapProvider.swift +647 -0
- package/ios/BiquadCoefficients.swift +80 -0
- package/ios/CarPlayBridge.swift +178 -0
- package/ios/CarPlayBrowseBuilder.swift +368 -0
- package/ios/CarPlayBrowseDataProvider.swift +162 -0
- package/ios/CarPlayCoordinator.swift +42 -0
- package/ios/CarPlaySceneDelegate.swift +199 -0
- package/ios/Cast/AirPlayRouteState.swift +281 -0
- package/ios/Cast/Chromecast/ChromecastDiscoveryAdapter.swift +27 -0
- package/ios/Cast/Chromecast/ChromecastReceiverMapper.swift +48 -0
- package/ios/Cast/Chromecast/ChromecastSession.swift +740 -0
- package/ios/Cast/Chromecast/ChromecastSessionAdapter.swift +114 -0
- package/ios/Cast/Chromecast/ChromecastSupport.swift +63 -0
- package/ios/Cast/Chromecast/MediaInfoBuilder.swift +104 -0
- package/ios/Cast/Chromecast/RemoteMediaObserver.swift +147 -0
- package/ios/Cast/Core/CastEventBridge.swift +210 -0
- package/ios/Cast/Core/CastMediaItem.swift +41 -0
- package/ios/Cast/Core/CastNowPlayingController.swift +310 -0
- package/ios/Cast/Core/CastReceiverState.swift +22 -0
- package/ios/Cast/Core/CastSession.swift +147 -0
- package/ios/Cast/Core/CastTransportRouter.swift +162 -0
- package/ios/Cast/Core/ChromecastBackend.swift +259 -0
- package/ios/Cast/Core/LocalAddressMonitor.swift +110 -0
- package/ios/Cast/Core/LocalMediaServer.swift +270 -0
- package/ios/Cast/Core/LocalNetworkPermissionProbe.swift +265 -0
- package/ios/Cast/Core/MediaHTTPConnection.swift +349 -0
- package/ios/Cast/Core/MediaServerHandle.swift +49 -0
- package/ios/Cast/Core/MediaTokenRegistry.swift +51 -0
- package/ios/Cast/Core/MimeTypes.swift +26 -0
- package/ios/Cast/Core/PlaybackStateRouter.swift +123 -0
- package/ios/CastManager.swift +493 -0
- package/ios/CrossfadeEngine.swift +1343 -0
- package/ios/CustomPresetStore.swift +78 -0
- package/ios/EQProcessor.swift +321 -0
- package/ios/EQTap.swift +241 -0
- package/ios/Equalizer.swift +321 -0
- package/ios/EqualizerPresets.swift +48 -0
- package/ios/FFTProcessor.swift +237 -0
- package/ios/GaplessEngine.swift +385 -0
- package/ios/InputGuards.swift +63 -0
- package/ios/InterruptionEventMapping.swift +51 -0
- package/ios/ListenerRegistry.swift +73 -0
- package/ios/LookaheadCache.swift +833 -0
- package/ios/LookaheadCacheEviction.swift +83 -0
- package/ios/LookaheadCachePrefetcher.swift +503 -0
- package/ios/MetadataReader.swift +555 -0
- package/ios/MilestoneTracker.swift +63 -0
- package/ios/NowPlayingFormatExtractor.swift +362 -0
- package/ios/NowPlayingInfo.swift +190 -0
- package/ios/OutputRouteMonitor.swift +125 -0
- package/ios/PendingBrowseRequests.swift +62 -0
- package/ios/PitchAlgorithm.swift +24 -0
- package/ios/PlaceholderArtwork.swift +46 -0
- package/ios/PlaybackEngine.swift +319 -0
- package/ios/PlaybackErrorMapping.swift +195 -0
- package/ios/PlaybackModeStateMachine.swift +159 -0
- package/ios/PlayerStateDerivation.swift +45 -0
- package/ios/ProgressEmissionGate.swift +54 -0
- package/ios/QueueMutationArithmetic.swift +129 -0
- package/ios/QueueSkipArithmetic.swift +109 -0
- package/ios/QueueState.swift +49 -0
- package/ios/RemoteCommands.swift +229 -0
- package/ios/ReplayGainData.swift +58 -0
- package/ios/ReplayGainExtractor.swift +82 -0
- package/ios/ReplayGainProcessor.swift +46 -0
- package/ios/Resources/RNQP-placeholder.jpg +0 -0
- package/ios/Resources/silence.m4a +0 -0
- package/ios/Siri/PendingIntentBuffer.swift +100 -0
- package/ios/Siri/PlayMediaIntentHandler.swift +283 -0
- package/ios/Siri/QueuePlayerMediaIntents.swift +45 -0
- package/ios/Siri/VoiceDonation.swift +50 -0
- package/ios/SleepTimerCore.swift +128 -0
- package/ios/StreamingBitrateProbe.swift +318 -0
- package/ios/Tests/AVQueueBuilderTests.swift +430 -0
- package/ios/Tests/ArtworkResolverTests.swift +540 -0
- package/ios/Tests/AudioSessionTests.swift +222 -0
- package/ios/Tests/AudioTapProviderReplayGainTests.swift +136 -0
- package/ios/Tests/AudioTapProviderVisualizationFlagTests.swift +104 -0
- package/ios/Tests/BiquadCoefficientsTests.swift +84 -0
- package/ios/Tests/CarPlayBridgeTests.swift +91 -0
- package/ios/Tests/CarPlayBrowseBuilderTests.swift +221 -0
- package/ios/Tests/CarPlayBrowseDataProviderTests.swift +218 -0
- package/ios/Tests/CastNowPlayingControllerTests.swift +204 -0
- package/ios/Tests/CrossfadeEngineStubTests.swift +43 -0
- package/ios/Tests/EQProcessorTests.swift +302 -0
- package/ios/Tests/EQTapTests.swift +49 -0
- package/ios/Tests/EqualizerAudioMixProviderTests.swift +110 -0
- package/ios/Tests/EqualizerHybridTests.swift +303 -0
- package/ios/Tests/EqualizerPresetsTests.swift +69 -0
- package/ios/Tests/FFTProcessorTests.swift +303 -0
- package/ios/Tests/Fixtures/silence-aac-128.m4a +0 -0
- package/ios/Tests/Fixtures/silence-cbr-128.mp3 +0 -0
- package/ios/Tests/Fixtures/silence-vbr.mp3 +0 -0
- package/ios/Tests/GaplessEngineLifecycleTests.swift +160 -0
- package/ios/Tests/InputGuardsTests.swift +75 -0
- package/ios/Tests/InterruptionEventMappingTests.swift +91 -0
- package/ios/Tests/LookaheadCacheEvictionTests.swift +217 -0
- package/ios/Tests/LookaheadCachePrefetcherTests.swift +630 -0
- package/ios/Tests/LookaheadCacheRuntimeConfigTests.swift +247 -0
- package/ios/Tests/LookaheadCacheTests.swift +717 -0
- package/ios/Tests/MediaHTTPConnectionTests.swift +163 -0
- package/ios/Tests/MetadataReaderTests.swift +605 -0
- package/ios/Tests/MilestoneTrackerTests.swift +76 -0
- package/ios/Tests/NowPlayingFormatExtractorTests.swift +158 -0
- package/ios/Tests/NowPlayingInfoTests.swift +292 -0
- package/ios/Tests/PendingBrowseRequestsTests.swift +69 -0
- package/ios/Tests/PendingIntentBufferTests.swift +164 -0
- package/ios/Tests/PlaybackEngineProtocolTests.swift +92 -0
- package/ios/Tests/PlaybackErrorMappingTests.swift +179 -0
- package/ios/Tests/PlaybackModeStateMachineTests.swift +40 -0
- package/ios/Tests/PlaybackStateRouterTests.swift +178 -0
- package/ios/Tests/PlayerStateDerivationTests.swift +69 -0
- package/ios/Tests/ProgressEmissionGateTests.swift +113 -0
- package/ios/Tests/QueueMutationArithmeticTests.swift +245 -0
- package/ios/Tests/RemoteCommandsTests.swift +147 -0
- package/ios/Tests/ReplayGainExtractorTests.swift +197 -0
- package/ios/Tests/ReplayGainProcessorTests.swift +90 -0
- package/ios/Tests/SkipCapabilityTests.swift +98 -0
- package/ios/Tests/SkipIndexTests.swift +259 -0
- package/ios/Tests/SleepTimerCoreTests.swift +98 -0
- package/ios/Tests/StreamingBitrateProbeTests.swift +29 -0
- package/ios/Tests/TrackSourceClassifierTests.swift +50 -0
- package/ios/Tests/VoiceDonationTests.swift +26 -0
- package/ios/TrackPlayer.swift +4766 -0
- package/ios/Visualizer.swift +274 -0
- package/ios/WindowApplicationSceneDelegate.swift +59 -0
- package/ios/tests-harness/Podfile +56 -0
- package/ios/tests-harness/TestHost/App.swift +12 -0
- package/ios/tests-harness/TestHost/Info.plist +37 -0
- package/ios/tests-harness/TestHost.xcodeproj/project.pbxproj +472 -0
- package/ios/tests-harness/TestHost.xcodeproj/xcshareddata/xcschemes/TestHost.xcscheme +68 -0
- package/ios/tests-harness/package.json +10 -0
- package/ios/tests-harness/scripts/seed-xcodeproj.rb +118 -0
- package/lib/module/CastManager.nitro.js +4 -0
- package/lib/module/CastManager.nitro.js.map +1 -0
- package/lib/module/Equalizer.nitro.js +4 -0
- package/lib/module/Equalizer.nitro.js.map +1 -0
- package/lib/module/TrackPlayer.nitro.js +4 -0
- package/lib/module/TrackPlayer.nitro.js.map +1 -0
- package/lib/module/Visualizer.nitro.js +4 -0
- package/lib/module/Visualizer.nitro.js.map +1 -0
- package/lib/module/cast/index.js +156 -0
- package/lib/module/cast/index.js.map +1 -0
- package/lib/module/clients.js +43 -0
- package/lib/module/clients.js.map +1 -0
- package/lib/module/equalizer.js +85 -0
- package/lib/module/equalizer.js.map +1 -0
- package/lib/module/hooks/index.js +16 -0
- package/lib/module/hooks/index.js.map +1 -0
- package/lib/module/hooks/useActiveTrack.js +50 -0
- package/lib/module/hooks/useActiveTrack.js.map +1 -0
- package/lib/module/hooks/useAudioRoute.js +60 -0
- package/lib/module/hooks/useAudioRoute.js.map +1 -0
- package/lib/module/hooks/useBufferState.js +34 -0
- package/lib/module/hooks/useBufferState.js.map +1 -0
- package/lib/module/hooks/useCanSkip.js +67 -0
- package/lib/module/hooks/useCanSkip.js.map +1 -0
- package/lib/module/hooks/useCast.js +107 -0
- package/lib/module/hooks/useCast.js.map +1 -0
- package/lib/module/hooks/useEqualizer.js +91 -0
- package/lib/module/hooks/useEqualizer.js.map +1 -0
- package/lib/module/hooks/useFullyBuffered.js +33 -0
- package/lib/module/hooks/useFullyBuffered.js.map +1 -0
- package/lib/module/hooks/useLookaheadCache.js +49 -0
- package/lib/module/hooks/useLookaheadCache.js.map +1 -0
- package/lib/module/hooks/useNowPlayingFormat.js +42 -0
- package/lib/module/hooks/useNowPlayingFormat.js.map +1 -0
- package/lib/module/hooks/usePlaybackState.js +36 -0
- package/lib/module/hooks/usePlaybackState.js.map +1 -0
- package/lib/module/hooks/useProgress.js +31 -0
- package/lib/module/hooks/useProgress.js.map +1 -0
- package/lib/module/hooks/useSleepTimer.js +65 -0
- package/lib/module/hooks/useSleepTimer.js.map +1 -0
- package/lib/module/hooks/useVisualizerState.js +99 -0
- package/lib/module/hooks/useVisualizerState.js.map +1 -0
- package/lib/module/index.js +37 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/module/playbackService.js +174 -0
- package/lib/module/playbackService.js.map +1 -0
- package/lib/module/types.js +592 -0
- package/lib/module/types.js.map +1 -0
- package/lib/typescript/CastManager.nitro.d.ts +154 -0
- package/lib/typescript/CastManager.nitro.d.ts.map +1 -0
- package/lib/typescript/Equalizer.nitro.d.ts +30 -0
- package/lib/typescript/Equalizer.nitro.d.ts.map +1 -0
- package/lib/typescript/TrackPlayer.nitro.d.ts +584 -0
- package/lib/typescript/TrackPlayer.nitro.d.ts.map +1 -0
- package/lib/typescript/Visualizer.nitro.d.ts +36 -0
- package/lib/typescript/Visualizer.nitro.d.ts.map +1 -0
- package/lib/typescript/cast/index.d.ts +65 -0
- package/lib/typescript/cast/index.d.ts.map +1 -0
- package/lib/typescript/clients.d.ts +9 -0
- package/lib/typescript/clients.d.ts.map +1 -0
- package/lib/typescript/equalizer.d.ts +45 -0
- package/lib/typescript/equalizer.d.ts.map +1 -0
- package/lib/typescript/hooks/index.d.ts +22 -0
- package/lib/typescript/hooks/index.d.ts.map +1 -0
- package/lib/typescript/hooks/useActiveTrack.d.ts +21 -0
- package/lib/typescript/hooks/useActiveTrack.d.ts.map +1 -0
- package/lib/typescript/hooks/useAudioRoute.d.ts +13 -0
- package/lib/typescript/hooks/useAudioRoute.d.ts.map +1 -0
- package/lib/typescript/hooks/useBufferState.d.ts +18 -0
- package/lib/typescript/hooks/useBufferState.d.ts.map +1 -0
- package/lib/typescript/hooks/useCanSkip.d.ts +43 -0
- package/lib/typescript/hooks/useCanSkip.d.ts.map +1 -0
- package/lib/typescript/hooks/useCast.d.ts +32 -0
- package/lib/typescript/hooks/useCast.d.ts.map +1 -0
- package/lib/typescript/hooks/useEqualizer.d.ts +20 -0
- package/lib/typescript/hooks/useEqualizer.d.ts.map +1 -0
- package/lib/typescript/hooks/useFullyBuffered.d.ts +15 -0
- package/lib/typescript/hooks/useFullyBuffered.d.ts.map +1 -0
- package/lib/typescript/hooks/useLookaheadCache.d.ts +13 -0
- package/lib/typescript/hooks/useLookaheadCache.d.ts.map +1 -0
- package/lib/typescript/hooks/useNowPlayingFormat.d.ts +18 -0
- package/lib/typescript/hooks/useNowPlayingFormat.d.ts.map +1 -0
- package/lib/typescript/hooks/usePlaybackState.d.ts +9 -0
- package/lib/typescript/hooks/usePlaybackState.d.ts.map +1 -0
- package/lib/typescript/hooks/useProgress.d.ts +15 -0
- package/lib/typescript/hooks/useProgress.d.ts.map +1 -0
- package/lib/typescript/hooks/useSleepTimer.d.ts +26 -0
- package/lib/typescript/hooks/useSleepTimer.d.ts.map +1 -0
- package/lib/typescript/hooks/useVisualizerState.d.ts +40 -0
- package/lib/typescript/hooks/useVisualizerState.d.ts.map +1 -0
- package/lib/typescript/index.d.ts +14 -0
- package/lib/typescript/index.d.ts.map +1 -0
- package/lib/typescript/package.json +1 -0
- package/lib/typescript/playbackService.d.ts +140 -0
- package/lib/typescript/playbackService.d.ts.map +1 -0
- package/lib/typescript/types.d.ts +1215 -0
- package/lib/typescript/types.d.ts.map +1 -0
- package/nitro.json +53 -0
- package/nitrogen/generated/android/c++/JAudioCategoryOptions.hpp +65 -0
- package/nitrogen/generated/android/c++/JAudioCodec.hpp +73 -0
- package/nitrogen/generated/android/c++/JAudioContainer.hpp +76 -0
- package/nitrogen/generated/android/c++/JAudioContentType.hpp +58 -0
- package/nitrogen/generated/android/c++/JAudioRoute.hpp +75 -0
- package/nitrogen/generated/android/c++/JAudioRouteKind.hpp +91 -0
- package/nitrogen/generated/android/c++/JBrowseItem.hpp +78 -0
- package/nitrogen/generated/android/c++/JBrowseSection.hpp +97 -0
- package/nitrogen/generated/android/c++/JBrowseSnapshot.hpp +87 -0
- package/nitrogen/generated/android/c++/JBufferState.hpp +64 -0
- package/nitrogen/generated/android/c++/JCacheStatus.hpp +92 -0
- package/nitrogen/generated/android/c++/JCastConfigureOptions.hpp +62 -0
- package/nitrogen/generated/android/c++/JCastConnectOptions.hpp +57 -0
- package/nitrogen/generated/android/c++/JCastDeviceKind.hpp +70 -0
- package/nitrogen/generated/android/c++/JCastDiscoveryState.hpp +57 -0
- package/nitrogen/generated/android/c++/JCastLocalNetworkPermission.hpp +61 -0
- package/nitrogen/generated/android/c++/JCastLocalNetworkPermissionEvent.hpp +58 -0
- package/nitrogen/generated/android/c++/JCastProtocol.hpp +67 -0
- package/nitrogen/generated/android/c++/JCastReceiver.hpp +89 -0
- package/nitrogen/generated/android/c++/JCastReceiverCapabilities.hpp +66 -0
- package/nitrogen/generated/android/c++/JCastRoute.hpp +85 -0
- package/nitrogen/generated/android/c++/JCastSessionDiedEvent.hpp +63 -0
- package/nitrogen/generated/android/c++/JCastSessionEndReason.hpp +76 -0
- package/nitrogen/generated/android/c++/JCastStreamingModel.hpp +58 -0
- package/nitrogen/generated/android/c++/JEqualizerBand.hpp +61 -0
- package/nitrogen/generated/android/c++/JEqualizerPreset.hpp +76 -0
- package/nitrogen/generated/android/c++/JEvictionPolicy.hpp +58 -0
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__vector_BrowseItem______std__string.hpp +146 -0
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__vector_TrackItem______MediaSearchRequest.hpp +161 -0
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__vector_TrackItem______std__string.hpp +147 -0
- package/nitrogen/generated/android/c++/JFunc_void.hpp +75 -0
- package/nitrogen/generated/android/c++/JFunc_void_AudioRoute.hpp +80 -0
- package/nitrogen/generated/android/c++/JFunc_void_BufferState.hpp +77 -0
- package/nitrogen/generated/android/c++/JFunc_void_CacheStatus.hpp +79 -0
- package/nitrogen/generated/android/c++/JFunc_void_CastDiscoveryState.hpp +77 -0
- package/nitrogen/generated/android/c++/JFunc_void_CastLocalNetworkPermissionEvent.hpp +79 -0
- package/nitrogen/generated/android/c++/JFunc_void_CastRoute.hpp +86 -0
- package/nitrogen/generated/android/c++/JFunc_void_CastSessionDiedEvent.hpp +80 -0
- package/nitrogen/generated/android/c++/JFunc_void_PlaybackError.hpp +80 -0
- package/nitrogen/generated/android/c++/JFunc_void_PlayerProgress.hpp +77 -0
- package/nitrogen/generated/android/c++/JFunc_void_PlayerState_StateChangeReason.hpp +79 -0
- package/nitrogen/generated/android/c++/JFunc_void_ServiceReadyReason.hpp +77 -0
- package/nitrogen/generated/android/c++/JFunc_void_SkipCapability.hpp +77 -0
- package/nitrogen/generated/android/c++/JFunc_void_SleepTimerState.hpp +78 -0
- package/nitrogen/generated/android/c++/JFunc_void_VisualizerErrorReason.hpp +77 -0
- package/nitrogen/generated/android/c++/JFunc_void_VisualizerFrame.hpp +80 -0
- package/nitrogen/generated/android/c++/JFunc_void_bool.hpp +75 -0
- package/nitrogen/generated/android/c++/JFunc_void_double_double.hpp +75 -0
- package/nitrogen/generated/android/c++/JFunc_void_std__optional_TrackItem__double_TrackChangeReason_std__optional_double_.hpp +82 -0
- package/nitrogen/generated/android/c++/JFunc_void_std__optional_std__variant_nitro__NullType__NowPlayingFormat__.hpp +93 -0
- package/nitrogen/generated/android/c++/JFunc_void_std__vector_CastReceiver_.hpp +105 -0
- package/nitrogen/generated/android/c++/JFunc_void_std__vector_EqualizerBand_.hpp +96 -0
- package/nitrogen/generated/android/c++/JHybridCastManagerSpec.cpp +388 -0
- package/nitrogen/generated/android/c++/JHybridCastManagerSpec.hpp +84 -0
- package/nitrogen/generated/android/c++/JHybridEqualizerSpec.cpp +233 -0
- package/nitrogen/generated/android/c++/JHybridEqualizerSpec.hpp +74 -0
- package/nitrogen/generated/android/c++/JHybridTrackPlayerSpec.cpp +1052 -0
- package/nitrogen/generated/android/c++/JHybridTrackPlayerSpec.hpp +130 -0
- package/nitrogen/generated/android/c++/JHybridVisualizerSpec.cpp +84 -0
- package/nitrogen/generated/android/c++/JHybridVisualizerSpec.hpp +64 -0
- package/nitrogen/generated/android/c++/JLookaheadCacheConfig.hpp +61 -0
- package/nitrogen/generated/android/c++/JMediaSearchOrigin.hpp +58 -0
- package/nitrogen/generated/android/c++/JMediaSearchQueueLocation.hpp +61 -0
- package/nitrogen/generated/android/c++/JMediaSearchReference.hpp +58 -0
- package/nitrogen/generated/android/c++/JMediaSearchReleaseDateRange.hpp +61 -0
- package/nitrogen/generated/android/c++/JMediaSearchRepeatMode.hpp +61 -0
- package/nitrogen/generated/android/c++/JMediaSearchRequest.hpp +126 -0
- package/nitrogen/generated/android/c++/JMediaSearchType.hpp +67 -0
- package/nitrogen/generated/android/c++/JNowPlayingFormat.hpp +123 -0
- package/nitrogen/generated/android/c++/JNowPlayingFormatAndroidExtras.hpp +71 -0
- package/nitrogen/generated/android/c++/JNowPlayingFormatIosExtras.hpp +61 -0
- package/nitrogen/generated/android/c++/JPitchCorrectionMode.hpp +61 -0
- package/nitrogen/generated/android/c++/JPlaybackError.hpp +87 -0
- package/nitrogen/generated/android/c++/JPlaybackErrorCode.hpp +88 -0
- package/nitrogen/generated/android/c++/JPlaybackMode.hpp +63 -0
- package/nitrogen/generated/android/c++/JPlaybackModeKind.hpp +58 -0
- package/nitrogen/generated/android/c++/JPlayerConfig.hpp +126 -0
- package/nitrogen/generated/android/c++/JPlayerProgress.hpp +65 -0
- package/nitrogen/generated/android/c++/JPlayerState.hpp +73 -0
- package/nitrogen/generated/android/c++/JRemoteControlOptions.hpp +66 -0
- package/nitrogen/generated/android/c++/JRemoteSkipMode.hpp +58 -0
- package/nitrogen/generated/android/c++/JRepeatMode.hpp +61 -0
- package/nitrogen/generated/android/c++/JReplayGainMode.hpp +61 -0
- package/nitrogen/generated/android/c++/JSectionIcon.hpp +91 -0
- package/nitrogen/generated/android/c++/JServiceReadyReason.hpp +58 -0
- package/nitrogen/generated/android/c++/JShuffleResult.hpp +88 -0
- package/nitrogen/generated/android/c++/JSkipCapability.hpp +61 -0
- package/nitrogen/generated/android/c++/JSleepTimerState.hpp +69 -0
- package/nitrogen/generated/android/c++/JStateChangeReason.hpp +73 -0
- package/nitrogen/generated/android/c++/JTrackChangeReason.hpp +73 -0
- package/nitrogen/generated/android/c++/JTrackItem.hpp +100 -0
- package/nitrogen/generated/android/c++/JTrackSource.hpp +61 -0
- package/nitrogen/generated/android/c++/JVariant_NullType_Double.cpp +26 -0
- package/nitrogen/generated/android/c++/JVariant_NullType_Double.hpp +69 -0
- package/nitrogen/generated/android/c++/JVariant_NullType_NowPlayingFormat.cpp +26 -0
- package/nitrogen/generated/android/c++/JVariant_NullType_NowPlayingFormat.hpp +83 -0
- package/nitrogen/generated/android/c++/JVariant_NullType_String.cpp +26 -0
- package/nitrogen/generated/android/c++/JVariant_NullType_String.hpp +70 -0
- package/nitrogen/generated/android/c++/JVisualizerConfig.hpp +65 -0
- package/nitrogen/generated/android/c++/JVisualizerErrorReason.hpp +64 -0
- package/nitrogen/generated/android/c++/JVisualizerFrame.hpp +67 -0
- package/nitrogen/generated/android/c++/JVoiceVocabulary.hpp +98 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/AudioCategoryOptions.kt +61 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/AudioCodec.kt +28 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/AudioContainer.kt +29 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/AudioContentType.kt +23 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/AudioRoute.kt +71 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/AudioRouteKind.kt +34 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/BrowseItem.kt +76 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/BrowseSection.kt +71 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/BrowseSnapshot.kt +56 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/BufferState.kt +25 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/CacheStatus.kt +71 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/CastConfigureOptions.kt +56 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/CastConnectOptions.kt +51 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/CastDeviceKind.kt +27 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/CastDiscoveryState.kt +51 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/CastLocalNetworkPermission.kt +24 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/CastLocalNetworkPermissionEvent.kt +51 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/CastProtocol.kt +26 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/CastReceiver.kt +81 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/CastReceiverCapabilities.kt +61 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/CastRoute.kt +76 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/CastSessionDiedEvent.kt +56 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/CastSessionEndReason.kt +29 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/CastStreamingModel.kt +23 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/EqualizerBand.kt +56 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/EqualizerPreset.kt +61 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/EvictionPolicy.kt +23 -0
- 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
- 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
- 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
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/Func_void.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/Func_void_AudioRoute.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/Func_void_BufferState.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/Func_void_CacheStatus.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/Func_void_CastDiscoveryState.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/Func_void_CastLocalNetworkPermissionEvent.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/Func_void_CastRoute.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/Func_void_CastSessionDiedEvent.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/Func_void_PlaybackError.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/Func_void_PlayerProgress.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/Func_void_PlayerState_StateChangeReason.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/Func_void_ServiceReadyReason.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/Func_void_SkipCapability.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/Func_void_SleepTimerState.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/Func_void_VisualizerErrorReason.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/Func_void_VisualizerFrame.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/Func_void_bool.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/Func_void_double_double.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/Func_void_std__optional_TrackItem__double_TrackChangeReason_std__optional_double_.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/Func_void_std__optional_std__variant_nitro__NullType__NowPlayingFormat__.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/Func_void_std__vector_CastReceiver_.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/Func_void_std__vector_EqualizerBand_.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/HybridCastManagerSpec.kt +169 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/HybridEqualizerSpec.kt +109 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/HybridTrackPlayerSpec.kt +419 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/HybridVisualizerSpec.kt +63 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/LookaheadCacheConfig.kt +56 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/MediaSearchOrigin.kt +23 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/MediaSearchQueueLocation.kt +24 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/MediaSearchReference.kt +23 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/MediaSearchReleaseDateRange.kt +56 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/MediaSearchRepeatMode.kt +24 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/MediaSearchRequest.kt +121 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/MediaSearchType.kt +26 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/NowPlayingFormat.kt +116 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/NowPlayingFormatAndroidExtras.kt +61 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/NowPlayingFormatIosExtras.kt +51 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/PitchCorrectionMode.kt +24 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/PlaybackError.kt +86 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/PlaybackErrorCode.kt +33 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/PlaybackMode.kt +56 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/PlaybackModeKind.kt +23 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/PlayerConfig.kt +111 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/PlayerProgress.kt +61 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/PlayerState.kt +28 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/RemoteControlOptions.kt +61 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/RemoteSkipMode.kt +23 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/RepeatMode.kt +24 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/ReplayGainMode.kt +24 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/SectionIcon.kt +34 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/ServiceReadyReason.kt +23 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/ShuffleResult.kt +61 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/SkipCapability.kt +56 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/SleepTimerState.kt +66 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/StateChangeReason.kt +28 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/TrackChangeReason.kt +28 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/TrackItem.kt +86 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/TrackSource.kt +24 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/Variant_NullType_Double.kt +62 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/Variant_NullType_NowPlayingFormat.kt +62 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/Variant_NullType_String.kt +62 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/VisualizerConfig.kt +61 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/VisualizerErrorReason.kt +25 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/VisualizerFrame.kt +61 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/VoiceVocabulary.kt +56 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/queueplayerOnLoad.kt +35 -0
- package/nitrogen/generated/android/queueplayer+autolinking.cmake +90 -0
- package/nitrogen/generated/android/queueplayer+autolinking.gradle +27 -0
- package/nitrogen/generated/android/queueplayerOnLoad.cpp +152 -0
- package/nitrogen/generated/android/queueplayerOnLoad.hpp +34 -0
- package/nitrogen/generated/ios/QueuePlayer+autolinking.rb +62 -0
- package/nitrogen/generated/ios/QueuePlayer-Swift-Cxx-Bridge.cpp +343 -0
- package/nitrogen/generated/ios/QueuePlayer-Swift-Cxx-Bridge.hpp +1831 -0
- package/nitrogen/generated/ios/QueuePlayer-Swift-Cxx-Umbrella.hpp +256 -0
- package/nitrogen/generated/ios/QueuePlayerAutolinking.mm +57 -0
- package/nitrogen/generated/ios/QueuePlayerAutolinking.swift +62 -0
- package/nitrogen/generated/ios/c++/HybridCastManagerSpecSwift.cpp +11 -0
- package/nitrogen/generated/ios/c++/HybridCastManagerSpecSwift.hpp +298 -0
- package/nitrogen/generated/ios/c++/HybridEqualizerSpecSwift.cpp +11 -0
- package/nitrogen/generated/ios/c++/HybridEqualizerSpecSwift.hpp +178 -0
- package/nitrogen/generated/ios/c++/HybridTrackPlayerSpecSwift.cpp +11 -0
- package/nitrogen/generated/ios/c++/HybridTrackPlayerSpecSwift.hpp +749 -0
- package/nitrogen/generated/ios/c++/HybridVisualizerSpecSwift.cpp +11 -0
- package/nitrogen/generated/ios/c++/HybridVisualizerSpecSwift.hpp +103 -0
- package/nitrogen/generated/ios/swift/AudioCategoryOptions.swift +78 -0
- package/nitrogen/generated/ios/swift/AudioCodec.swift +60 -0
- package/nitrogen/generated/ios/swift/AudioContainer.swift +64 -0
- package/nitrogen/generated/ios/swift/AudioContentType.swift +40 -0
- package/nitrogen/generated/ios/swift/AudioRoute.swift +49 -0
- package/nitrogen/generated/ios/swift/AudioRouteKind.swift +84 -0
- package/nitrogen/generated/ios/swift/BrowseItem.swift +93 -0
- package/nitrogen/generated/ios/swift/BrowseSection.swift +74 -0
- package/nitrogen/generated/ios/swift/BrowseSnapshot.swift +40 -0
- package/nitrogen/generated/ios/swift/BufferState.swift +48 -0
- package/nitrogen/generated/ios/swift/CacheStatus.swift +55 -0
- package/nitrogen/generated/ios/swift/CastConfigureOptions.swift +47 -0
- package/nitrogen/generated/ios/swift/CastConnectOptions.swift +29 -0
- package/nitrogen/generated/ios/swift/CastDeviceKind.swift +56 -0
- package/nitrogen/generated/ios/swift/CastDiscoveryState.swift +29 -0
- package/nitrogen/generated/ios/swift/CastLocalNetworkPermission.swift +44 -0
- package/nitrogen/generated/ios/swift/CastLocalNetworkPermissionEvent.swift +29 -0
- package/nitrogen/generated/ios/swift/CastProtocol.swift +52 -0
- package/nitrogen/generated/ios/swift/CastReceiver.swift +59 -0
- package/nitrogen/generated/ios/swift/CastReceiverCapabilities.swift +39 -0
- package/nitrogen/generated/ios/swift/CastRoute.swift +54 -0
- package/nitrogen/generated/ios/swift/CastSessionDiedEvent.swift +34 -0
- package/nitrogen/generated/ios/swift/CastSessionEndReason.swift +64 -0
- package/nitrogen/generated/ios/swift/CastStreamingModel.swift +40 -0
- package/nitrogen/generated/ios/swift/EqualizerBand.swift +34 -0
- package/nitrogen/generated/ios/swift/EqualizerPreset.swift +45 -0
- package/nitrogen/generated/ios/swift/EvictionPolicy.swift +40 -0
- package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__vector_BrowseItem______std__string.swift +67 -0
- package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__vector_TrackItem______MediaSearchRequest.swift +67 -0
- package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__vector_TrackItem______std__string.swift +67 -0
- package/nitrogen/generated/ios/swift/Func_void.swift +46 -0
- package/nitrogen/generated/ios/swift/Func_void_AudioRoute.swift +46 -0
- package/nitrogen/generated/ios/swift/Func_void_BufferState.swift +46 -0
- package/nitrogen/generated/ios/swift/Func_void_CacheStatus.swift +46 -0
- package/nitrogen/generated/ios/swift/Func_void_CastDiscoveryState.swift +46 -0
- package/nitrogen/generated/ios/swift/Func_void_CastLocalNetworkPermission.swift +46 -0
- package/nitrogen/generated/ios/swift/Func_void_CastLocalNetworkPermissionEvent.swift +46 -0
- package/nitrogen/generated/ios/swift/Func_void_CastRoute.swift +46 -0
- package/nitrogen/generated/ios/swift/Func_void_CastSessionDiedEvent.swift +46 -0
- package/nitrogen/generated/ios/swift/Func_void_PlaybackError.swift +46 -0
- package/nitrogen/generated/ios/swift/Func_void_PlayerProgress.swift +46 -0
- package/nitrogen/generated/ios/swift/Func_void_PlayerState_StateChangeReason.swift +46 -0
- package/nitrogen/generated/ios/swift/Func_void_ServiceReadyReason.swift +46 -0
- package/nitrogen/generated/ios/swift/Func_void_ShuffleResult.swift +46 -0
- package/nitrogen/generated/ios/swift/Func_void_SkipCapability.swift +46 -0
- package/nitrogen/generated/ios/swift/Func_void_SleepTimerState.swift +46 -0
- package/nitrogen/generated/ios/swift/Func_void_VisualizerErrorReason.swift +46 -0
- package/nitrogen/generated/ios/swift/Func_void_VisualizerFrame.swift +46 -0
- package/nitrogen/generated/ios/swift/Func_void_bool.swift +46 -0
- package/nitrogen/generated/ios/swift/Func_void_double_double.swift +46 -0
- package/nitrogen/generated/ios/swift/Func_void_std__exception_ptr.swift +46 -0
- package/nitrogen/generated/ios/swift/Func_void_std__optional_TrackItem__double_TrackChangeReason_std__optional_double_.swift +53 -0
- package/nitrogen/generated/ios/swift/Func_void_std__optional_std__variant_nitro__NullType__NowPlayingFormat__.swift +65 -0
- package/nitrogen/generated/ios/swift/Func_void_std__shared_ptr_Promise_std__vector_BrowseItem___.swift +66 -0
- package/nitrogen/generated/ios/swift/Func_void_std__shared_ptr_Promise_std__vector_TrackItem___.swift +66 -0
- package/nitrogen/generated/ios/swift/Func_void_std__vector_BrowseItem_.swift +46 -0
- package/nitrogen/generated/ios/swift/Func_void_std__vector_CastReceiver_.swift +46 -0
- package/nitrogen/generated/ios/swift/Func_void_std__vector_EqualizerBand_.swift +46 -0
- package/nitrogen/generated/ios/swift/Func_void_std__vector_TrackItem_.swift +46 -0
- package/nitrogen/generated/ios/swift/HybridCastManagerSpec.swift +76 -0
- package/nitrogen/generated/ios/swift/HybridCastManagerSpec_cxx.swift +519 -0
- package/nitrogen/generated/ios/swift/HybridEqualizerSpec.swift +66 -0
- package/nitrogen/generated/ios/swift/HybridEqualizerSpec_cxx.swift +353 -0
- package/nitrogen/generated/ios/swift/HybridTrackPlayerSpec.swift +122 -0
- package/nitrogen/generated/ios/swift/HybridTrackPlayerSpec_cxx.swift +1430 -0
- package/nitrogen/generated/ios/swift/HybridVisualizerSpec.swift +56 -0
- package/nitrogen/generated/ios/swift/HybridVisualizerSpec_cxx.swift +163 -0
- package/nitrogen/generated/ios/swift/LookaheadCacheConfig.swift +34 -0
- package/nitrogen/generated/ios/swift/MediaSearchOrigin.swift +40 -0
- package/nitrogen/generated/ios/swift/MediaSearchQueueLocation.swift +44 -0
- package/nitrogen/generated/ios/swift/MediaSearchReference.swift +40 -0
- package/nitrogen/generated/ios/swift/MediaSearchReleaseDateRange.swift +60 -0
- package/nitrogen/generated/ios/swift/MediaSearchRepeatMode.swift +44 -0
- package/nitrogen/generated/ios/swift/MediaSearchRequest.swift +239 -0
- package/nitrogen/generated/ios/swift/MediaSearchType.swift +52 -0
- package/nitrogen/generated/ios/swift/NowPlayingFormat.swift +394 -0
- package/nitrogen/generated/ios/swift/NowPlayingFormatAndroidExtras.swift +135 -0
- package/nitrogen/generated/ios/swift/NowPlayingFormatIosExtras.swift +61 -0
- package/nitrogen/generated/ios/swift/PitchCorrectionMode.swift +44 -0
- package/nitrogen/generated/ios/swift/PlaybackError.swift +64 -0
- package/nitrogen/generated/ios/swift/PlaybackErrorCode.swift +80 -0
- package/nitrogen/generated/ios/swift/PlaybackMode.swift +47 -0
- package/nitrogen/generated/ios/swift/PlaybackModeKind.swift +40 -0
- package/nitrogen/generated/ios/swift/PlayerConfig.swift +251 -0
- package/nitrogen/generated/ios/swift/PlayerProgress.swift +39 -0
- package/nitrogen/generated/ios/swift/PlayerState.swift +60 -0
- package/nitrogen/generated/ios/swift/RemoteControlOptions.swift +39 -0
- package/nitrogen/generated/ios/swift/RemoteSkipMode.swift +40 -0
- package/nitrogen/generated/ios/swift/RepeatMode.swift +44 -0
- package/nitrogen/generated/ios/swift/ReplayGainMode.swift +44 -0
- package/nitrogen/generated/ios/swift/SectionIcon.swift +84 -0
- package/nitrogen/generated/ios/swift/ServiceReadyReason.swift +40 -0
- package/nitrogen/generated/ios/swift/ShuffleResult.swift +51 -0
- package/nitrogen/generated/ios/swift/SkipCapability.swift +34 -0
- package/nitrogen/generated/ios/swift/SleepTimerState.swift +70 -0
- package/nitrogen/generated/ios/swift/StateChangeReason.swift +60 -0
- package/nitrogen/generated/ios/swift/TrackChangeReason.swift +60 -0
- package/nitrogen/generated/ios/swift/TrackItem.swift +169 -0
- package/nitrogen/generated/ios/swift/TrackSource.swift +44 -0
- package/nitrogen/generated/ios/swift/Variant_NullType_Double.swift +30 -0
- package/nitrogen/generated/ios/swift/Variant_NullType_NowPlayingFormat.swift +30 -0
- package/nitrogen/generated/ios/swift/Variant_NullType_String.swift +30 -0
- package/nitrogen/generated/ios/swift/VisualizerConfig.swift +52 -0
- package/nitrogen/generated/ios/swift/VisualizerErrorReason.swift +48 -0
- package/nitrogen/generated/ios/swift/VisualizerFrame.swift +52 -0
- package/nitrogen/generated/ios/swift/VoiceVocabulary.swift +46 -0
- package/nitrogen/generated/shared/c++/AudioCategoryOptions.hpp +91 -0
- package/nitrogen/generated/shared/c++/AudioCodec.hpp +96 -0
- package/nitrogen/generated/shared/c++/AudioContainer.hpp +100 -0
- package/nitrogen/generated/shared/c++/AudioContentType.hpp +76 -0
- package/nitrogen/generated/shared/c++/AudioRoute.hpp +101 -0
- package/nitrogen/generated/shared/c++/AudioRouteKind.hpp +120 -0
- package/nitrogen/generated/shared/c++/BrowseItem.hpp +104 -0
- package/nitrogen/generated/shared/c++/BrowseSection.hpp +106 -0
- package/nitrogen/generated/shared/c++/BrowseSnapshot.hpp +90 -0
- package/nitrogen/generated/shared/c++/BufferState.hpp +84 -0
- package/nitrogen/generated/shared/c++/CacheStatus.hpp +100 -0
- package/nitrogen/generated/shared/c++/CastConfigureOptions.hpp +88 -0
- package/nitrogen/generated/shared/c++/CastConnectOptions.hpp +83 -0
- package/nitrogen/generated/shared/c++/CastDeviceKind.hpp +92 -0
- package/nitrogen/generated/shared/c++/CastDiscoveryState.hpp +83 -0
- package/nitrogen/generated/shared/c++/CastLocalNetworkPermission.hpp +80 -0
- package/nitrogen/generated/shared/c++/CastLocalNetworkPermissionEvent.hpp +84 -0
- package/nitrogen/generated/shared/c++/CastProtocol.hpp +88 -0
- package/nitrogen/generated/shared/c++/CastReceiver.hpp +115 -0
- package/nitrogen/generated/shared/c++/CastReceiverCapabilities.hpp +92 -0
- package/nitrogen/generated/shared/c++/CastRoute.hpp +111 -0
- package/nitrogen/generated/shared/c++/CastSessionDiedEvent.hpp +89 -0
- package/nitrogen/generated/shared/c++/CastSessionEndReason.hpp +100 -0
- package/nitrogen/generated/shared/c++/CastStreamingModel.hpp +76 -0
- package/nitrogen/generated/shared/c++/EqualizerBand.hpp +87 -0
- package/nitrogen/generated/shared/c++/EqualizerPreset.hpp +92 -0
- package/nitrogen/generated/shared/c++/EvictionPolicy.hpp +76 -0
- package/nitrogen/generated/shared/c++/HybridCastManagerSpec.cpp +42 -0
- package/nitrogen/generated/shared/c++/HybridCastManagerSpec.hpp +115 -0
- package/nitrogen/generated/shared/c++/HybridEqualizerSpec.cpp +32 -0
- package/nitrogen/generated/shared/c++/HybridEqualizerSpec.hpp +81 -0
- package/nitrogen/generated/shared/c++/HybridTrackPlayerSpec.cpp +88 -0
- package/nitrogen/generated/shared/c++/HybridTrackPlayerSpec.hpp +209 -0
- package/nitrogen/generated/shared/c++/HybridVisualizerSpec.cpp +22 -0
- package/nitrogen/generated/shared/c++/HybridVisualizerSpec.hpp +71 -0
- package/nitrogen/generated/shared/c++/LookaheadCacheConfig.hpp +87 -0
- package/nitrogen/generated/shared/c++/MediaSearchOrigin.hpp +76 -0
- package/nitrogen/generated/shared/c++/MediaSearchQueueLocation.hpp +80 -0
- package/nitrogen/generated/shared/c++/MediaSearchReference.hpp +76 -0
- package/nitrogen/generated/shared/c++/MediaSearchReleaseDateRange.hpp +87 -0
- package/nitrogen/generated/shared/c++/MediaSearchRepeatMode.hpp +80 -0
- package/nitrogen/generated/shared/c++/MediaSearchRequest.hpp +157 -0
- package/nitrogen/generated/shared/c++/MediaSearchType.hpp +88 -0
- package/nitrogen/generated/shared/c++/NowPlayingFormat.hpp +149 -0
- package/nitrogen/generated/shared/c++/NowPlayingFormatAndroidExtras.hpp +94 -0
- package/nitrogen/generated/shared/c++/NowPlayingFormatIosExtras.hpp +85 -0
- package/nitrogen/generated/shared/c++/PitchCorrectionMode.hpp +80 -0
- package/nitrogen/generated/shared/c++/PlaybackError.hpp +113 -0
- package/nitrogen/generated/shared/c++/PlaybackErrorCode.hpp +116 -0
- package/nitrogen/generated/shared/c++/PlaybackMode.hpp +89 -0
- package/nitrogen/generated/shared/c++/PlaybackModeKind.hpp +76 -0
- package/nitrogen/generated/shared/c++/PlayerConfig.hpp +141 -0
- package/nitrogen/generated/shared/c++/PlayerProgress.hpp +91 -0
- package/nitrogen/generated/shared/c++/PlayerState.hpp +96 -0
- package/nitrogen/generated/shared/c++/RemoteControlOptions.hpp +92 -0
- package/nitrogen/generated/shared/c++/RemoteSkipMode.hpp +76 -0
- package/nitrogen/generated/shared/c++/RepeatMode.hpp +80 -0
- package/nitrogen/generated/shared/c++/ReplayGainMode.hpp +80 -0
- package/nitrogen/generated/shared/c++/SectionIcon.hpp +120 -0
- package/nitrogen/generated/shared/c++/ServiceReadyReason.hpp +76 -0
- package/nitrogen/generated/shared/c++/ShuffleResult.hpp +94 -0
- package/nitrogen/generated/shared/c++/SkipCapability.hpp +87 -0
- package/nitrogen/generated/shared/c++/SleepTimerState.hpp +95 -0
- package/nitrogen/generated/shared/c++/StateChangeReason.hpp +96 -0
- package/nitrogen/generated/shared/c++/TrackChangeReason.hpp +96 -0
- package/nitrogen/generated/shared/c++/TrackItem.hpp +113 -0
- package/nitrogen/generated/shared/c++/TrackSource.hpp +80 -0
- package/nitrogen/generated/shared/c++/VisualizerConfig.hpp +91 -0
- package/nitrogen/generated/shared/c++/VisualizerErrorReason.hpp +84 -0
- package/nitrogen/generated/shared/c++/VisualizerFrame.hpp +92 -0
- package/nitrogen/generated/shared/c++/VoiceVocabulary.hpp +88 -0
- package/package.json +167 -0
- package/src/CastManager.nitro.ts +206 -0
- package/src/Equalizer.nitro.ts +37 -0
- package/src/TrackPlayer.nitro.ts +667 -0
- package/src/Visualizer.nitro.ts +48 -0
- package/src/cast/index.ts +224 -0
- package/src/clients.ts +50 -0
- package/src/equalizer.ts +86 -0
- package/src/hooks/index.ts +33 -0
- package/src/hooks/useActiveTrack.ts +55 -0
- package/src/hooks/useAudioRoute.ts +69 -0
- package/src/hooks/useBufferState.ts +35 -0
- package/src/hooks/useCanSkip.ts +92 -0
- package/src/hooks/useCast.ts +121 -0
- package/src/hooks/useEqualizer.ts +111 -0
- package/src/hooks/useFullyBuffered.ts +32 -0
- package/src/hooks/useLookaheadCache.ts +54 -0
- package/src/hooks/useNowPlayingFormat.ts +43 -0
- package/src/hooks/usePlaybackState.ts +34 -0
- package/src/hooks/useProgress.ts +36 -0
- package/src/hooks/useSleepTimer.ts +63 -0
- package/src/hooks/useVisualizerState.ts +121 -0
- package/src/index.ts +125 -0
- package/src/playbackService.ts +304 -0
- package/src/types.ts +1387 -0
|
@@ -0,0 +1,833 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import CryptoKit
|
|
3
|
+
|
|
4
|
+
/// On-disk lookahead cache for the iOS player. Mirrors the Android
|
|
5
|
+
/// `LookaheadCache.kt` shape: directory + per-track download +
|
|
6
|
+
/// lookup, paired with the `TrackPlayer` lifecycle.
|
|
7
|
+
///
|
|
8
|
+
/// iOS has no Media3-equivalent built-in cache, so we own the
|
|
9
|
+
/// download orchestration directly (`URLSessionDownloadTask` per
|
|
10
|
+
/// track, atomic move into `cacheDirectory`, plist metadata index
|
|
11
|
+
/// tracking `(trackId, fileName, sizeBytes, lastAccessTick)`).
|
|
12
|
+
/// The plist is persisted lazily — every successful download or
|
|
13
|
+
/// eviction rewrites it; concurrent reads use the in-memory
|
|
14
|
+
/// snapshot guarded by a serial dispatch queue.
|
|
15
|
+
///
|
|
16
|
+
/// `LookaheadCachePrefetcher` orchestrates downloads on every queue
|
|
17
|
+
/// + skip mutation. LRU eviction enforces the budget set via
|
|
18
|
+
/// `setMaxSizeBytes`. Mid-download tracks aren't in the index until
|
|
19
|
+
/// the move-into-destination block completes, so `cachedURL`
|
|
20
|
+
/// returns nil and the consumer reads remote.
|
|
21
|
+
///
|
|
22
|
+
/// Cross-platform parity with Android:
|
|
23
|
+
/// - cache directory name: `audio_lookahead`
|
|
24
|
+
/// - bootstrap budget: 100 MB (`DEFAULT_MAX_SIZE_BYTES`)
|
|
25
|
+
/// - file:// / asset:// URIs bypass the cache (only http/https go to disk)
|
|
26
|
+
/// - lifecycle paired with TrackPlayer.configure / .destroy
|
|
27
|
+
/// - per-track failures don't poison the rest of the prefetch window
|
|
28
|
+
public final class LookaheadCache: @unchecked Sendable {
|
|
29
|
+
|
|
30
|
+
/// On-disk root for cache files. Defaults to
|
|
31
|
+
/// `tmpDir/audio_lookahead/`. The plist index lives at
|
|
32
|
+
/// `cacheDirectory.appendingPathComponent("index.plist")`.
|
|
33
|
+
public let cacheDirectory: URL
|
|
34
|
+
|
|
35
|
+
/// Cache budget (bytes). Mutable — the runtime config
|
|
36
|
+
/// API can shrink/grow the budget. Internal because Swift's
|
|
37
|
+
/// `public private(set) var` auto-synthesizes a setter that
|
|
38
|
+
/// collides with the explicit [setMaxSizeBytes] method in the
|
|
39
|
+
/// generated Obj-C bridge header. Consumers read the value via
|
|
40
|
+
/// [getMaxSizeBytes]; the explicit method wraps the eviction pass.
|
|
41
|
+
internal var maxBytes: UInt64
|
|
42
|
+
|
|
43
|
+
/// Eviction policy, fixed at construction. `.lru` sorts victims by
|
|
44
|
+
/// `lastAccessTick` (playback-touched); `.fifo` by `insertionOrderTick`
|
|
45
|
+
/// (download order). See `LookaheadCacheEviction`.
|
|
46
|
+
internal let evictionPolicy: EvictionPolicy
|
|
47
|
+
|
|
48
|
+
/// Read the current cache budget. Public accessor so the field
|
|
49
|
+
/// itself can stay internal (avoids the bridge-header method
|
|
50
|
+
/// collision documented on `maxBytes`).
|
|
51
|
+
public func getMaxSizeBytes() -> UInt64 {
|
|
52
|
+
return queue.sync { self.maxBytes }
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/// URLSession used for foreground downloads. Constructor injects so
|
|
56
|
+
/// tests can pass a session backed by a `URLProtocol` stub.
|
|
57
|
+
internal let urlSession: URLSession
|
|
58
|
+
|
|
59
|
+
/// Serial queue protecting `index` + on-disk plist writes. Reads
|
|
60
|
+
/// from arbitrary threads (the prefetcher hops to its own task)
|
|
61
|
+
/// funnel through `queue.sync`; writes use `queue.async` after
|
|
62
|
+
/// the in-memory mutation so the plist write doesn't block the
|
|
63
|
+
/// download-completion callback.
|
|
64
|
+
private let queue = DispatchQueue(label: "queueplayer.lookahead-cache.index")
|
|
65
|
+
|
|
66
|
+
/// In-memory plist index, mirrored to disk after every mutation.
|
|
67
|
+
private var index: Index
|
|
68
|
+
|
|
69
|
+
/// Per-trackId dedup of in-flight downloads. The prefetcher
|
|
70
|
+
/// serializes per-chain so concurrent same-trackId
|
|
71
|
+
/// paths are rare in practice, but `tearDown → reschedule`
|
|
72
|
+
/// during a hot KVO window can produce the race + waste
|
|
73
|
+
/// bandwidth on duplicate downloads. With the dedup, the second
|
|
74
|
+
/// caller observes the trackId in the set + returns
|
|
75
|
+
/// immediately; the first caller's eventual cache write makes
|
|
76
|
+
/// the file available for the next `cachedURL` lookup. Guarded
|
|
77
|
+
/// by `queue` like `index`.
|
|
78
|
+
private var pendingDownloads: Set<String> = []
|
|
79
|
+
|
|
80
|
+
/// Quiescence flag. When false, `download` no-ops before touching
|
|
81
|
+
/// the URLSession so a `setLookaheadCache(enabled:false)` toggle
|
|
82
|
+
/// can stop new schedule without invalidating the session. Live
|
|
83
|
+
/// downloads are cancelled in `disable()` via
|
|
84
|
+
/// `getAllTasks { $0.cancel() }` — the session itself stays valid
|
|
85
|
+
/// for the cache's lifetime, so an `enable()` flip back can resume
|
|
86
|
+
/// scheduling immediately. Guarded by `queue`. The URLSession is
|
|
87
|
+
/// only invalidated by `tearDown()` at full destroy.
|
|
88
|
+
private var isEnabled: Bool = true
|
|
89
|
+
|
|
90
|
+
// MARK: - Init / lifecycle
|
|
91
|
+
|
|
92
|
+
/// - Parameters:
|
|
93
|
+
/// - directory: root directory for cache files. Defaults to
|
|
94
|
+
/// `defaultDirectory()` (`tmpDir/audio_lookahead/`).
|
|
95
|
+
/// - maxSizeBytes: cache budget; eviction reads this value to enforce LRU bounds.
|
|
96
|
+
///
|
|
97
|
+
/// Production callers use this init; the `URLSession` is built
|
|
98
|
+
/// internally with `URLSessionConfiguration.default`. Tests that
|
|
99
|
+
/// need to inject a `URLProtocol`-stubbed session use the SPI init
|
|
100
|
+
/// below.
|
|
101
|
+
///
|
|
102
|
+
/// `URLSession` is deliberately NOT exposed on the public init
|
|
103
|
+
/// signature — Swift's C++ interop generator (enabled via
|
|
104
|
+
/// `cxx-interoperability-mode=default` per the podspec build flags)
|
|
105
|
+
/// chokes on `URLSession` references in public Swift API on some
|
|
106
|
+
/// toolchains, surfacing as `use of undeclared identifier
|
|
107
|
+
/// 'NSURLSession'` in the auto-generated `QueuePlayer-Swift.h`.
|
|
108
|
+
/// Keeping the URLSession parameter on a separate SPI init dodges
|
|
109
|
+
/// the bridge-generator pathology.
|
|
110
|
+
// `internal` (not `public`): the `evictionPolicy` parameter is a generated
|
|
111
|
+
// enum, and cxx-interop drops public API referencing it from the emitted
|
|
112
|
+
// module interface (same pathology as `computeEvictions`). Nothing external
|
|
113
|
+
// constructs `LookaheadCache` — production builds it in-module and tests reach
|
|
114
|
+
// it via `@testable import`.
|
|
115
|
+
internal convenience init(
|
|
116
|
+
directory: URL = LookaheadCache.defaultDirectory(),
|
|
117
|
+
maxSizeBytes: UInt64 = LookaheadCache.DEFAULT_MAX_SIZE_BYTES,
|
|
118
|
+
evictionPolicy: EvictionPolicy = .lru
|
|
119
|
+
) {
|
|
120
|
+
// `.ephemeral` rather than `.default` so the OS shared URL
|
|
121
|
+
// response cache doesn't double-cache our prefetch bytes (we
|
|
122
|
+
// already store the downloaded body in the lookahead cache
|
|
123
|
+
// directory ourselves; the OS-level URLCache would just shadow
|
|
124
|
+
// those bytes in `~/Library/Caches/...` for no benefit). Saves
|
|
125
|
+
// a modest amount of disk + memory and avoids surprising the
|
|
126
|
+
// consumer with two on-disk copies of the same audio.
|
|
127
|
+
let cfg = URLSessionConfiguration.ephemeral
|
|
128
|
+
// `timeoutIntervalForRequest` is an inactivity timer (reset on each byte).
|
|
129
|
+
// A long-track prefetch from a slow or throttling server can idle past the
|
|
130
|
+
// 60s default and get killed mid-download; raise it well past a normal
|
|
131
|
+
// stall. `timeoutIntervalForResource` keeps its 7-day default as the
|
|
132
|
+
// overall backstop, and the cache's own retry/eviction handles a genuinely
|
|
133
|
+
// dead download.
|
|
134
|
+
cfg.timeoutIntervalForRequest = 300
|
|
135
|
+
self.init(
|
|
136
|
+
directory: directory,
|
|
137
|
+
maxSizeBytes: maxSizeBytes,
|
|
138
|
+
evictionPolicy: evictionPolicy,
|
|
139
|
+
urlSession: URLSession(configuration: cfg)
|
|
140
|
+
)
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/// Test-only init — tests inject a `URLSession` wired to a
|
|
144
|
+
/// `URLProtocol` stub here. `internal` (not `@_spi public`)
|
|
145
|
+
/// because `public` symbols still emit C++ interop bindings even
|
|
146
|
+
/// behind SPI, and `URLSession` in any public signature trips
|
|
147
|
+
/// the bridge generator (`use of undeclared identifier 'NSURLSession'`).
|
|
148
|
+
/// Tests reach this via `@testable import QueuePlayer`.
|
|
149
|
+
internal init(
|
|
150
|
+
directory: URL,
|
|
151
|
+
maxSizeBytes: UInt64,
|
|
152
|
+
evictionPolicy: EvictionPolicy = .lru,
|
|
153
|
+
urlSession: URLSession
|
|
154
|
+
) {
|
|
155
|
+
self.cacheDirectory = directory
|
|
156
|
+
self.maxBytes = maxSizeBytes
|
|
157
|
+
self.evictionPolicy = evictionPolicy
|
|
158
|
+
self.urlSession = urlSession
|
|
159
|
+
Self.ensureDirectoryExists(at: directory)
|
|
160
|
+
self.index = Self.loadOrCreateIndex(at: directory)
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/// Cancel every in-flight download + invalidate the URLSession.
|
|
164
|
+
/// Idempotent — calling twice on the same instance is safe.
|
|
165
|
+
/// Must be called from `TrackPlayer.destroy` BEFORE any consumer
|
|
166
|
+
/// drops their reference to the cache instance.
|
|
167
|
+
///
|
|
168
|
+
/// Named `tearDown` (not `release`) to avoid the Obj-C
|
|
169
|
+
/// `NSObject.release` selector collision; pure Swift class so
|
|
170
|
+
/// there is no actual NSObject to inherit, but staying clear
|
|
171
|
+
/// of the name keeps things friendly if a future @objc bridge
|
|
172
|
+
/// gets added.
|
|
173
|
+
public func tearDown() {
|
|
174
|
+
urlSession.invalidateAndCancel()
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/// Quiesce the cache without invalidating its URLSession.
|
|
178
|
+
/// `setLookaheadCache(enabled:false)` calls this rather than
|
|
179
|
+
/// `tearDown` so a subsequent `enable()` can reuse the session
|
|
180
|
+
/// without the bridge between disable + the next download
|
|
181
|
+
/// scheduling against an invalidated session (Obj-C exception
|
|
182
|
+
/// `Task created in a session that has been invalidated`,
|
|
183
|
+
/// uncatchable in Swift's `do-catch`).
|
|
184
|
+
///
|
|
185
|
+
/// Effects: clears the `isEnabled` flag so `download` no-ops + the
|
|
186
|
+
/// in-flight dedup set so a re-enable starts clean, and cancels
|
|
187
|
+
/// any URLSession tasks already mid-flight via `getAllTasks`. The
|
|
188
|
+
/// session itself stays alive — a later `enable()` reuses it.
|
|
189
|
+
public func disable() {
|
|
190
|
+
queue.sync {
|
|
191
|
+
self.isEnabled = false
|
|
192
|
+
self.pendingDownloads.removeAll()
|
|
193
|
+
}
|
|
194
|
+
urlSession.getAllTasks { tasks in
|
|
195
|
+
tasks.forEach { $0.cancel() }
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/// Re-arm the cache after a `disable()`. Just flips the flag —
|
|
200
|
+
/// `download()` will start scheduling against the existing
|
|
201
|
+
/// URLSession again. Idempotent on already-enabled caches.
|
|
202
|
+
public func enable() {
|
|
203
|
+
queue.sync {
|
|
204
|
+
self.isEnabled = true
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/// Update the cache budget at runtime. On shrink, runs
|
|
209
|
+
/// `evictUnderBudgetLocked` immediately so the new ceiling is
|
|
210
|
+
/// enforced before the call returns. On grow, the new budget
|
|
211
|
+
/// takes effect on the next download — no immediate eviction.
|
|
212
|
+
///
|
|
213
|
+
/// `protectedUrls`: caller passes the source URLs whose
|
|
214
|
+
/// `AVPlayerItem`s are currently held by AVQueuePlayer. Without
|
|
215
|
+
/// this, a shrink could evict the file backing a live
|
|
216
|
+
/// AVPlayerItem + manifest as `AVPlayerItemFailedToPlayToEndTime`
|
|
217
|
+
/// mid-playback. TrackPlayer passes
|
|
218
|
+
/// `tracks[currentTrackIndex...].map { $0.url }` so the entire
|
|
219
|
+
/// active tail (current + buffered-ahead) is safe. Always keyed
|
|
220
|
+
/// on URL — `track.id` is consumer-supplied + unreliable.
|
|
221
|
+
public func setMaxSizeBytes(_ newSize: UInt64, protectedUrls: Set<String> = []) {
|
|
222
|
+
let urlsToDeleteAfterUnlock: [URL] = queue.sync {
|
|
223
|
+
let shrinking = newSize < self.maxBytes
|
|
224
|
+
self.maxBytes = newSize
|
|
225
|
+
guard shrinking else { return [] }
|
|
226
|
+
let urls = self.evictUnderBudgetLocked(protectedUrls: protectedUrls)
|
|
227
|
+
self.persistIndexLocked()
|
|
228
|
+
return urls
|
|
229
|
+
}
|
|
230
|
+
for url in urlsToDeleteAfterUnlock {
|
|
231
|
+
try? FileManager.default.removeItem(at: url)
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/// Sum of cached bytes across every entry in the index. Reads
|
|
236
|
+
/// `index.entries.sizeBytes` — does NOT stat the on-disk files
|
|
237
|
+
/// (the recorded size is the source of truth).
|
|
238
|
+
public func currentSizeBytes() -> UInt64 {
|
|
239
|
+
return queue.sync {
|
|
240
|
+
self.index.entries.reduce(UInt64(0)) { $0 + $1.sizeBytes }
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/// Whether the cache holds the entire content for the given source URL.
|
|
245
|
+
/// True iff an index entry exists AND the on-disk file is still
|
|
246
|
+
/// present.
|
|
247
|
+
public func isFullyCached(url: String) -> Bool {
|
|
248
|
+
return queue.sync {
|
|
249
|
+
guard let entry = self.index.entries.first(where: { $0.trackId == url }) else {
|
|
250
|
+
return false
|
|
251
|
+
}
|
|
252
|
+
let fileURL = cacheDirectory.appendingPathComponent(entry.fileName)
|
|
253
|
+
return FileManager.default.fileExists(atPath: fileURL.path)
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/// Number of cache index entries whose file is still on disk
|
|
258
|
+
/// (queue-agnostic). Mirrors the semantics of `currentSizeBytes()`
|
|
259
|
+
/// (cache state, independent of any current queue). Used by
|
|
260
|
+
/// `TrackPlayer.buildCacheStatusSnapshot` for the
|
|
261
|
+
/// `tracksFullyCached` field — the count reflects the cache itself,
|
|
262
|
+
/// not the intersection with `self.tracks`.
|
|
263
|
+
public func fullyCachedCount() -> Int {
|
|
264
|
+
return queue.sync {
|
|
265
|
+
self.index.entries.reduce(into: 0) { acc, entry in
|
|
266
|
+
let fileURL = cacheDirectory.appendingPathComponent(entry.fileName)
|
|
267
|
+
if FileManager.default.fileExists(atPath: fileURL.path) {
|
|
268
|
+
acc += 1
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/// Wipe every cached file + reset the index.
|
|
275
|
+
///
|
|
276
|
+
/// **Mid-playback caveat:** if a currently-playing `AVPlayerItem`
|
|
277
|
+
/// was constructed from a cached file URL, deleting that file
|
|
278
|
+
/// mid-playback surfaces as an `AVPlayerItemFailedToPlayToEndTime`
|
|
279
|
+
/// error. Contract is "do not call during active playback";
|
|
280
|
+
/// consumers should `pause()` first or accept the mid-track error.
|
|
281
|
+
public func clear() {
|
|
282
|
+
let urlsToDelete: [URL] = queue.sync {
|
|
283
|
+
let urls = self.index.entries.map {
|
|
284
|
+
cacheDirectory.appendingPathComponent($0.fileName)
|
|
285
|
+
}
|
|
286
|
+
self.index = Index(version: 2, entries: [], nextAccessTick: 1, nextInsertionTick: 1)
|
|
287
|
+
self.persistIndexLocked()
|
|
288
|
+
return urls
|
|
289
|
+
}
|
|
290
|
+
// Defer the FS deletes outside `queue.sync` for consistency
|
|
291
|
+
// with `download` + `setMaxSizeBytes`. The deletes can't
|
|
292
|
+
// collide with concurrent reads (the entries are gone from the
|
|
293
|
+
// in-memory index) and slow FS removals shouldn't block
|
|
294
|
+
// concurrent `cachedURL` lookups.
|
|
295
|
+
for url in urlsToDelete {
|
|
296
|
+
try? FileManager.default.removeItem(at: url)
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
// MARK: - Lookup
|
|
301
|
+
|
|
302
|
+
/// Return the local file URL for `url` (the source URL — see
|
|
303
|
+
/// "Key shape" on `isFullyCached(url:)`) if a fully-downloaded
|
|
304
|
+
/// cache entry exists, otherwise nil. Pure read — does NOT touch
|
|
305
|
+
/// the LRU access tick. Callers that want LRU bookkeeping (the
|
|
306
|
+
/// `AVQueueBuilder.makeItem` cache-hit branch is the production
|
|
307
|
+
/// caller) call `touch(url:)` separately. Splitting these
|
|
308
|
+
/// out avoids the prior pattern's two-FS-writes-per-read penalty
|
|
309
|
+
/// on the playback hot path.
|
|
310
|
+
///
|
|
311
|
+
/// Defensive: if the file got pruned out from under us (consumer
|
|
312
|
+
/// ran `rm -rf tmp`, or eviction then crashed before
|
|
313
|
+
/// updating the plist), drop the stale entry + return nil. The
|
|
314
|
+
/// in-memory removal is deliberate; we deliberately do NOT
|
|
315
|
+
/// persist the plist on the defensive removal because doing so
|
|
316
|
+
/// would re-introduce a write on every read of an evicted entry.
|
|
317
|
+
/// The next mutation (`download` / `setMaxSizeBytes` / `clear`)
|
|
318
|
+
/// will persist anyway, and the in-memory state is consistent
|
|
319
|
+
/// for the lifetime of this process.
|
|
320
|
+
public func cachedURL(forUrl url: String) -> URL? {
|
|
321
|
+
return queue.sync {
|
|
322
|
+
guard let entryIdx = self.index.entries.firstIndex(where: { $0.trackId == url }) else {
|
|
323
|
+
return nil
|
|
324
|
+
}
|
|
325
|
+
let entry = self.index.entries[entryIdx]
|
|
326
|
+
let fileURL = cacheDirectory.appendingPathComponent(entry.fileName)
|
|
327
|
+
guard FileManager.default.fileExists(atPath: fileURL.path) else {
|
|
328
|
+
self.index.entries.remove(at: entryIdx)
|
|
329
|
+
return nil
|
|
330
|
+
}
|
|
331
|
+
return fileURL
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
/// Bump the LRU access tick for the cache entry keyed on `url`.
|
|
336
|
+
/// Callers invoke this separately from `cachedURL(forUrl:)` so a
|
|
337
|
+
/// read-heavy playback path doesn't trigger a plist write per
|
|
338
|
+
/// resolution. No-op for unknown URLs.
|
|
339
|
+
public func touch(url: String) {
|
|
340
|
+
queue.async {
|
|
341
|
+
guard let entryIdx = self.index.entries.firstIndex(where: { $0.trackId == url }) else {
|
|
342
|
+
return
|
|
343
|
+
}
|
|
344
|
+
var bumped = self.index.entries[entryIdx]
|
|
345
|
+
bumped.lastAccessTick = self.index.nextAccessTick
|
|
346
|
+
self.index.nextAccessTick &+= 1
|
|
347
|
+
self.index.entries[entryIdx] = bumped
|
|
348
|
+
self.persistIndexLocked()
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
// MARK: - Download
|
|
353
|
+
|
|
354
|
+
/// Download `track.url` to the cache directory with the supplied
|
|
355
|
+
/// HTTP headers. Atomic: a partial download (interrupted by cancel
|
|
356
|
+
/// or network failure) is removed before the function returns —
|
|
357
|
+
/// `cachedURL(forUrl:)` only resolves to a complete file.
|
|
358
|
+
///
|
|
359
|
+
/// Idempotent on already-cached tracks: returns immediately if the
|
|
360
|
+
/// trackId is already in the index + the file exists. Skips any
|
|
361
|
+
/// non-http(s) URL (file:// / asset:// don't need caching; iOS
|
|
362
|
+
/// reads them off the local filesystem directly).
|
|
363
|
+
///
|
|
364
|
+
/// Throws `CancellationError` on cooperative cancellation,
|
|
365
|
+
/// `LookaheadCacheError.invalidUrl` for malformed URLs, or any
|
|
366
|
+
/// `URLSession` error from the download itself.
|
|
367
|
+
public func download(
|
|
368
|
+
track: TrackItem,
|
|
369
|
+
headers: [String: String]?
|
|
370
|
+
) async throws {
|
|
371
|
+
guard let url = URL(string: track.url) else {
|
|
372
|
+
throw LookaheadCacheError.invalidUrl
|
|
373
|
+
}
|
|
374
|
+
let scheme = url.scheme?.lowercased()
|
|
375
|
+
guard scheme == "http" || scheme == "https" else { return }
|
|
376
|
+
|
|
377
|
+
// Quiescence gate: a `disable()` toggle no-ops new schedule
|
|
378
|
+
// before touching the URLSession, so a stale prefetcher Task
|
|
379
|
+
// that survived `disable()` + tried to download against the
|
|
380
|
+
// (intentionally NOT invalidated) session still skips the
|
|
381
|
+
// request rather than competing with a re-enable cycle.
|
|
382
|
+
let enabled = queue.sync { self.isEnabled }
|
|
383
|
+
guard enabled else { return }
|
|
384
|
+
|
|
385
|
+
// Cache key = source URL. The `Entry` struct's `trackId` field
|
|
386
|
+
// holds the URL (kept for on-disk plist back-compat); the
|
|
387
|
+
// public APIs all use `url:` parameter labels.
|
|
388
|
+
if let _ = self.cachedURL(forUrl: track.url) {
|
|
389
|
+
return
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
// Per-URL dedup. Atomically check + insert: if
|
|
393
|
+
// another caller is already downloading this URL, return
|
|
394
|
+
// immediately without spawning a duplicate URLSession task.
|
|
395
|
+
// The first caller's eventual cache write makes the file
|
|
396
|
+
// available on the next `cachedURL` lookup. Cleanup happens
|
|
397
|
+
// via `defer` below so a thrown error / cancellation also
|
|
398
|
+
// releases the dedup slot.
|
|
399
|
+
//
|
|
400
|
+
// Throw-path semantics: if the first caller throws before the
|
|
401
|
+
// cache write block (e.g. HTTP error or task cancellation),
|
|
402
|
+
// a concurrent second caller's `cachedURL` check would already
|
|
403
|
+
// have returned nil + then observed the dedup slot still
|
|
404
|
+
// occupied → second caller no-ops and skips this iteration.
|
|
405
|
+
// The next prefetch reschedule re-queues the download.
|
|
406
|
+
// Aligns with the existing per-track-failure-swallowed
|
|
407
|
+
// contract in `LookaheadCachePrefetcher` (failed tracks retry
|
|
408
|
+
// on the next reschedule).
|
|
409
|
+
let dedupeKey = track.url
|
|
410
|
+
let alreadyPending: Bool = queue.sync {
|
|
411
|
+
if self.pendingDownloads.contains(dedupeKey) { return true }
|
|
412
|
+
self.pendingDownloads.insert(dedupeKey)
|
|
413
|
+
return false
|
|
414
|
+
}
|
|
415
|
+
if alreadyPending { return }
|
|
416
|
+
defer {
|
|
417
|
+
queue.async { _ = self.pendingDownloads.remove(dedupeKey) }
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
let (tempLocation, sizeBytes, contentType) = try await performDownload(
|
|
421
|
+
url: url, headers: headers
|
|
422
|
+
)
|
|
423
|
+
try Task.checkCancellation()
|
|
424
|
+
|
|
425
|
+
let fileName = Self.fileName(forUrl: track.url, contentType: contentType)
|
|
426
|
+
try commitDownloadedFile(
|
|
427
|
+
tempLocation: tempLocation,
|
|
428
|
+
urlKey: track.url,
|
|
429
|
+
fileName: fileName,
|
|
430
|
+
sizeBytes: sizeBytes
|
|
431
|
+
)
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
/// Run the URLSession download + HTTP-status validation. Returns
|
|
435
|
+
/// the temp location URLSession wrote to + the measured size in
|
|
436
|
+
/// bytes (so the commit step doesn't re-stat the file). Throws
|
|
437
|
+
/// `LookaheadCacheError.httpError` for non-2xx responses (and
|
|
438
|
+
/// cleans up the temp file before throwing).
|
|
439
|
+
private func performDownload(
|
|
440
|
+
url: URL, headers: [String: String]?
|
|
441
|
+
) async throws -> (tempLocation: URL, sizeBytes: UInt64, contentType: String?) {
|
|
442
|
+
var request = URLRequest(url: url)
|
|
443
|
+
headers?.forEach { request.addValue($1, forHTTPHeaderField: $0) }
|
|
444
|
+
|
|
445
|
+
let (tempLocation, response) = try await urlSession.download(for: request)
|
|
446
|
+
|
|
447
|
+
guard let httpResponse = response as? HTTPURLResponse,
|
|
448
|
+
(200..<300).contains(httpResponse.statusCode) else {
|
|
449
|
+
// Log temp-file cleanup failures (rare on iOS but possible on
|
|
450
|
+
// shared containers across volumes or sandboxed scenarios) so
|
|
451
|
+
// a leaked temp file is diagnosable in production logs.
|
|
452
|
+
do {
|
|
453
|
+
try FileManager.default.removeItem(at: tempLocation)
|
|
454
|
+
} catch {
|
|
455
|
+
NSLog(
|
|
456
|
+
"[LookaheadCache] HTTP-error temp-file cleanup failed at %@: %@",
|
|
457
|
+
tempLocation.path, String(describing: error)
|
|
458
|
+
)
|
|
459
|
+
}
|
|
460
|
+
throw LookaheadCacheError.httpError(
|
|
461
|
+
statusCode: (response as? HTTPURLResponse)?.statusCode ?? -1
|
|
462
|
+
)
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
let attrs = try? FileManager.default.attributesOfItem(atPath: tempLocation.path)
|
|
466
|
+
let sizeBytes: UInt64 = (attrs?[.size] as? NSNumber)?.uint64Value ?? 0
|
|
467
|
+
let contentType = httpResponse.value(forHTTPHeaderField: "Content-Type")
|
|
468
|
+
return (tempLocation, sizeBytes, contentType)
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
/// Move the downloaded temp file into the cache directory and
|
|
472
|
+
/// update the index under `queue.sync`: drop any stale entry for
|
|
473
|
+
/// `urlKey`, append the new Entry, bump `nextAccessTick`, run
|
|
474
|
+
/// `evictUnderBudgetLocked` (with `urlKey` protected), persist
|
|
475
|
+
/// the plist. After the lock releases, delete any evicted files.
|
|
476
|
+
///
|
|
477
|
+
/// `moveItem` failures are lifted out of `queue.sync` and rethrown
|
|
478
|
+
/// as `LookaheadCacheError.moveFailed` so a sandbox / cross-volume
|
|
479
|
+
/// failure surfaces to the prefetcher cleanly.
|
|
480
|
+
private func commitDownloadedFile(
|
|
481
|
+
tempLocation: URL, urlKey: String, fileName: String, sizeBytes: UInt64
|
|
482
|
+
) throws {
|
|
483
|
+
let destination = cacheDirectory.appendingPathComponent(fileName)
|
|
484
|
+
var moveError: Error?
|
|
485
|
+
let urlsToDeleteAfterUnlock: [URL]? = queue.sync {
|
|
486
|
+
// Remove any prior file at this destination (re-download path).
|
|
487
|
+
try? FileManager.default.removeItem(at: destination)
|
|
488
|
+
do {
|
|
489
|
+
try FileManager.default.moveItem(at: tempLocation, to: destination)
|
|
490
|
+
} catch {
|
|
491
|
+
moveError = error
|
|
492
|
+
try? FileManager.default.removeItem(at: tempLocation)
|
|
493
|
+
return nil
|
|
494
|
+
}
|
|
495
|
+
// Drop any stale entry for the same key (re-download).
|
|
496
|
+
self.index.entries.removeAll { $0.trackId == urlKey }
|
|
497
|
+
self.index.entries.append(Entry(
|
|
498
|
+
trackId: urlKey,
|
|
499
|
+
fileName: fileName,
|
|
500
|
+
sizeBytes: sizeBytes,
|
|
501
|
+
lastAccessTick: self.index.nextAccessTick,
|
|
502
|
+
insertionOrderTick: self.index.nextInsertionTick
|
|
503
|
+
))
|
|
504
|
+
self.index.nextAccessTick &+= 1
|
|
505
|
+
self.index.nextInsertionTick &+= 1
|
|
506
|
+
// Protect the just-appended URL from eviction so an oversized
|
|
507
|
+
// download (single track > maxBytes) doesn't silently
|
|
508
|
+
// evict itself and leave the consumer with a successful-but-
|
|
509
|
+
// immediately-discarded prefetch.
|
|
510
|
+
let urlsToDelete = self.evictUnderBudgetLocked(protectedUrls: [urlKey])
|
|
511
|
+
self.persistIndexLocked()
|
|
512
|
+
return urlsToDelete
|
|
513
|
+
}
|
|
514
|
+
if let error = moveError {
|
|
515
|
+
throw LookaheadCacheError.moveFailed(underlying: error)
|
|
516
|
+
}
|
|
517
|
+
for url in urlsToDeleteAfterUnlock ?? [] {
|
|
518
|
+
try? FileManager.default.removeItem(at: url)
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
/// Apply LRU eviction so cumulative cached bytes drop to
|
|
523
|
+
/// [maxBytes] or below. Mutates the in-memory index but
|
|
524
|
+
/// returns the file URLs the caller must delete from disk
|
|
525
|
+
/// AFTER releasing `queue.sync` — slow FS removals shouldn't
|
|
526
|
+
/// block concurrent `cachedURL` lookups. The defensive
|
|
527
|
+
/// "stale entry on cachedURL" branch handles the brief window
|
|
528
|
+
/// where the index says "evicted" but the file still exists on
|
|
529
|
+
/// disk.
|
|
530
|
+
///
|
|
531
|
+
/// `protectedUrls` skips matching entries from the eviction
|
|
532
|
+
/// candidate set entirely — the download body uses this to
|
|
533
|
+
/// protect the just-appended entry (see [download]).
|
|
534
|
+
///
|
|
535
|
+
/// MUST be called inside `queue.sync`. Caller is responsible for
|
|
536
|
+
/// the subsequent `persistIndexLocked()` — coalescing the persist
|
|
537
|
+
/// with an appending caller avoids double-writing the plist.
|
|
538
|
+
///
|
|
539
|
+
/// `internal` (not `private`) so `setLookaheadCache(maxBytes:)`
|
|
540
|
+
/// shrink path can call it directly without duplicating the
|
|
541
|
+
/// orchestration. Tests reach via `@testable import`.
|
|
542
|
+
internal func evictUnderBudgetLocked(
|
|
543
|
+
protectedUrls: Set<String> = []
|
|
544
|
+
) -> [URL] {
|
|
545
|
+
let evicted = LookaheadCacheEviction.computeEvictions(
|
|
546
|
+
entries: self.index.entries,
|
|
547
|
+
maxBytes: self.maxBytes,
|
|
548
|
+
useFifoOrder: self.evictionPolicy == .fifo,
|
|
549
|
+
protectedUrls: protectedUrls
|
|
550
|
+
)
|
|
551
|
+
if evicted.isEmpty { return [] }
|
|
552
|
+
let evictedIds = Set(evicted.map { $0.trackId })
|
|
553
|
+
let urls = evicted.map { cacheDirectory.appendingPathComponent($0.fileName) }
|
|
554
|
+
self.index.entries.removeAll { evictedIds.contains($0.trackId) }
|
|
555
|
+
return urls
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
// MARK: - Test introspection
|
|
559
|
+
|
|
560
|
+
/// Snapshot of the current index. Test-only — production code
|
|
561
|
+
/// reaches into the cache via `cachedURL` / `download`.
|
|
562
|
+
@_spi(QueuePlayerTests)
|
|
563
|
+
public var indexSnapshot: [Entry] {
|
|
564
|
+
return queue.sync { self.index.entries }
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
/// Whether `index.plist` exists on disk. Test-only.
|
|
568
|
+
@_spi(QueuePlayerTests)
|
|
569
|
+
public var indexFileExists: Bool {
|
|
570
|
+
return FileManager.default.fileExists(atPath: indexFileURL.path)
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
// MARK: - Internals
|
|
574
|
+
|
|
575
|
+
private var indexFileURL: URL {
|
|
576
|
+
return cacheDirectory.appendingPathComponent("index.plist")
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
/// MUST be called inside `queue.sync` — the in-memory `self.index`
|
|
580
|
+
/// is the authoritative source and the plist is its mirror.
|
|
581
|
+
private func persistIndexLocked() {
|
|
582
|
+
let encoder = PropertyListEncoder()
|
|
583
|
+
encoder.outputFormat = .binary
|
|
584
|
+
do {
|
|
585
|
+
let data = try encoder.encode(self.index)
|
|
586
|
+
try data.write(to: indexFileURL, options: .atomic)
|
|
587
|
+
} catch {
|
|
588
|
+
// Persistence failure is non-fatal — the in-memory index is
|
|
589
|
+
// authoritative for the lifetime of this process. Next launch
|
|
590
|
+
// will fall back to whatever last persisted successfully.
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
private static func loadOrCreateIndex(at directory: URL) -> Index {
|
|
595
|
+
let url = directory.appendingPathComponent("index.plist")
|
|
596
|
+
guard let data = try? Data(contentsOf: url) else {
|
|
597
|
+
return Index(version: 2, entries: [], nextAccessTick: 1, nextInsertionTick: 1)
|
|
598
|
+
}
|
|
599
|
+
do {
|
|
600
|
+
return try PropertyListDecoder().decode(Index.self, from: data)
|
|
601
|
+
} catch {
|
|
602
|
+
// Unreadable index (an older on-disk schema or genuine corruption).
|
|
603
|
+
// Without a valid index the on-disk files are unreferenced, so purge
|
|
604
|
+
// the directory to avoid orphans, then start fresh.
|
|
605
|
+
Self.purgeCachedFiles(at: directory)
|
|
606
|
+
return Index(version: 2, entries: [], nextAccessTick: 1, nextInsertionTick: 1)
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
/// Delete every file in the cache directory. Used when the index is
|
|
611
|
+
/// reset (unreadable/older schema) so orphaned audio files don't linger.
|
|
612
|
+
private static func purgeCachedFiles(at directory: URL) {
|
|
613
|
+
let fm = FileManager.default
|
|
614
|
+
guard let contents = try? fm.contentsOfDirectory(
|
|
615
|
+
at: directory, includingPropertiesForKeys: nil
|
|
616
|
+
) else { return }
|
|
617
|
+
for file in contents {
|
|
618
|
+
try? fm.removeItem(at: file)
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
/// Delete every file in the default cache directory without a live instance.
|
|
623
|
+
/// Used at configure time when the eviction policy changes while the cache is
|
|
624
|
+
/// disabled (no instance to `clear()`), so the change still starts empty —
|
|
625
|
+
/// parity with Android's unconditional clear.
|
|
626
|
+
internal static func purgeDefaultDirectory() {
|
|
627
|
+
purgeCachedFiles(at: defaultDirectory())
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
private static func ensureDirectoryExists(at directory: URL) {
|
|
631
|
+
try? FileManager.default.createDirectory(
|
|
632
|
+
at: directory, withIntermediateDirectories: true
|
|
633
|
+
)
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
/// Default cache root: `tmpDir/audio_lookahead/`. Matches the
|
|
637
|
+
/// Android sibling's `context.cacheDir/audio_lookahead/`.
|
|
638
|
+
public static func defaultDirectory() -> URL {
|
|
639
|
+
return FileManager.default.temporaryDirectory
|
|
640
|
+
.appendingPathComponent("audio_lookahead", isDirectory: true)
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
/// Filesystem-safe filename derived from a source URL. Uses a SHA256
|
|
644
|
+
/// hex digest of the UTF-8 bytes so collision risk is cryptographic
|
|
645
|
+
/// (two URLs colliding → SHA256 collision found) rather than
|
|
646
|
+
/// dependent on the URL's character set. Earlier versions did
|
|
647
|
+
/// alphanumeric collapse, which collided non-trivially: `"a/b"`
|
|
648
|
+
/// and `"a_b"` mapped to the same filename + clobbered each other.
|
|
649
|
+
///
|
|
650
|
+
/// A short readable prefix is prepended for human debuggability when
|
|
651
|
+
/// inspecting the cache directory — derived from the same alphanumeric
|
|
652
|
+
/// collapse but for display only, not used for collision checks.
|
|
653
|
+
///
|
|
654
|
+
/// `contentType` (HTTP `Content-Type` header from the download
|
|
655
|
+
/// response, when known) drives the file extension. AVFoundation
|
|
656
|
+
/// uses the extension as one signal when picking a demuxer for a
|
|
657
|
+
/// local-file AVURLAsset; a `.bin` extension breaks decoding for
|
|
658
|
+
/// some assets, so the cached file MUST end in the right format
|
|
659
|
+
/// suffix for AVPlayer to play it back correctly. Falls back to
|
|
660
|
+
/// the URL's path extension, then `.bin` as a last resort.
|
|
661
|
+
///
|
|
662
|
+
/// Exposed via `@_spi(QueuePlayerTests)` so unit tests can verify
|
|
663
|
+
/// the derivation; production code reaches it through `download`.
|
|
664
|
+
@_spi(QueuePlayerTests)
|
|
665
|
+
public static func fileName(
|
|
666
|
+
forUrl url: String, contentType: String? = nil
|
|
667
|
+
) -> String {
|
|
668
|
+
let hash = SHA256.hash(data: Data(url.utf8))
|
|
669
|
+
let hex = hash.map { String(format: "%02x", $0) }.joined()
|
|
670
|
+
let prefix = url.unicodeScalars.prefix(16).map { scalar -> Character in
|
|
671
|
+
let c = Character(scalar)
|
|
672
|
+
if c.isLetter || c.isNumber || c == "-" || c == "_" { return c }
|
|
673
|
+
return "_"
|
|
674
|
+
}
|
|
675
|
+
let prefixString = String(prefix)
|
|
676
|
+
let ext = extensionFromMimeType(contentType)
|
|
677
|
+
?? extensionFromUrl(url)
|
|
678
|
+
?? "bin"
|
|
679
|
+
return "\(prefixString.isEmpty ? "track" : prefixString)-\(hex).\(ext)"
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
/// Map an HTTP `Content-Type` value to a file-extension hint that
|
|
683
|
+
/// AVFoundation recognises. Returns `nil` for unknown / missing
|
|
684
|
+
/// types so the caller can fall through to URL-derived hints.
|
|
685
|
+
/// `application/octet-stream` (default for some Subsonic configs)
|
|
686
|
+
/// is treated as unknown — caller falls back to URL hints.
|
|
687
|
+
@_spi(QueuePlayerTests)
|
|
688
|
+
public static func extensionFromMimeType(_ contentType: String?) -> String? {
|
|
689
|
+
guard let raw = contentType, !raw.isEmpty else { return nil }
|
|
690
|
+
// Strip parameter suffix (e.g. `audio/flac; charset=utf-8`).
|
|
691
|
+
// `prefix(while:)` returns the entire string when there's no `;`.
|
|
692
|
+
let head = raw.prefix(while: { $0 != ";" })
|
|
693
|
+
let normalised = String(head).trimmingCharacters(in: .whitespaces).lowercased()
|
|
694
|
+
switch normalised {
|
|
695
|
+
case "audio/mpeg": return "mp3"
|
|
696
|
+
case "audio/mp4", "audio/mp4a-latm": return "m4a"
|
|
697
|
+
case "audio/aac": return "aac"
|
|
698
|
+
case "audio/wav", "audio/wave", "audio/x-wav": return "wav"
|
|
699
|
+
case "audio/flac", "audio/x-flac": return "flac"
|
|
700
|
+
case "audio/ogg", "application/ogg": return "ogg"
|
|
701
|
+
case "audio/opus": return "opus"
|
|
702
|
+
case "audio/x-m4a": return "m4a"
|
|
703
|
+
case "application/x-mpegurl", "application/vnd.apple.mpegurl": return "m3u8"
|
|
704
|
+
default: return nil
|
|
705
|
+
}
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
/// URL-side extension fallback — the URL's path extension when it
|
|
709
|
+
/// names a known audio format (`song.mp3`, `track.m4a`,
|
|
710
|
+
/// `playlist.m3u8`). Returns `nil` for opaque / parameterised URLs
|
|
711
|
+
/// so the caller can fall through to the `.bin` default.
|
|
712
|
+
@_spi(QueuePlayerTests)
|
|
713
|
+
public static func extensionFromUrl(_ url: String) -> String? {
|
|
714
|
+
guard let components = URLComponents(string: url) else { return nil }
|
|
715
|
+
let path = components.path
|
|
716
|
+
if let dotIndex = path.lastIndex(of: ".") {
|
|
717
|
+
let ext = String(path[path.index(after: dotIndex)...]).lowercased()
|
|
718
|
+
// Canonicalise `.mp4` → `m4a` to match `extensionFromMimeType`'s
|
|
719
|
+
// `audio/mp4 → m4a` mapping. Both extensions are AVFoundation-
|
|
720
|
+
// playable but the canonical audio form keeps URL-derived and
|
|
721
|
+
// Content-Type-derived names symmetric so the same cached file
|
|
722
|
+
// never appears under two suffixes across re-cache cycles.
|
|
723
|
+
if ext == "mp4" { return "m4a" }
|
|
724
|
+
if Self.knownAudioExtensions.contains(ext) { return ext }
|
|
725
|
+
}
|
|
726
|
+
return nil
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
private static let knownAudioExtensions: Set<String> = [
|
|
730
|
+
"mp3", "m4a", "m4b", "m4r", "aac",
|
|
731
|
+
"wav", "wave", "flac", "ogg", "opus", "m3u8"
|
|
732
|
+
]
|
|
733
|
+
|
|
734
|
+
// MARK: - Constants
|
|
735
|
+
|
|
736
|
+
/// Default cache budget. The bootstrap budget is deliberately
|
|
737
|
+
/// smaller than the consumer-facing API's 500 MB default so a
|
|
738
|
+
/// fresh install doesn't surprise users with half a gigabyte of
|
|
739
|
+
/// automatic disk usage. Mirrors Android.
|
|
740
|
+
public static let DEFAULT_MAX_SIZE_BYTES: UInt64 = 100 * 1024 * 1024
|
|
741
|
+
|
|
742
|
+
/// 1 MB in bytes — the minimum cache budget enforced at every
|
|
743
|
+
/// site that converts `PlayerConfig.lookaheadCacheMaxSizeMb` into
|
|
744
|
+
/// a byte budget. Mirrors Android's `LookaheadCache.BYTES_PER_MB`
|
|
745
|
+
/// minimum-floor.
|
|
746
|
+
public static let BYTES_PER_MB: UInt64 = 1024 * 1024
|
|
747
|
+
|
|
748
|
+
/// Convert a Double-typed cache budget (MB) from
|
|
749
|
+
/// `PlayerConfig.lookaheadCacheMaxSizeMb` into a `UInt64` byte budget. Multiplies
|
|
750
|
+
/// in Double space BEFORE the `UInt64` cast so a 0.5 MB request
|
|
751
|
+
/// produces 524288 bytes intermediate (then floored to `BYTES_PER_MB`
|
|
752
|
+
/// = 1 MB on the final return) rather than 0 bytes (which the
|
|
753
|
+
/// bare `UInt64(0.5) * BYTES_PER_MB = 0` shape would produce).
|
|
754
|
+
/// Floors at `BYTES_PER_MB` (1 MB) for cross-platform parity with
|
|
755
|
+
/// Android.
|
|
756
|
+
///
|
|
757
|
+
/// Defends against `NaN` / `±Infinity` from the JS bridge: Swift's
|
|
758
|
+
/// `UInt64(.nan)` and `UInt64(.infinity)` both trap, so a JS caller
|
|
759
|
+
/// passing `Number.NaN` or `Number.POSITIVE_INFINITY` would crash
|
|
760
|
+
/// the app. Treat non-finite inputs as "garbage in → safe minimum"
|
|
761
|
+
/// and return `BYTES_PER_MB` directly. Mirrors Android's
|
|
762
|
+
/// `LookaheadCache.maxBytesForMb` defence.
|
|
763
|
+
public static func maxBytes(forMb maxCacheSizeMb: Double) -> UInt64 {
|
|
764
|
+
guard maxCacheSizeMb.isFinite else { return BYTES_PER_MB }
|
|
765
|
+
let raw = max(0, maxCacheSizeMb) * Double(BYTES_PER_MB)
|
|
766
|
+
let asBytes = UInt64(raw)
|
|
767
|
+
return max(asBytes, BYTES_PER_MB)
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
// MARK: - Nested types
|
|
771
|
+
|
|
772
|
+
/// Per-track metadata persisted in the plist index.
|
|
773
|
+
public struct Entry: Codable, Equatable {
|
|
774
|
+
/// Holds the source URL (the cache key). Named `trackId` for
|
|
775
|
+
/// on-disk plist back-compat; the public APIs use the accurate
|
|
776
|
+
/// `url:` label. Lib-internal state never derives from
|
|
777
|
+
/// consumer-supplied TrackItem fields.
|
|
778
|
+
public let trackId: String
|
|
779
|
+
public let fileName: String
|
|
780
|
+
public let sizeBytes: UInt64
|
|
781
|
+
/// Bumped every time the entry is touched for playback — the `.lru` sort key.
|
|
782
|
+
public var lastAccessTick: UInt64
|
|
783
|
+
/// Stamped once at download, never bumped — the `.fifo` sort key.
|
|
784
|
+
public let insertionOrderTick: UInt64
|
|
785
|
+
}
|
|
786
|
+
|
|
787
|
+
/// Plist-encoded index payload. `version` lets a future migration
|
|
788
|
+
/// detect + upgrade old layouts; ships v1.
|
|
789
|
+
internal struct Index: Codable {
|
|
790
|
+
var version: Int
|
|
791
|
+
var entries: [Entry]
|
|
792
|
+
var nextAccessTick: UInt64
|
|
793
|
+
var nextInsertionTick: UInt64
|
|
794
|
+
}
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
/// Errors thrown by `LookaheadCache.download`. Non-throwing scheme
|
|
798
|
+
/// skip (file:// etc.) returns silently — this enum only covers
|
|
799
|
+
/// real failures the caller might want to log.
|
|
800
|
+
public enum LookaheadCacheError: Error {
|
|
801
|
+
case invalidUrl
|
|
802
|
+
case httpError(statusCode: Int)
|
|
803
|
+
/// `FileManager.moveItem` from temp → cache directory failed
|
|
804
|
+
/// (sandbox / cross-volume / permission). Without surfacing this,
|
|
805
|
+
/// the prefetcher would log "track processed" with success
|
|
806
|
+
/// semantics while no `Entry` was appended; subsequent
|
|
807
|
+
/// `cachedURL` lookups return nil and the cache-status snapshot
|
|
808
|
+
/// lies. See `download(track:headers:)` for the throw site.
|
|
809
|
+
case moveFailed(underlying: Error)
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
/// Abstraction over `LookaheadCache.download` so the prefetcher
|
|
813
|
+
/// can be unit-tested with a stub conformer that records
|
|
814
|
+
/// invocations without touching `URLSession`. Production code uses
|
|
815
|
+
/// `LookaheadCache` itself (which conforms below).
|
|
816
|
+
///
|
|
817
|
+
/// Gated behind `@_spi(QueuePlayerTests)` — only consumer is the
|
|
818
|
+
/// test stub. Production callers reach `LookaheadCache` directly
|
|
819
|
+
/// via `LookaheadCachePrefetcher.init(cache:)`.
|
|
820
|
+
@_spi(QueuePlayerTests)
|
|
821
|
+
public protocol LookaheadCacheDownloader: AnyObject {
|
|
822
|
+
func download(track: TrackItem, headers: [String: String]?) async throws
|
|
823
|
+
|
|
824
|
+
/// Reports whether the underlying cache holds a complete copy of
|
|
825
|
+
/// `url`. The prefetcher reads this in `reschedule` to skip
|
|
826
|
+
/// re-enqueuing already-cached URLs and inside the orchestrator
|
|
827
|
+
/// loop to skip a popped target whose bytes landed via another
|
|
828
|
+
/// path before the loop reached it.
|
|
829
|
+
func isFullyCached(url: String) -> Bool
|
|
830
|
+
}
|
|
831
|
+
|
|
832
|
+
@_spi(QueuePlayerTests)
|
|
833
|
+
extension LookaheadCache: LookaheadCacheDownloader {}
|