@glassly/bluetooth-sdk 0.1.0-dev.26

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (548) hide show
  1. package/README.md +563 -0
  2. package/android/build.gradle +450 -0
  3. package/android/gradle.properties.example +9 -0
  4. package/android/lc3Lib/CMakeLists.txt +6 -0
  5. package/android/lc3Lib/build.gradle +212 -0
  6. package/android/lc3Lib/proguard-rules.pro +33 -0
  7. package/android/lc3Lib/src/main/AndroidManifest.xml +2 -0
  8. package/android/lc3Lib/src/main/cpp/CMakeLists.txt +8 -0
  9. package/android/lc3Lib/src/main/cpp/google_opus_stuff/CMakeLists.txt +30 -0
  10. package/android/lc3Lib/src/main/cpp/google_opus_stuff/jni/CMakeLists.txt +7 -0
  11. package/android/lc3Lib/src/main/cpp/google_opus_stuff/jni/ogg_opus_encoder.cc +96 -0
  12. package/android/lc3Lib/src/main/cpp/google_opus_stuff/jni/ogg_opus_encoder.h +53 -0
  13. package/android/lc3Lib/src/main/cpp/google_opus_stuff/libogg/Makefile.am +6 -0
  14. package/android/lc3Lib/src/main/cpp/google_opus_stuff/libogg/config_types.h +26 -0
  15. package/android/lc3Lib/src/main/cpp/google_opus_stuff/libogg/config_types.h.in +26 -0
  16. package/android/lc3Lib/src/main/cpp/google_opus_stuff/libogg/ogg.h +209 -0
  17. package/android/lc3Lib/src/main/cpp/google_opus_stuff/libogg/os_types.h +158 -0
  18. package/android/lc3Lib/src/main/cpp/google_opus_stuff/libopus/opus.h +981 -0
  19. package/android/lc3Lib/src/main/cpp/google_opus_stuff/libopus/opus_custom.h +342 -0
  20. package/android/lc3Lib/src/main/cpp/google_opus_stuff/libopus/opus_defines.h +799 -0
  21. package/android/lc3Lib/src/main/cpp/google_opus_stuff/libopus/opus_multistream.h +660 -0
  22. package/android/lc3Lib/src/main/cpp/google_opus_stuff/libopus/opus_projection.h +568 -0
  23. package/android/lc3Lib/src/main/cpp/google_opus_stuff/libopus/opus_types.h +166 -0
  24. package/android/lc3Lib/src/main/cpp/google_opus_stuff/ogg_opus_encoder.cc +268 -0
  25. package/android/lc3Lib/src/main/cpp/google_opus_stuff/ogg_opus_encoder.h +115 -0
  26. package/android/lc3Lib/src/main/cpp/google_opus_stuff/opus_tools/opus_header.h +59 -0
  27. package/android/lc3Lib/src/main/cpp/liblc3/CMakeLists.txt +38 -0
  28. package/android/lc3Lib/src/main/cpp/liblc3/include/lc3.h +309 -0
  29. package/android/lc3Lib/src/main/cpp/liblc3/include/lc3_private.h +162 -0
  30. package/android/lc3Lib/src/main/cpp/liblc3/include/rnnoise.h +114 -0
  31. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/CMakeLists.txt +19 -0
  32. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/attdet.c +92 -0
  33. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/attdet.h +44 -0
  34. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/bits.c +375 -0
  35. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/bits.h +315 -0
  36. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/bwdet.c +129 -0
  37. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/bwdet.h +69 -0
  38. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/common.h +148 -0
  39. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/energy.c +70 -0
  40. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/energy.h +43 -0
  41. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/fastmath.h +158 -0
  42. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/lc3.c +702 -0
  43. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/ltpf.c +893 -0
  44. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/ltpf.h +111 -0
  45. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/ltpf_arm.h +506 -0
  46. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/ltpf_neon.h +281 -0
  47. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/makefile.mk +35 -0
  48. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/mdct.c +452 -0
  49. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/mdct.h +57 -0
  50. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/mdct_neon.h +296 -0
  51. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/meson.build +46 -0
  52. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/plc.c +61 -0
  53. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/plc.h +57 -0
  54. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/sns.c +880 -0
  55. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/sns.h +103 -0
  56. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/spec.c +904 -0
  57. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/spec.h +119 -0
  58. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/tables.c +3457 -0
  59. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/tables.h +94 -0
  60. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/tns.c +457 -0
  61. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/tns.h +99 -0
  62. package/android/lc3Lib/src/main/cpp/liblc3/liblc3.cpp +159 -0
  63. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/_kiss_fft_guts.h +182 -0
  64. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/arch.h +261 -0
  65. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/celt_lpc.c +279 -0
  66. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/celt_lpc.h +59 -0
  67. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/common.h +48 -0
  68. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/compile.sh +3 -0
  69. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/denoise.c +646 -0
  70. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/kiss_fft.c +601 -0
  71. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/kiss_fft.h +203 -0
  72. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/opus_types.h +159 -0
  73. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/pitch.c +526 -0
  74. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/pitch.h +149 -0
  75. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/rnn.c +178 -0
  76. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/rnn.h +69 -0
  77. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/rnn_data.c +11051 -0
  78. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/rnn_data.h +34 -0
  79. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/rnn_reader.c +168 -0
  80. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/rnn_train.py +66 -0
  81. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/tansig_table.h +45 -0
  82. package/android/lc3Lib/src/main/java/com/glassly/lc3Lib/Lc3Cpp.java +38 -0
  83. package/android/lc3Lib/third_party/CMakeLists.txt +23 -0
  84. package/android/lc3Lib/third_party/CMakeLists_libogg.txt +18 -0
  85. package/android/lc3Lib/third_party/CMakeLists_libopus.txt +18 -0
  86. package/android/lc3Lib/third_party/CMakeLists_opus-tools.txt +23 -0
  87. package/android/lc3Lib/third_party/opus_tools/src/AUTHORS +5 -0
  88. package/android/lc3Lib/third_party/opus_tools/src/CMakeLists.txt +4 -0
  89. package/android/lc3Lib/third_party/opus_tools/src/COPYING +371 -0
  90. package/android/lc3Lib/third_party/opus_tools/src/ChangeLog +3 -0
  91. package/android/lc3Lib/third_party/opus_tools/src/Makefile.am +42 -0
  92. package/android/lc3Lib/third_party/opus_tools/src/Makefile.unix +23 -0
  93. package/android/lc3Lib/third_party/opus_tools/src/NEWS +0 -0
  94. package/android/lc3Lib/third_party/opus_tools/src/README +0 -0
  95. package/android/lc3Lib/third_party/opus_tools/src/autogen.sh +115 -0
  96. package/android/lc3Lib/third_party/opus_tools/src/configure.ac +293 -0
  97. package/android/lc3Lib/third_party/opus_tools/src/src/arch.h +239 -0
  98. package/android/lc3Lib/third_party/opus_tools/src/src/audio-in.c +1046 -0
  99. package/android/lc3Lib/third_party/opus_tools/src/src/diag_range.c +245 -0
  100. package/android/lc3Lib/third_party/opus_tools/src/src/diag_range.h +28 -0
  101. package/android/lc3Lib/third_party/opus_tools/src/src/info_opus.c +320 -0
  102. package/android/lc3Lib/third_party/opus_tools/src/src/info_opus.h +51 -0
  103. package/android/lc3Lib/third_party/opus_tools/src/src/lpc.c +157 -0
  104. package/android/lc3Lib/third_party/opus_tools/src/src/lpc.h +27 -0
  105. package/android/lc3Lib/third_party/opus_tools/src/src/opus_header.c +286 -0
  106. package/android/lc3Lib/third_party/opus_tools/src/src/opus_header.h +59 -0
  107. package/android/lc3Lib/third_party/opus_tools/src/src/opusdec.c +884 -0
  108. package/android/lc3Lib/third_party/opus_tools/src/src/opusenc.c +1021 -0
  109. package/android/lc3Lib/third_party/opus_tools/src/src/opusenc.h +101 -0
  110. package/android/lc3Lib/third_party/opus_tools/src/src/opusinfo.c +639 -0
  111. package/android/lc3Lib/third_party/opus_tools/src/src/opusinfo.h +51 -0
  112. package/android/lc3Lib/third_party/opus_tools/src/src/os_support.h +167 -0
  113. package/android/lc3Lib/third_party/opus_tools/src/src/resample.c +1137 -0
  114. package/android/lc3Lib/third_party/opus_tools/src/src/speex_resampler.h +344 -0
  115. package/android/lc3Lib/third_party/opus_tools/src/src/stack_alloc.h +115 -0
  116. package/android/lc3Lib/third_party/opus_tools/src/src/wav_io.c +125 -0
  117. package/android/lc3Lib/third_party/opus_tools/src/src/wav_io.h +62 -0
  118. package/android/lc3Lib/third_party/opus_tools/src/src/wave_out.c +223 -0
  119. package/android/lc3Lib/third_party/opus_tools/src/src/wave_out.h +60 -0
  120. package/android/settings.gradle +4 -0
  121. package/android/silero/LICENSE.md +17 -0
  122. package/android/silero/build.gradle +50 -0
  123. package/android/silero/proguard-rules.pro +24 -0
  124. package/android/silero/src/androidTest/assets/hello.wav +0 -0
  125. package/android/silero/src/androidTest/java/com/konovalov/vad/silero/VadSileroTest.kt +79 -0
  126. package/android/silero/src/main/assets/LICENSE +21 -0
  127. package/android/silero/src/main/assets/silero_vad.onnx +0 -0
  128. package/android/silero/src/main/java/com/konovalov/vad/silero/Vad.kt +160 -0
  129. package/android/silero/src/main/java/com/konovalov/vad/silero/VadSilero.kt +449 -0
  130. package/android/silero/src/main/java/com/konovalov/vad/silero/config/FrameSize.kt +15 -0
  131. package/android/silero/src/main/java/com/konovalov/vad/silero/config/Mode.kt +14 -0
  132. package/android/silero/src/main/java/com/konovalov/vad/silero/config/SampleRate.kt +12 -0
  133. package/android/silero/src/main/java/com/konovalov/vad/silero/utils/AudioUtils.kt +47 -0
  134. package/android/silero/src/main/java/com/konovalov/vad/silero/utils/TensorMap.kt +41 -0
  135. package/android/silero/src/test/java/com/konovalov/vad/silero/utils/AudioUtilsTest.kt +44 -0
  136. package/android/src/main/AndroidManifest.xml +42 -0
  137. package/android/src/main/assets/G2Firmware/README.md +11 -0
  138. package/android/src/main/java/com/glassly/bluetoothsdk/BluetoothSdk.kt +2325 -0
  139. package/android/src/main/java/com/glassly/bluetoothsdk/BluetoothSdkAnalytics.kt +216 -0
  140. package/android/src/main/java/com/glassly/bluetoothsdk/BluetoothSdkDebug.kt +14 -0
  141. package/android/src/main/java/com/glassly/bluetoothsdk/BluetoothSdkDefaults.kt +7 -0
  142. package/android/src/main/java/com/glassly/bluetoothsdk/BluetoothSdkModule.kt +1088 -0
  143. package/android/src/main/java/com/glassly/bluetoothsdk/Bridge.kt +953 -0
  144. package/android/src/main/java/com/glassly/bluetoothsdk/DeviceManager.kt +2528 -0
  145. package/android/src/main/java/com/glassly/bluetoothsdk/DeviceStore.kt +360 -0
  146. package/android/src/main/java/com/glassly/bluetoothsdk/GeneratedChangelogCatalog.kt +8 -0
  147. package/android/src/main/java/com/glassly/bluetoothsdk/GeneratedReleaseMetadata.kt +11 -0
  148. package/android/src/main/java/com/glassly/bluetoothsdk/LocalNetworkModule.kt +414 -0
  149. package/android/src/main/java/com/glassly/bluetoothsdk/ObservableStore.kt +88 -0
  150. package/android/src/main/java/com/glassly/bluetoothsdk/OtaManifest.kt +191 -0
  151. package/android/src/main/java/com/glassly/bluetoothsdk/ReleaseChangelog.kt +61 -0
  152. package/android/src/main/java/com/glassly/bluetoothsdk/ScopedNetworkReadiness.kt +17 -0
  153. package/android/src/main/java/com/glassly/bluetoothsdk/audio/AudioModels.kt +144 -0
  154. package/android/src/main/java/com/glassly/bluetoothsdk/camera/CameraModels.kt +486 -0
  155. package/android/src/main/java/com/glassly/bluetoothsdk/connection/ConnectionModels.kt +78 -0
  156. package/android/src/main/java/com/glassly/bluetoothsdk/controllers/ControllerManager.kt +158 -0
  157. package/android/src/main/java/com/glassly/bluetoothsdk/controllers/R1.kt +937 -0
  158. package/android/src/main/java/com/glassly/bluetoothsdk/debug/BleTraceLogger.kt +165 -0
  159. package/android/src/main/java/com/glassly/bluetoothsdk/events/BluetoothEvents.kt +178 -0
  160. package/android/src/main/java/com/glassly/bluetoothsdk/internal/MapParsing.kt +140 -0
  161. package/android/src/main/java/com/glassly/bluetoothsdk/net/LocalIpv4.kt +57 -0
  162. package/android/src/main/java/com/glassly/bluetoothsdk/otaserver/LocalOtaServer.kt +304 -0
  163. package/android/src/main/java/com/glassly/bluetoothsdk/otaserver/OtaServerModule.kt +120 -0
  164. package/android/src/main/java/com/glassly/bluetoothsdk/photoreceiver/LocalPhotoReceiverRegistry.java +108 -0
  165. package/android/src/main/java/com/glassly/bluetoothsdk/photoreceiver/LocalPhotoUploadServer.kt +622 -0
  166. package/android/src/main/java/com/glassly/bluetoothsdk/photoreceiver/PhotoReceiverModule.kt +156 -0
  167. package/android/src/main/java/com/glassly/bluetoothsdk/requests/DisplayRequests.kt +56 -0
  168. package/android/src/main/java/com/glassly/bluetoothsdk/services/Foreground.kt +272 -0
  169. package/android/src/main/java/com/glassly/bluetoothsdk/services/PhoneMic.kt +1195 -0
  170. package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/Ar99.java +2653 -0
  171. package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/BesOtaHeartbeatGuard.kt +49 -0
  172. package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/BesOtaProgressMapper.kt +27 -0
  173. package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/G1.kt +3878 -0
  174. package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/G1TextSanitizer.kt +38 -0
  175. package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/G2.kt +6428 -0
  176. package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/G2CfwClassification.kt +49 -0
  177. package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/G2CfwRenderer.kt +1241 -0
  178. package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/G2CfwTextureCache.kt +270 -0
  179. package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/G2FlashProtocol.kt +291 -0
  180. package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/G2Flasher.kt +411 -0
  181. package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/GlasslyBle.java +43189 -0
  182. package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/Mach1.kt +1280 -0
  183. package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/MentraLive.kt +10817 -0
  184. package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/MentraLiveL2capChannel.kt +274 -0
  185. package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/MentraLivePairingAdvertisement.kt +54 -0
  186. package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/MentraNex.kt +2011 -0
  187. package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/Nimo.kt +2532 -0
  188. package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/SGCManager.kt +470 -0
  189. package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/Simulated.kt +228 -0
  190. package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/ar99/ota/Ar99OtaManager.java +566 -0
  191. package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/ar99/ota/OtaByteUtils.java +18 -0
  192. package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/ar99/ota/OtaCommandConstants.java +35 -0
  193. package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/ar99/ota/OtaCrc32Util.java +13 -0
  194. package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/ar99/ota/OtaGattTransport.java +11 -0
  195. package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/ar99/ota/OtaProtocol.java +92 -0
  196. package/android/src/main/java/com/glassly/bluetoothsdk/speakerid/SpeakerIdEngine.kt +525 -0
  197. package/android/src/main/java/com/glassly/bluetoothsdk/status/DeviceStatus.kt +669 -0
  198. package/android/src/main/java/com/glassly/bluetoothsdk/status/RuntimeState.kt +201 -0
  199. package/android/src/main/java/com/glassly/bluetoothsdk/status/WifiHotspotStatus.kt +189 -0
  200. package/android/src/main/java/com/glassly/bluetoothsdk/streaming/StreamModels.kt +518 -0
  201. package/android/src/main/java/com/glassly/bluetoothsdk/stt/STTTools.kt +391 -0
  202. package/android/src/main/java/com/glassly/bluetoothsdk/stt/SherpaOnnxTranscriber.kt +518 -0
  203. package/android/src/main/java/com/glassly/bluetoothsdk/stt/VadGateSpeechPolicy.kt +229 -0
  204. package/android/src/main/java/com/glassly/bluetoothsdk/tts/TTSTools.kt +248 -0
  205. package/android/src/main/java/com/glassly/bluetoothsdk/types/DeviceModels.kt +96 -0
  206. package/android/src/main/java/com/glassly/bluetoothsdk/utils/AES.java +106 -0
  207. package/android/src/main/java/com/glassly/bluetoothsdk/utils/AudioSessionMonitor.kt +189 -0
  208. package/android/src/main/java/com/glassly/bluetoothsdk/utils/AvifExifStripper.java +573 -0
  209. package/android/src/main/java/com/glassly/bluetoothsdk/utils/BitmapJavaUtils.java +169 -0
  210. package/android/src/main/java/com/glassly/bluetoothsdk/utils/BleJsonCompact.java +496 -0
  211. package/android/src/main/java/com/glassly/bluetoothsdk/utils/BlePhotoUploadService.java +677 -0
  212. package/android/src/main/java/com/glassly/bluetoothsdk/utils/BleWireProtocol.java +108 -0
  213. package/android/src/main/java/com/glassly/bluetoothsdk/utils/Constants.kt +46 -0
  214. package/android/src/main/java/com/glassly/bluetoothsdk/utils/G1Text.kt +436 -0
  215. package/android/src/main/java/com/glassly/bluetoothsdk/utils/HeifExifTagReader.java +199 -0
  216. package/android/src/main/java/com/glassly/bluetoothsdk/utils/IncidentLogBleRelayNaming.java +29 -0
  217. package/android/src/main/java/com/glassly/bluetoothsdk/utils/IncidentLogBleUploadService.java +77 -0
  218. package/android/src/main/java/com/glassly/bluetoothsdk/utils/K900LengthCodec.java +115 -0
  219. package/android/src/main/java/com/glassly/bluetoothsdk/utils/K900ProtocolUtils.java +827 -0
  220. package/android/src/main/java/com/glassly/bluetoothsdk/utils/MessageChunkReassembler.java +228 -0
  221. package/android/src/main/java/com/glassly/bluetoothsdk/utils/MessageChunker.java +325 -0
  222. package/android/src/main/java/com/glassly/bluetoothsdk/utils/NexSGCUtils.kt +698 -0
  223. package/android/src/main/java/com/glassly/bluetoothsdk/utils/PhoneAudioMonitor.kt +348 -0
  224. package/android/src/main/java/com/glassly/bluetoothsdk/utils/SmartGlassesConnectionState.java +9 -0
  225. package/android/src/main/java/com/glassly/bluetoothsdk/utils/audio/Ar99OpusPcmDecoder.java +398 -0
  226. package/android/src/main/java/com/glassly/bluetoothsdk/utils/audio/ByteUtilAudioPlayer.java +655 -0
  227. package/android/src/main/java/com/glassly/bluetoothsdk/utils/audio/Lc3Player.java +441 -0
  228. package/android/src/main/java/com/glassly/bluetoothsdk/utils/audio/PCMAudioPlayer.java +431 -0
  229. package/android/src/main/java/com/glassly/bluetoothsdk/utils/audio/PcmStreamPlayer.kt +328 -0
  230. package/android/src/main/res/values/strings.xml +4 -0
  231. package/android/src/test/java/com/glassly/bluetoothsdk/BluetoothSdkExceptionTest.kt +18 -0
  232. package/android/src/test/java/com/glassly/bluetoothsdk/OtaManifestDowngradeTest.kt +86 -0
  233. package/android/src/test/java/com/glassly/bluetoothsdk/OtaStartResponsePolicyTest.kt +30 -0
  234. package/android/src/test/java/com/glassly/bluetoothsdk/ReleaseChangelogTest.kt +13 -0
  235. package/android/src/test/java/com/glassly/bluetoothsdk/ScopedNetworkReadinessTest.kt +39 -0
  236. package/android/src/test/java/com/glassly/bluetoothsdk/StreamStatusEventTest.kt +29 -0
  237. package/android/src/test/java/com/glassly/bluetoothsdk/camera/PhotoRequestTest.kt +141 -0
  238. package/android/src/test/java/com/glassly/bluetoothsdk/otaserver/LocalOtaServerTest.kt +82 -0
  239. package/android/src/test/java/com/glassly/bluetoothsdk/photoreceiver/LocalPhotoReceiverRegistryTest.java +75 -0
  240. package/android/src/test/java/com/glassly/bluetoothsdk/services/ForegroundServiceTypeTest.kt +69 -0
  241. package/android/src/test/java/com/glassly/bluetoothsdk/sgcs/Ar99AdvertisementMatcherTest.java +22 -0
  242. package/android/src/test/java/com/glassly/bluetoothsdk/sgcs/BesOtaHeartbeatGuardTest.kt +73 -0
  243. package/android/src/test/java/com/glassly/bluetoothsdk/sgcs/BesOtaProgressMapperTest.kt +67 -0
  244. package/android/src/test/java/com/glassly/bluetoothsdk/sgcs/EvenRleTest.kt +63 -0
  245. package/android/src/test/java/com/glassly/bluetoothsdk/sgcs/G1TextSanitizerTest.kt +31 -0
  246. package/android/src/test/java/com/glassly/bluetoothsdk/sgcs/G2CfwClassificationTest.kt +89 -0
  247. package/android/src/test/java/com/glassly/bluetoothsdk/sgcs/G2CfwRendererTest.kt +344 -0
  248. package/android/src/test/java/com/glassly/bluetoothsdk/sgcs/G2CfwTextureCacheTest.kt +200 -0
  249. package/android/src/test/java/com/glassly/bluetoothsdk/sgcs/G2FlashProtocolTest.kt +131 -0
  250. package/android/src/test/java/com/glassly/bluetoothsdk/sgcs/MentraLiveGattCharacteristicsTest.kt +39 -0
  251. package/android/src/test/java/com/glassly/bluetoothsdk/sgcs/MentraLivePairingAdvertisementParserTest.kt +133 -0
  252. package/android/src/test/java/com/glassly/bluetoothsdk/sgcs/NimoProtocolTest.kt +333 -0
  253. package/android/src/test/java/com/glassly/bluetoothsdk/utils/AvifExifStripperTest.java +46 -0
  254. package/android/src/test/java/com/glassly/bluetoothsdk/utils/BinaryMessageChunkerTest.java +84 -0
  255. package/android/src/test/java/com/glassly/bluetoothsdk/utils/BleJsonCompactTest.java +319 -0
  256. package/android/src/test/java/com/glassly/bluetoothsdk/utils/BlePhotoUploadServiceTest.java +107 -0
  257. package/android/src/test/java/com/glassly/bluetoothsdk/utils/K900ProtocolUtilsEndiannessTest.java +172 -0
  258. package/android/src/test/java/com/glassly/bluetoothsdk/utils/K900ProtocolUtilsTest.java +24 -0
  259. package/android/src/test/java/com/glassly/bluetoothsdk/utils/PhoneAudioMonitorTest.kt +45 -0
  260. package/android/src/test/resources/avif_with_exif.avif +0 -0
  261. package/app.plugin.js +3 -0
  262. package/build/BluetoothSdk.types.d.ts +1354 -0
  263. package/build/BluetoothSdk.types.d.ts.map +1 -0
  264. package/build/BluetoothSdk.types.js +41 -0
  265. package/build/BluetoothSdk.types.js.map +1 -0
  266. package/build/_internal.d.ts +17 -0
  267. package/build/_internal.d.ts.map +1 -0
  268. package/build/_internal.js +16 -0
  269. package/build/_internal.js.map +1 -0
  270. package/build/_private/BluetoothSdkModule.d.ts +172 -0
  271. package/build/_private/BluetoothSdkModule.d.ts.map +1 -0
  272. package/build/_private/BluetoothSdkModule.js +300 -0
  273. package/build/_private/BluetoothSdkModule.js.map +1 -0
  274. package/build/_private/LocalNetworkModule.d.ts +38 -0
  275. package/build/_private/LocalNetworkModule.d.ts.map +1 -0
  276. package/build/_private/LocalNetworkModule.js +3 -0
  277. package/build/_private/LocalNetworkModule.js.map +1 -0
  278. package/build/_private/cameraRequestPayload.d.ts +4 -0
  279. package/build/_private/cameraRequestPayload.d.ts.map +1 -0
  280. package/build/_private/cameraRequestPayload.js +32 -0
  281. package/build/_private/cameraRequestPayload.js.map +1 -0
  282. package/build/_private/photoRequestPayload.d.ts +6 -0
  283. package/build/_private/photoRequestPayload.d.ts.map +1 -0
  284. package/build/_private/photoRequestPayload.js +86 -0
  285. package/build/_private/photoRequestPayload.js.map +1 -0
  286. package/build/_private/sdkOtaManifest.d.ts +11 -0
  287. package/build/_private/sdkOtaManifest.d.ts.map +1 -0
  288. package/build/_private/sdkOtaManifest.js +15 -0
  289. package/build/_private/sdkOtaManifest.js.map +1 -0
  290. package/build/changelogs.d.ts +7 -0
  291. package/build/changelogs.d.ts.map +1 -0
  292. package/build/changelogs.js +46 -0
  293. package/build/changelogs.js.map +1 -0
  294. package/build/debug.d.ts +3 -0
  295. package/build/debug.d.ts.map +1 -0
  296. package/build/debug.js +8 -0
  297. package/build/debug.js.map +1 -0
  298. package/build/generated/changelogCatalog.d.ts +9 -0
  299. package/build/generated/changelogCatalog.d.ts.map +1 -0
  300. package/build/generated/changelogCatalog.js +12 -0
  301. package/build/generated/changelogCatalog.js.map +1 -0
  302. package/build/generated/releaseMetadata.d.ts +12 -0
  303. package/build/generated/releaseMetadata.d.ts.map +1 -0
  304. package/build/generated/releaseMetadata.js +10 -0
  305. package/build/generated/releaseMetadata.js.map +1 -0
  306. package/build/index.d.ts +6 -0
  307. package/build/index.d.ts.map +1 -0
  308. package/build/index.js +171 -0
  309. package/build/index.js.map +1 -0
  310. package/build/ota-server/OtaServer.types.d.ts +14 -0
  311. package/build/ota-server/OtaServer.types.d.ts.map +1 -0
  312. package/build/ota-server/OtaServer.types.js +2 -0
  313. package/build/ota-server/OtaServer.types.js.map +1 -0
  314. package/build/ota-server/OtaServerModule.d.ts +21 -0
  315. package/build/ota-server/OtaServerModule.d.ts.map +1 -0
  316. package/build/ota-server/OtaServerModule.js +3 -0
  317. package/build/ota-server/OtaServerModule.js.map +1 -0
  318. package/build/ota-server/OtaServerModule.web.d.ts +10 -0
  319. package/build/ota-server/OtaServerModule.web.d.ts.map +1 -0
  320. package/build/ota-server/OtaServerModule.web.js +12 -0
  321. package/build/ota-server/OtaServerModule.web.js.map +1 -0
  322. package/build/ota-server/index.d.ts +3 -0
  323. package/build/ota-server/index.d.ts.map +1 -0
  324. package/build/ota-server/index.js +3 -0
  325. package/build/ota-server/index.js.map +1 -0
  326. package/build/ota-transport/index.d.ts +67 -0
  327. package/build/ota-transport/index.d.ts.map +1 -0
  328. package/build/ota-transport/index.js +58 -0
  329. package/build/ota-transport/index.js.map +1 -0
  330. package/build/photo-receiver/PhotoReceiver.types.d.ts +18 -0
  331. package/build/photo-receiver/PhotoReceiver.types.d.ts.map +1 -0
  332. package/build/photo-receiver/PhotoReceiver.types.js +2 -0
  333. package/build/photo-receiver/PhotoReceiver.types.js.map +1 -0
  334. package/build/photo-receiver/PhotoReceiverModule.d.ts +10 -0
  335. package/build/photo-receiver/PhotoReceiverModule.d.ts.map +1 -0
  336. package/build/photo-receiver/PhotoReceiverModule.js +3 -0
  337. package/build/photo-receiver/PhotoReceiverModule.js.map +1 -0
  338. package/build/photo-receiver/PhotoReceiverModule.web.d.ts +10 -0
  339. package/build/photo-receiver/PhotoReceiverModule.web.d.ts.map +1 -0
  340. package/build/photo-receiver/PhotoReceiverModule.web.js +12 -0
  341. package/build/photo-receiver/PhotoReceiverModule.web.js.map +1 -0
  342. package/build/photo-receiver/index.d.ts +3 -0
  343. package/build/photo-receiver/index.d.ts.map +1 -0
  344. package/build/photo-receiver/index.js +3 -0
  345. package/build/photo-receiver/index.js.map +1 -0
  346. package/build/react/index.d.ts +5 -0
  347. package/build/react/index.d.ts.map +1 -0
  348. package/build/react/index.js +4 -0
  349. package/build/react/index.js.map +1 -0
  350. package/build/react/useBluetooth.d.ts +100 -0
  351. package/build/react/useBluetooth.d.ts.map +1 -0
  352. package/build/react/useBluetooth.js +167 -0
  353. package/build/react/useBluetooth.js.map +1 -0
  354. package/build/react/useBluetoothEvent.d.ts +6 -0
  355. package/build/react/useBluetoothEvent.d.ts.map +1 -0
  356. package/build/react/useBluetoothEvent.js +21 -0
  357. package/build/react/useBluetoothEvent.js.map +1 -0
  358. package/build/react/useBluetoothScan.d.ts +22 -0
  359. package/build/react/useBluetoothScan.d.ts.map +1 -0
  360. package/build/react/useBluetoothScan.js +135 -0
  361. package/build/react/useBluetoothScan.js.map +1 -0
  362. package/build/react/useBluetoothStatus.d.ts +16 -0
  363. package/build/react/useBluetoothStatus.d.ts.map +1 -0
  364. package/build/react/useBluetoothStatus.js +137 -0
  365. package/build/react/useBluetoothStatus.js.map +1 -0
  366. package/build/react/useGlassesConnection.d.ts +29 -0
  367. package/build/react/useGlassesConnection.d.ts.map +1 -0
  368. package/build/react/useGlassesConnection.js +153 -0
  369. package/build/react/useGlassesConnection.js.map +1 -0
  370. package/build/types/index.d.ts +3 -0
  371. package/build/types/index.d.ts.map +1 -0
  372. package/build/types/index.js +2 -0
  373. package/build/types/index.js.map +1 -0
  374. package/expo-module.config.json +14 -0
  375. package/ios/BackgroundOtaArtifactDownloader.swift +125 -0
  376. package/ios/BluetoothSdkModule.swift +1034 -0
  377. package/ios/GlasslyBluetoothSDK.podspec +106 -0
  378. package/ios/LocalIPv4.swift +150 -0
  379. package/ios/LocalOtaServer.swift +309 -0
  380. package/ios/LocalPhotoUploadServer.swift +754 -0
  381. package/ios/OtaServerModule.swift +147 -0
  382. package/ios/Packages/CoreObjC/CoreObjC.xcodeproj/project.pbxproj +213 -0
  383. package/ios/Packages/CoreObjC/PcmConverter.h +22 -0
  384. package/ios/Packages/CoreObjC/PcmConverter.m +266 -0
  385. package/ios/Packages/CoreObjC/attdet.c +92 -0
  386. package/ios/Packages/CoreObjC/attdet.h +44 -0
  387. package/ios/Packages/CoreObjC/bits.c +375 -0
  388. package/ios/Packages/CoreObjC/bits.h +315 -0
  389. package/ios/Packages/CoreObjC/bwdet.c +129 -0
  390. package/ios/Packages/CoreObjC/bwdet.h +69 -0
  391. package/ios/Packages/CoreObjC/common.h +151 -0
  392. package/ios/Packages/CoreObjC/energy.c +70 -0
  393. package/ios/Packages/CoreObjC/energy.h +43 -0
  394. package/ios/Packages/CoreObjC/fastmath.h +158 -0
  395. package/ios/Packages/CoreObjC/include/PcmConverter.h +22 -0
  396. package/ios/Packages/CoreObjC/lc3.c +704 -0
  397. package/ios/Packages/CoreObjC/lc3.h +313 -0
  398. package/ios/Packages/CoreObjC/lc3_cpp.h +283 -0
  399. package/ios/Packages/CoreObjC/lc3_private.h +163 -0
  400. package/ios/Packages/CoreObjC/ltpf.c +905 -0
  401. package/ios/Packages/CoreObjC/ltpf.h +111 -0
  402. package/ios/Packages/CoreObjC/ltpf_arm.h +506 -0
  403. package/ios/Packages/CoreObjC/ltpf_neon.h +281 -0
  404. package/ios/Packages/CoreObjC/makefile.mk +35 -0
  405. package/ios/Packages/CoreObjC/mdct.c +469 -0
  406. package/ios/Packages/CoreObjC/mdct.h +57 -0
  407. package/ios/Packages/CoreObjC/mdct_neon.h +296 -0
  408. package/ios/Packages/CoreObjC/meson.build +61 -0
  409. package/ios/Packages/CoreObjC/plc.c +61 -0
  410. package/ios/Packages/CoreObjC/plc.h +57 -0
  411. package/ios/Packages/CoreObjC/rnnoise.h +114 -0
  412. package/ios/Packages/CoreObjC/sns.c +880 -0
  413. package/ios/Packages/CoreObjC/sns.h +103 -0
  414. package/ios/Packages/CoreObjC/spec.c +907 -0
  415. package/ios/Packages/CoreObjC/spec.h +119 -0
  416. package/ios/Packages/CoreObjC/tables.c +3457 -0
  417. package/ios/Packages/CoreObjC/tables.h +94 -0
  418. package/ios/Packages/CoreObjC/tns.c +457 -0
  419. package/ios/Packages/CoreObjC/tns.h +99 -0
  420. package/ios/Packages/SherpaOnnx/Model/joiner.onnx +0 -0
  421. package/ios/Packages/SherpaOnnx/Model/tokens.txt +502 -0
  422. package/ios/Packages/SherpaOnnx/SherpaOnnx.swift +2383 -0
  423. package/ios/Packages/SherpaOnnx/sherpa-onnx.xcframework/Info.plist +48 -0
  424. package/ios/Packages/SherpaOnnx/sherpa-onnx.xcframework/ios-arm64/Headers/sherpa-onnx/c-api/c-api.h +4689 -0
  425. package/ios/Packages/SherpaOnnx/sherpa-onnx.xcframework/ios-arm64/Headers/sherpa-onnx/c-api/cxx-api.h +2036 -0
  426. package/ios/Packages/SherpaOnnx/sherpa-onnx.xcframework/ios-arm64/libsherpa-onnx.a +0 -0
  427. package/ios/Packages/SherpaOnnx/sherpa-onnx.xcframework/ios-arm64_x86_64-simulator/Headers/sherpa-onnx/c-api/c-api.h +4689 -0
  428. package/ios/Packages/SherpaOnnx/sherpa-onnx.xcframework/ios-arm64_x86_64-simulator/Headers/sherpa-onnx/c-api/cxx-api.h +2036 -0
  429. package/ios/Packages/SherpaOnnx/sherpa-onnx.xcframework/ios-arm64_x86_64-simulator/libsherpa-onnx.a +0 -0
  430. package/ios/Packages/libbz2/module.modulemap +5 -0
  431. package/ios/Packages/libbz2/shim.h +1 -0
  432. package/ios/PhotoReceiverModule.swift +129 -0
  433. package/ios/Source/BluetoothSDK.swift +2303 -0
  434. package/ios/Source/BluetoothSDKDebug.swift +12 -0
  435. package/ios/Source/BluetoothSdkDefaults.swift +29 -0
  436. package/ios/Source/Bridge.swift +708 -0
  437. package/ios/Source/Bridging-Header.h +16 -0
  438. package/ios/Source/DeviceManager.swift +2109 -0
  439. package/ios/Source/DeviceStore.swift +336 -0
  440. package/ios/Source/GeneratedChangelogCatalog.swift +7 -0
  441. package/ios/Source/GeneratedReleaseMetadata.swift +11 -0
  442. package/ios/Source/ObservableStore.swift +118 -0
  443. package/ios/Source/OtaManifest.swift +211 -0
  444. package/ios/Source/PrivacyInfo.xcprivacy +23 -0
  445. package/ios/Source/ReleaseChangelog.swift +65 -0
  446. package/ios/Source/Resources/G2Firmware/README.md +10 -0
  447. package/ios/Source/audio/AudioModels.swift +178 -0
  448. package/ios/Source/audio/PcmStreamPlayer.swift +410 -0
  449. package/ios/Source/camera/CameraModels.swift +866 -0
  450. package/ios/Source/connection/ScanSession.swift +27 -0
  451. package/ios/Source/controllers/ControllerManager.swift +184 -0
  452. package/ios/Source/controllers/R1.swift +829 -0
  453. package/ios/Source/errors/BluetoothSdkError.swift +19 -0
  454. package/ios/Source/events/BluetoothEvents.swift +342 -0
  455. package/ios/Source/internal/BleTraceLogger.swift +192 -0
  456. package/ios/Source/internal/BluetoothAvailability.swift +78 -0
  457. package/ios/Source/internal/BluetoothSdkAnalytics.swift +199 -0
  458. package/ios/Source/internal/ValueParsing.swift +99 -0
  459. package/ios/Source/requests/DisplayRequests.swift +82 -0
  460. package/ios/Source/services/PhoneMic.swift +662 -0
  461. package/ios/Source/sgcs/Ar99.swift +2451 -0
  462. package/ios/Source/sgcs/Frame.swift +649 -0
  463. package/ios/Source/sgcs/G1.swift +2554 -0
  464. package/ios/Source/sgcs/G2.swift +6887 -0
  465. package/ios/Source/sgcs/G2CfwClassification.swift +43 -0
  466. package/ios/Source/sgcs/G2CfwRenderer.swift +1279 -0
  467. package/ios/Source/sgcs/G2CfwTextureCache.swift +233 -0
  468. package/ios/Source/sgcs/G2FlashProtocol.swift +312 -0
  469. package/ios/Source/sgcs/G2Flasher.swift +773 -0
  470. package/ios/Source/sgcs/Mach1.swift +541 -0
  471. package/ios/Source/sgcs/MentraLive.swift +7011 -0
  472. package/ios/Source/sgcs/MentraLiveL2capChannel.swift +183 -0
  473. package/ios/Source/sgcs/MentraLivePairingAdvertisement.swift +64 -0
  474. package/ios/Source/sgcs/MentraNex.swift +3221 -0
  475. package/ios/Source/sgcs/Nimo.swift +1886 -0
  476. package/ios/Source/sgcs/SGCManager.swift +608 -0
  477. package/ios/Source/sgcs/Simulated.swift +274 -0
  478. package/ios/Source/sgcs/ar99/ota/Ar99OtaManager.swift +637 -0
  479. package/ios/Source/sgcs/glassly_ble.pb.swift +4354 -0
  480. package/ios/Source/speakerid/SpeakerIdEngine.swift +573 -0
  481. package/ios/Source/status/DeviceStatus.swift +981 -0
  482. package/ios/Source/status/RuntimeState.swift +359 -0
  483. package/ios/Source/status/WifiHotspotStatus.swift +345 -0
  484. package/ios/Source/streaming/StreamModels.swift +693 -0
  485. package/ios/Source/stt/STTTools.swift +191 -0
  486. package/ios/Source/stt/SherpaOnnxTranscriber.swift +466 -0
  487. package/ios/Source/tts/TTSTools.swift +171 -0
  488. package/ios/Source/types/DeviceModels.swift +177 -0
  489. package/ios/Source/utils/AudioSessionMonitor.swift +283 -0
  490. package/ios/Source/utils/BinaryCodec.swift +61 -0
  491. package/ios/Source/utils/BleJsonCompact.swift +405 -0
  492. package/ios/Source/utils/BleWireProtocol.swift +92 -0
  493. package/ios/Source/utils/Constants.swift +78 -0
  494. package/ios/Source/utils/Enums.swift +95 -0
  495. package/ios/Source/utils/G1Text.swift +2096 -0
  496. package/ios/Source/utils/JSCExperiment.swift +241 -0
  497. package/ios/Source/utils/MemoryMonitor.swift +44 -0
  498. package/ios/Source/utils/MessageChunkReassembler.swift +190 -0
  499. package/ios/Source/utils/MessageChunker.swift +294 -0
  500. package/ios/Source/utils/Models.swift +135 -0
  501. package/ios/Source/utils/PhoneAudioMonitor.swift +230 -0
  502. package/ios/Source/utils/TarBz2Extractor.swift +257 -0
  503. package/ios/Tests/BluetoothSDKTests/G2CfwClassificationTests.swift +78 -0
  504. package/ios/Tests/BluetoothSDKTests/G2CfwRendererTests.swift +372 -0
  505. package/ios/Tests/BluetoothSDKTests/G2CfwTextureCacheTests.swift +162 -0
  506. package/ios/Tests/BluetoothSDKTests/G2FlashProtocolTests.swift +182 -0
  507. package/ios/Tests/MentraLivePairingAdvertisementTests.swift +160 -0
  508. package/ios/Tests/ReleaseChangelogTests.swift +13 -0
  509. package/package.json +129 -0
  510. package/plugin/build/index.d.ts +10 -0
  511. package/plugin/build/index.js +12 -0
  512. package/plugin/build/withAndroid.d.ts +3 -0
  513. package/plugin/build/withAndroid.js +190 -0
  514. package/plugin/build/withIos.d.ts +5 -0
  515. package/plugin/build/withIos.js +108 -0
  516. package/scripts/inject-ios-sdk-version.mjs +65 -0
  517. package/scripts/public-ota-api.test.mjs +37 -0
  518. package/scripts/verify-release-package.mjs +45 -0
  519. package/scripts/write-release-metadata.mjs +152 -0
  520. package/scripts/write-release-metadata.test.mjs +37 -0
  521. package/src/BluetoothSdk.types.ts +1623 -0
  522. package/src/_internal.ts +16 -0
  523. package/src/_private/BluetoothSdkModule.ts +684 -0
  524. package/src/_private/LocalNetworkModule.ts +50 -0
  525. package/src/_private/cameraRequestPayload.ts +34 -0
  526. package/src/_private/photoRequestPayload.ts +90 -0
  527. package/src/_private/sdkOtaManifest.ts +18 -0
  528. package/src/changelogs.ts +46 -0
  529. package/src/debug.ts +9 -0
  530. package/src/generated/changelogCatalog.ts +13 -0
  531. package/src/generated/releaseMetadata.ts +20 -0
  532. package/src/index.ts +321 -0
  533. package/src/ota-server/OtaServer.types.ts +10 -0
  534. package/src/ota-server/OtaServerModule.ts +23 -0
  535. package/src/ota-server/OtaServerModule.web.ts +17 -0
  536. package/src/ota-server/index.ts +2 -0
  537. package/src/ota-transport/index.ts +116 -0
  538. package/src/photo-receiver/PhotoReceiver.types.ts +20 -0
  539. package/src/photo-receiver/PhotoReceiverModule.ts +11 -0
  540. package/src/photo-receiver/PhotoReceiverModule.web.ts +17 -0
  541. package/src/photo-receiver/index.ts +2 -0
  542. package/src/react/index.ts +21 -0
  543. package/src/react/useBluetooth.ts +309 -0
  544. package/src/react/useBluetoothEvent.ts +35 -0
  545. package/src/react/useBluetoothScan.ts +173 -0
  546. package/src/react/useBluetoothStatus.ts +180 -0
  547. package/src/react/useGlassesConnection.ts +202 -0
  548. package/src/types/index.ts +12 -0
@@ -0,0 +1,171 @@
1
+ import Foundation
2
+
3
+ /// Utilities for offline Sherpa-ONNX Supertonic 3 TTS.
4
+ ///
5
+ /// Supertonic 3 is a single multilingual model bundle (31 languages) with
6
+ /// 10 preset voice styles packed into voice.bin. Speaker IDs are indexed
7
+ /// alphabetically by JSON filename, so the order is F1, F2, F3, F4, F5,
8
+ /// M1, M2, M3, M4, M5 (sids 0..9). We default to F1 (sid 0) for a female
9
+ /// voice.
10
+ class TTSTools {
11
+ private static let kFileDurationPredictor = "duration_predictor.int8.onnx"
12
+ private static let kFileTextEncoder = "text_encoder.int8.onnx"
13
+ private static let kFileVectorEstimator = "vector_estimator.int8.onnx"
14
+ private static let kFileVocoder = "vocoder.int8.onnx"
15
+ private static let kFileTtsJson = "tts.json"
16
+ private static let kFileUnicodeIndexer = "unicode_indexer.bin"
17
+ private static let kFileVoiceStyle = "voice.bin"
18
+
19
+ private static let kRequiredFiles: [String] = [
20
+ kFileDurationPredictor,
21
+ kFileTextEncoder,
22
+ kFileVectorEstimator,
23
+ kFileVocoder,
24
+ kFileTtsJson,
25
+ kFileUnicodeIndexer,
26
+ kFileVoiceStyle,
27
+ ]
28
+
29
+ private static let kSupportedLangs: Set<String> = [
30
+ "en", "ko", "ja", "ar", "bg", "cs", "da", "de", "el", "es", "et",
31
+ "fi", "fr", "hi", "hr", "hu", "id", "it", "lt", "lv", "nl", "pl",
32
+ "pt", "ro", "ru", "sk", "sl", "sv", "tr", "uk", "vi",
33
+ ]
34
+
35
+ static func setTtsModelDetails(_ path: String, _ languageCode: String) {
36
+ UserDefaults.standard.set(path, forKey: "TTSModelPath")
37
+ UserDefaults.standard.set(languageCode, forKey: "TTSModelLanguageCode")
38
+ UserDefaults.standard.synchronize()
39
+ }
40
+
41
+ static func getTtsModelPath() -> String {
42
+ return UserDefaults.standard.string(forKey: "TTSModelPath") ?? ""
43
+ }
44
+
45
+ static func getTtsModelLanguage() -> String {
46
+ return UserDefaults.standard.string(forKey: "TTSModelLanguageCode") ?? "en-US"
47
+ }
48
+
49
+ static func checkTTSModelAvailable() -> Bool {
50
+ guard let modelPath = UserDefaults.standard.string(forKey: "TTSModelPath") else {
51
+ return false
52
+ }
53
+ return validateTTSModel(modelPath)
54
+ }
55
+
56
+ static func validateTTSModel(_ path: String) -> Bool {
57
+ let fileManager = FileManager.default
58
+ var isDirectory: ObjCBool = false
59
+ if !fileManager.fileExists(atPath: path, isDirectory: &isDirectory) || !isDirectory.boolValue {
60
+ Bridge.log("TTS model path does not exist or is not a directory: \(path)")
61
+ return false
62
+ }
63
+
64
+ for name in kRequiredFiles {
65
+ let filePath = (path as NSString).appendingPathComponent(name)
66
+ if !fileManager.fileExists(atPath: filePath) {
67
+ Bridge.log("TTS model missing required file '\(name)' at: \(path)")
68
+ return false
69
+ }
70
+ let size = (try? fileManager.attributesOfItem(atPath: filePath)[.size] as? UInt64) ?? 0
71
+ if size == 0 {
72
+ Bridge.log("TTS model file '\(name)' is empty at: \(path)")
73
+ return false
74
+ }
75
+ }
76
+
77
+ return true
78
+ }
79
+
80
+ static func generateTtsAudio(
81
+ text: String,
82
+ modelPath: String,
83
+ outputPath: String,
84
+ speakerId: Int,
85
+ speed: Double
86
+ ) -> Bool {
87
+ guard !text.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty else {
88
+ Bridge.log("TTS_ERROR: text is empty")
89
+ return false
90
+ }
91
+ guard validateTTSModel(modelPath) else {
92
+ Bridge.log("TTS_ERROR: model is invalid: \(modelPath)")
93
+ return false
94
+ }
95
+
96
+ do {
97
+ let outputURL = URL(fileURLWithPath: outputPath)
98
+ try FileManager.default.createDirectory(
99
+ at: outputURL.deletingLastPathComponent(),
100
+ withIntermediateDirectories: true,
101
+ attributes: nil
102
+ )
103
+
104
+ // Build the config and construct the engine inside one C-string
105
+ // scope: the config's `const char*` fields point at buffers owned by
106
+ // that scope (see toCPointer in SherpaOnnx.swift). Only construction
107
+ // goes inside — `tts` itself is safe to use afterwards, since
108
+ // sherpa-onnx copies every string during construction.
109
+ let tts = withSherpaOnnxCStrings { () -> SherpaOnnxOfflineTtsWrapper in
110
+ let supertonic = sherpaOnnxOfflineTtsSupertonicModelConfig(
111
+ durationPredictor: (modelPath as NSString).appendingPathComponent(kFileDurationPredictor),
112
+ textEncoder: (modelPath as NSString).appendingPathComponent(kFileTextEncoder),
113
+ vectorEstimator: (modelPath as NSString).appendingPathComponent(kFileVectorEstimator),
114
+ vocoder: (modelPath as NSString).appendingPathComponent(kFileVocoder),
115
+ ttsJson: (modelPath as NSString).appendingPathComponent(kFileTtsJson),
116
+ unicodeIndexer: (modelPath as NSString).appendingPathComponent(kFileUnicodeIndexer),
117
+ voiceStyle: (modelPath as NSString).appendingPathComponent(kFileVoiceStyle)
118
+ )
119
+ let modelConfig = sherpaOnnxOfflineTtsModelConfig(
120
+ numThreads: 8,
121
+ supertonic: supertonic
122
+ )
123
+ var config = sherpaOnnxOfflineTtsConfig(model: modelConfig, maxNumSentences: 1)
124
+ return SherpaOnnxOfflineTtsWrapper(config: &config)
125
+ }
126
+
127
+ // The new wrapper dropped numSpeakers() in v1.13.2; call the C API
128
+ // directly. The C signature accepts the underlying OpaquePointer.
129
+ let numSpeakers = max(1, Int(SherpaOnnxOfflineTtsNumSpeakers(tts.tts)))
130
+ let sid = max(0, min(speakerId, numSpeakers - 1))
131
+ let clampedSpeed = Float(min(max(speed, 0.5), 2.0))
132
+ let lang = languageTagToSupertonicLang(getTtsModelLanguage())
133
+
134
+ // generate(...) no longer accepts `extra`; that field moved onto
135
+ // SherpaOnnxGenerationConfigSwift and is delivered via
136
+ // generateWithConfig(...).
137
+ //
138
+ // numSteps controls the Supertonic flow-matching vocoder's
139
+ // iteration count. The Swift wrapper defaults to 1, which produces
140
+ // unintelligible robot audio — sherpa-onnx's actual C-side default
141
+ // is 5. Pin it here so we don't inherit the wrapper's bug.
142
+ let genConfig = SherpaOnnxGenerationConfigSwift(
143
+ speed: clampedSpeed,
144
+ sid: sid,
145
+ numSteps: 5,
146
+ extra: ["lang": lang]
147
+ )
148
+ let audio = tts.generateWithConfig(
149
+ text: text,
150
+ config: genConfig,
151
+ callback: nil,
152
+ arg: nil
153
+ )
154
+ let saved = audio.save(filename: outputPath) == 1
155
+ Bridge.log(
156
+ "TTS generated \(outputPath): saved=\(saved) sid=\(sid) lang=\(lang) " +
157
+ "sr=\(audio.sampleRate) samples=\(audio.n) speed=\(clampedSpeed)"
158
+ )
159
+ return saved
160
+ } catch {
161
+ Bridge.log("TTS_ERROR: \(error.localizedDescription)")
162
+ return false
163
+ }
164
+ }
165
+
166
+ /// Convert a BCP-47 tag (e.g. "en-US", "fr-FR") to a Supertonic 2-letter code.
167
+ private static func languageTagToSupertonicLang(_ tag: String) -> String {
168
+ let primary = tag.split(separator: "-").first.map(String.init)?.lowercased() ?? "en"
169
+ return kSupportedLangs.contains(primary) ? primary : "en"
170
+ }
171
+ }
@@ -0,0 +1,177 @@
1
+ import Foundation
2
+
3
+ public struct BluetoothSDKConfiguration {
4
+ public static let `default` = BluetoothSDKConfiguration()
5
+
6
+ public let analytics: BluetoothSdkAnalyticsConfiguration
7
+
8
+ public init(analytics: BluetoothSdkAnalyticsConfiguration = BluetoothSdkAnalyticsConfiguration()) {
9
+ self.analytics = analytics
10
+ }
11
+ }
12
+
13
+ public enum DeviceModel: String {
14
+ case g1
15
+ case g2
16
+ case mentraLive
17
+ case mentraNex
18
+ case mach1
19
+ case z100
20
+ case frame
21
+ case nimo
22
+ case ar99
23
+ case simulated
24
+ case r1
25
+
26
+ public var deviceType: String {
27
+ switch self {
28
+ case .g1:
29
+ DeviceTypes.G1
30
+ case .g2:
31
+ DeviceTypes.G2
32
+ case .mentraLive:
33
+ DeviceTypes.LIVE
34
+ case .mentraNex:
35
+ DeviceTypes.NEX
36
+ case .mach1:
37
+ DeviceTypes.MACH1
38
+ case .z100:
39
+ DeviceTypes.Z100
40
+ case .frame:
41
+ DeviceTypes.FRAME
42
+ case .nimo:
43
+ DeviceTypes.NIMO
44
+ case .ar99:
45
+ DeviceTypes.AR99
46
+ case .simulated:
47
+ DeviceTypes.SIMULATED
48
+ case .r1:
49
+ ControllerTypes.R1
50
+ }
51
+ }
52
+
53
+ public static func fromDeviceType(_ deviceType: String?) -> DeviceModel {
54
+ switch deviceType {
55
+ case DeviceTypes.G1:
56
+ .g1
57
+ case DeviceTypes.G2:
58
+ .g2
59
+ case DeviceTypes.LIVE:
60
+ .mentraLive
61
+ case DeviceTypes.NEX:
62
+ .mentraNex
63
+ case DeviceTypes.MACH1:
64
+ .mach1
65
+ case DeviceTypes.Z100:
66
+ .z100
67
+ case DeviceTypes.FRAME:
68
+ .frame
69
+ case DeviceTypes.NIMO:
70
+ .nimo
71
+ case DeviceTypes.AR99:
72
+ .ar99
73
+ case DeviceTypes.SIMULATED:
74
+ .simulated
75
+ case ControllerTypes.R1:
76
+ .r1
77
+ default:
78
+ .mentraLive
79
+ }
80
+ }
81
+ }
82
+
83
+ public struct Device: Identifiable, Equatable, CustomStringConvertible {
84
+ public let model: DeviceModel
85
+ public let name: String
86
+ /// CoreBluetooth identifier when available.
87
+ public let identifier: String?
88
+ public let projectName: String?
89
+ public let rssi: Int?
90
+ /// Stable app-facing scan-result key. Do not parse; use typed fields instead.
91
+ public let id: String
92
+ public let pairingMode: Bool?
93
+ public let pairingCode: String?
94
+ public let securePairingCapable: Bool?
95
+
96
+ public init(
97
+ model: DeviceModel,
98
+ name: String,
99
+ identifier: String? = nil,
100
+ projectName: String? = nil,
101
+ rssi: Int? = nil,
102
+ id: String? = nil,
103
+ pairingMode: Bool? = nil,
104
+ pairingCode: String? = nil,
105
+ securePairingCapable: Bool? = nil
106
+ ) {
107
+ self.model = model
108
+ self.name = name
109
+ self.identifier = identifier
110
+ self.projectName = projectName
111
+ self.rssi = rssi
112
+ self.id = id ?? identifier.flatMap { $0.isEmpty ? nil : $0 } ?? "\(model.deviceType):\(name)"
113
+ self.pairingMode = pairingMode
114
+ self.pairingCode = pairingCode
115
+ self.securePairingCapable = securePairingCapable
116
+ }
117
+
118
+ public var description: String {
119
+ "Device(model: \(model), name: \(name))"
120
+ }
121
+
122
+ var dictionary: [String: Any] {
123
+ var values: [String: Any] = [
124
+ "id": id,
125
+ "model": model.deviceType,
126
+ "name": name,
127
+ ]
128
+ if let identifier, !identifier.isEmpty {
129
+ values["address"] = identifier
130
+ }
131
+ if let projectName, !projectName.isEmpty {
132
+ values["projectName"] = projectName
133
+ }
134
+ if let rssi {
135
+ values["rssi"] = rssi
136
+ }
137
+ if let pairingMode {
138
+ values["pairingMode"] = pairingMode
139
+ }
140
+ if let pairingCode, !pairingCode.isEmpty {
141
+ values["pairingCode"] = pairingCode
142
+ }
143
+ if let securePairingCapable {
144
+ values["securePairingCapable"] = securePairingCapable
145
+ }
146
+ return values
147
+ }
148
+
149
+ init?(values: [String: Any]) {
150
+ guard let model = stringValue(values, "model") else { return nil }
151
+ guard let name = stringValue(values, "name") else { return nil }
152
+ let identifier = stringValue(values, "address").flatMap { $0.isEmpty ? nil : $0 }
153
+ let projectName = stringValue(values, "projectName").flatMap { $0.isEmpty ? nil : $0 }
154
+ let rssi = intValue(values["rssi"])
155
+ self.init(
156
+ model: DeviceModel.fromDeviceType(model),
157
+ name: name,
158
+ identifier: identifier,
159
+ projectName: projectName,
160
+ rssi: rssi,
161
+ id: stringValue(values, "id"),
162
+ pairingMode: boolValue(values, "pairingMode"),
163
+ pairingCode: stringValue(values, "pairingCode").flatMap { $0.isEmpty ? nil : $0 },
164
+ securePairingCapable: boolValue(values, "securePairingCapable")
165
+ )
166
+ }
167
+ }
168
+
169
+ public struct ConnectOptions {
170
+ public let saveAsDefault: Bool
171
+ public let cancelExistingConnectionAttempt: Bool
172
+
173
+ public init(saveAsDefault: Bool = true, cancelExistingConnectionAttempt: Bool = true) {
174
+ self.saveAsDefault = saveAsDefault
175
+ self.cancelExistingConnectionAttempt = cancelExistingConnectionAttempt
176
+ }
177
+ }
@@ -0,0 +1,283 @@
1
+ //
2
+ // AudioSessionMonitor.swift
3
+ // AOS
4
+ //
5
+ // Monitors iOS AVAudioSession for Bluetooth audio device connections
6
+ // Used to detect when Mentra Live glasses are paired/connected for audio
7
+ //
8
+
9
+ import AVFoundation
10
+ import Foundation
11
+ import UIKit
12
+
13
+ class AudioSessionMonitor {
14
+ /// Singleton instance
15
+ private static var instance: AudioSessionMonitor?
16
+
17
+ // Current monitoring state
18
+ static var isMonitoring = false
19
+ static var devicePattern: String?
20
+ static var callback: ((Bool, String?) -> Void)?
21
+
22
+ private init() {
23
+ Bridge.log("AudioMonitor: Initialized")
24
+ }
25
+
26
+ static func getInstance() -> AudioSessionMonitor {
27
+ if instance == nil {
28
+ instance = AudioSessionMonitor()
29
+ }
30
+ return instance!
31
+ }
32
+
33
+ /// Check if AVAudioSession is configured for Bluetooth
34
+ /// Returns true if session allows Bluetooth audio
35
+ /// NOTE: We don't configure the session - PhoneMic.swift handles that when recording
36
+ static func isAudioSessionConfigured() -> Bool {
37
+ let session = AVAudioSession.sharedInstance()
38
+
39
+ // Check if category supports Bluetooth
40
+ let category = session.category
41
+ let supportsBluetooth =
42
+ category == .playAndRecord || category == .record || category == .multiRoute
43
+
44
+ Bridge.log(
45
+ "AudioMonitor: Audio session category: \(category.rawValue), supports BT: \(supportsBluetooth)"
46
+ )
47
+ return supportsBluetooth
48
+ }
49
+
50
+ /// Check if a Bluetooth audio device matching the pattern is currently the active audio route
51
+ /// Returns true if device is actively routing audio
52
+ static func isAudioDeviceConnected(devicePattern: String) -> Bool {
53
+ let session = AVAudioSession.sharedInstance()
54
+ let outputs = session.currentRoute.outputs
55
+
56
+ Bridge.log("AudioMonitor: Checking active route, output count: \(outputs.count)")
57
+ for output in outputs {
58
+ Bridge.log("AudioMonitor: - \(output.portName) (type: \(output.portType.rawValue))")
59
+ if output.portType == .bluetoothHFP || output.portType == .bluetoothA2DP {
60
+ if output.portName.localizedCaseInsensitiveContains(devicePattern) {
61
+ Bridge.log("AudioMonitor: ✅ Found active audio device: \(output.portName)")
62
+ return true
63
+ }
64
+ }
65
+ }
66
+
67
+ Bridge.log("AudioMonitor: No active audio device matching '\(devicePattern)'")
68
+ return false
69
+ }
70
+
71
+ static func isOtherAudioDeviceConnected(devicePattern: String) -> Bool {
72
+ let connected = isAudioDeviceConnected(devicePattern: devicePattern)
73
+ if connected {
74
+ return false
75
+ }
76
+
77
+ // do we have multiple devices connected?
78
+ let session = AVAudioSession.sharedInstance()
79
+ let outputs = session.currentRoute.outputs
80
+
81
+ Bridge.log("AudioMonitor: Checking active route, output count: \(outputs.count)")
82
+ if outputs.count > 1 {
83
+ return true
84
+ }
85
+
86
+ return false
87
+ }
88
+
89
+ /// Check if a Bluetooth device matching the pattern is paired (appears in availableInputs)
90
+ /// Returns true if device is found (paired), WITHOUT activating it
91
+ /// This avoids switching A2DP music playback to HFP microphone mode
92
+ static func isDevicePaired(devicePattern: String) -> Bool {
93
+ let session = AVAudioSession.sharedInstance()
94
+
95
+ // Check if already active (using A2DP for music or HFP for calls)
96
+ if isAudioDeviceConnected(devicePattern: devicePattern) {
97
+ Bridge.log("AudioMonitor: Device '\(devicePattern)' already active")
98
+ return true
99
+ }
100
+
101
+ // Try to find in availableInputs (includes paired devices)
102
+ guard let availableInputs = session.availableInputs else {
103
+ Bridge.log("AudioMonitor: ❌ availableInputs is nil")
104
+ return false
105
+ }
106
+
107
+ Bridge.log("AudioMonitor: availableInputs count: \(availableInputs.count)")
108
+ for input in availableInputs {
109
+ Bridge.log("AudioMonitor: - \(input.portName) (type: \(input.portType.rawValue))")
110
+ }
111
+
112
+ let bluetoothInput = availableInputs.first { input in
113
+ input.portType == .bluetoothHFP
114
+ && input.portName.localizedCaseInsensitiveContains(devicePattern)
115
+ }
116
+
117
+ if let btInput = bluetoothInput {
118
+ Bridge.log(
119
+ "AudioMonitor: ✅ Found paired device '\(btInput.portName)' (not activating to preserve A2DP)"
120
+ )
121
+ return true
122
+ } else {
123
+ Bridge.log(
124
+ "AudioMonitor: ❌ Bluetooth HFP device '\(devicePattern)' not found in availableInputs"
125
+ )
126
+ return false
127
+ }
128
+ }
129
+
130
+ /// Start monitoring for audio route changes
131
+ /// Callback will be called when device matching pattern connects/disconnects
132
+ static func startMonitoring(devicePattern: String, callback: @escaping (Bool, String?) -> Void) {
133
+ guard !isMonitoring else {
134
+ Bridge.log("AudioMonitor: Already monitoring")
135
+ return
136
+ }
137
+
138
+ self.devicePattern = devicePattern
139
+ self.callback = callback
140
+
141
+ // Register for route change notifications
142
+ NotificationCenter.default.addObserver(
143
+ self,
144
+ selector: #selector(handleRouteChange),
145
+ name: AVAudioSession.routeChangeNotification,
146
+ object: nil
147
+ )
148
+
149
+ // Register for app foreground notifications
150
+ // This handles the case where user pairs in Settings and returns to app
151
+ NotificationCenter.default.addObserver(
152
+ self,
153
+ selector: #selector(handleAppBecameActive),
154
+ name: UIApplication.didBecomeActiveNotification,
155
+ object: nil
156
+ )
157
+
158
+ isMonitoring = true
159
+ Bridge.log("AudioMonitor: Started monitoring for '\(devicePattern)'")
160
+ }
161
+
162
+ /// Stop monitoring for audio route changes
163
+ static func stopMonitoring() {
164
+ guard isMonitoring else {
165
+ Bridge.log("AudioMonitor: Not currently monitoring")
166
+ return
167
+ }
168
+
169
+ NotificationCenter.default.removeObserver(
170
+ self,
171
+ name: AVAudioSession.routeChangeNotification,
172
+ object: nil
173
+ )
174
+
175
+ NotificationCenter.default.removeObserver(
176
+ self,
177
+ name: UIApplication.didBecomeActiveNotification,
178
+ object: nil
179
+ )
180
+
181
+ AudioSessionMonitor.isMonitoring = false
182
+ AudioSessionMonitor.devicePattern = nil
183
+ AudioSessionMonitor.callback = nil
184
+
185
+ Bridge.log("AudioMonitor: Stopped monitoring")
186
+ }
187
+
188
+ @objc private func handleRouteChange(notification: Notification) {
189
+ guard let userInfo = notification.userInfo,
190
+ let reasonValue = userInfo[AVAudioSessionRouteChangeReasonKey] as? UInt,
191
+ let reason = AVAudioSession.RouteChangeReason(rawValue: reasonValue),
192
+ let pattern = AudioSessionMonitor.devicePattern
193
+ else {
194
+ return
195
+ }
196
+
197
+ Bridge.log("AudioMonitor: Route change detected: \(reason.rawValue)")
198
+
199
+ switch reason {
200
+ case .newDeviceAvailable:
201
+ // When a new device becomes available, try to set it as preferred
202
+ // This handles the case where user pairs in Settings and returns to app
203
+ Bridge.log("AudioMonitor: New device available, attempting to activate '\(pattern)'")
204
+
205
+ // Add small delay to let iOS populate availableInputs
206
+ DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) {
207
+ if AudioSessionMonitor.isDevicePaired(devicePattern: pattern) {
208
+ let session = AVAudioSession.sharedInstance()
209
+ let deviceName = session.availableInputs?.first(where: {
210
+ $0.portName.localizedCaseInsensitiveContains(pattern)
211
+ })?.portName
212
+ Bridge.log(
213
+ "AudioMonitor: ✅ Successfully detected newly paired device '\(pattern)'"
214
+ )
215
+ AudioSessionMonitor.callback?(true, deviceName)
216
+ } else {
217
+ Bridge.log("AudioMonitor: New device available but not matching '\(pattern)'")
218
+ }
219
+ }
220
+
221
+ case .oldDeviceUnavailable:
222
+ // Check if our device disconnected
223
+ if !AudioSessionMonitor.isAudioDeviceConnected(devicePattern: pattern) {
224
+ Bridge.log("AudioMonitor: Device '\(pattern)' disconnected")
225
+ AudioSessionMonitor.callback?(false, nil)
226
+ }
227
+
228
+ default:
229
+ break
230
+ }
231
+ }
232
+
233
+ @objc private static func handleAppBecameActive() {
234
+ guard let pattern = AudioSessionMonitor.devicePattern else { return }
235
+
236
+ Bridge.log("AudioMonitor: App became active, checking for paired device '\(pattern)'")
237
+
238
+ // Don't reconfigure session - it's already configured from when monitoring started
239
+ // Just wait a bit for iOS to update availableInputs after returning from background
240
+ // iOS needs time to populate availableInputs after app foreground
241
+ // Use retry with progressive delays: 100ms, 400ms, 500ms = 1s total
242
+ AudioSessionMonitor.attemptActivateDevice(pattern: pattern, attempt: 0, maxAttempts: 3)
243
+ }
244
+
245
+ /// Try to detect if the audio device is paired with retry logic
246
+ /// Delays: [100ms, 400ms, 500ms] = 1 second total
247
+ static func attemptActivateDevice(pattern: String, attempt: Int, maxAttempts: Int) {
248
+ // Progressive delays in seconds (total: 1 second)
249
+ let delays: [TimeInterval] = [0.1, 0.4, 0.5]
250
+
251
+ if attempt >= maxAttempts {
252
+ Bridge.log(
253
+ "AudioMonitor: ❌ Failed to find paired device '\(pattern)' after \(maxAttempts) attempts"
254
+ )
255
+ return
256
+ }
257
+
258
+ let delay = attempt < delays.count ? delays[attempt] : 0.5
259
+
260
+ DispatchQueue.main.asyncAfter(deadline: .now() + delay) {
261
+ Bridge.log(
262
+ "AudioMonitor: Attempt \(attempt + 1)/\(maxAttempts) to detect '\(pattern)'..."
263
+ )
264
+
265
+ if AudioSessionMonitor.isDevicePaired(devicePattern: pattern) {
266
+ let session = AVAudioSession.sharedInstance()
267
+ // Try to get device name from availableInputs
268
+ let deviceName = session.availableInputs?.first(where: {
269
+ $0.portName.localizedCaseInsensitiveContains(pattern)
270
+ })?.portName
271
+ Bridge.log("AudioMonitor: ✅ Found paired device on attempt \(attempt + 1)")
272
+ AudioSessionMonitor.callback?(true, deviceName)
273
+ } else {
274
+ Bridge.log(
275
+ "AudioMonitor: Attempt \(attempt + 1) failed, retrying in \(delays[min(attempt + 1, delays.count - 1)])s..."
276
+ )
277
+ AudioSessionMonitor.attemptActivateDevice(
278
+ pattern: pattern, attempt: attempt + 1, maxAttempts: maxAttempts
279
+ )
280
+ }
281
+ }
282
+ }
283
+ }
@@ -0,0 +1,61 @@
1
+ import Compression
2
+ import Foundation
3
+
4
+ /// Byte-level codecs shared by glasses transports.
5
+ enum BinaryCodec {
6
+ /// CRC-16/CCITT-FALSE: polynomial 0x1021, initial value 0xFFFF.
7
+ static func crc16CCITT<S: Sequence>(_ bytes: S) -> UInt16 where S.Element == UInt8 {
8
+ var crc: UInt32 = 0xFFFF
9
+ for byte in bytes {
10
+ crc ^= UInt32(byte) << 8
11
+ for _ in 0 ..< 8 {
12
+ crc = (crc & 0x8000) != 0
13
+ ? ((crc << 1) ^ 0x1021) & 0xFFFF
14
+ : (crc << 1) & 0xFFFF
15
+ }
16
+ }
17
+ return UInt16(crc)
18
+ }
19
+
20
+ static func crc16CCITTLittleEndian<S: Sequence>(_ bytes: S) -> [UInt8]
21
+ where S.Element == UInt8
22
+ {
23
+ let crc = crc16CCITT(bytes)
24
+ return [UInt8(crc & 0xFF), UInt8((crc >> 8) & 0xFF)]
25
+ }
26
+
27
+ /// RFC1950 zlib stream. Apple's Compression framework emits raw DEFLATE,
28
+ /// so add the zlib header and Adler-32 trailer here in one shared implementation.
29
+ static func zlibRFC1950(_ data: Data) -> Data? {
30
+ guard !data.isEmpty else { return nil }
31
+ let capacity = data.count + data.count / 16 + 256
32
+ var deflated = Data(count: capacity)
33
+ let written = deflated.withUnsafeMutableBytes { destination -> Int in
34
+ data.withUnsafeBytes { source -> Int in
35
+ guard let destinationBase = destination.bindMemory(to: UInt8.self).baseAddress,
36
+ let sourceBase = source.bindMemory(to: UInt8.self).baseAddress
37
+ else { return 0 }
38
+ return compression_encode_buffer(
39
+ destinationBase, capacity, sourceBase, data.count, nil, COMPRESSION_ZLIB
40
+ )
41
+ }
42
+ }
43
+ guard written > 0 else { return nil }
44
+ deflated.removeSubrange(written ..< deflated.count)
45
+
46
+ var output = Data([0x78, 0x9C])
47
+ output.append(deflated)
48
+ var a: UInt32 = 1
49
+ var b: UInt32 = 0
50
+ for byte in data {
51
+ a = (a + UInt32(byte)) % 65521
52
+ b = (b + a) % 65521
53
+ }
54
+ let checksum = (b << 16) | a
55
+ output.append(contentsOf: [
56
+ UInt8((checksum >> 24) & 0xFF), UInt8((checksum >> 16) & 0xFF),
57
+ UInt8((checksum >> 8) & 0xFF), UInt8(checksum & 0xFF),
58
+ ])
59
+ return output
60
+ }
61
+ }