@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,1280 @@
1
+ package com.glassly.bluetoothsdk.sgcs
2
+
3
+ import android.content.Context
4
+ import android.content.res.Resources
5
+ import android.graphics.Bitmap
6
+ import android.graphics.BitmapFactory
7
+ import android.graphics.drawable.Drawable
8
+ import android.os.Handler
9
+ import android.os.Looper
10
+ import android.util.Log
11
+
12
+ import androidx.lifecycle.LiveData
13
+ import androidx.lifecycle.Observer
14
+
15
+ // Glassly
16
+ import com.glassly.bluetoothsdk.DeviceManager
17
+ import com.glassly.bluetoothsdk.Bridge
18
+ import com.glassly.bluetoothsdk.PhotoRequest
19
+ import com.glassly.bluetoothsdk.utils.DeviceTypes
20
+ import com.glassly.bluetoothsdk.utils.ConnTypes
21
+ import com.glassly.bluetoothsdk.utils.BitmapJavaUtils
22
+ import com.glassly.bluetoothsdk.utils.SmartGlassesConnectionState
23
+ import com.glassly.bluetoothsdk.utils.K900ProtocolUtils
24
+ import com.glassly.bluetoothsdk.utils.MessageChunker
25
+ import com.glassly.bluetoothsdk.utils.audio.Lc3Player
26
+ import com.glassly.bluetoothsdk.utils.BlePhotoUploadService
27
+ import com.glassly.bluetoothsdk.DeviceStore
28
+
29
+ // import com.augmentos.augmentos_core.R;
30
+ // import com.augmentos.augmentos_core.smarterglassesmanager.smartglassescommunicators.SmartGlassesCommunicator;
31
+ // import com.augmentos.augmentos_core.smarterglassesmanager.smartglassescommunicators.SmartGlassesFontSize;
32
+ // import com.augmentos.augmentos_core.smarterglassesmanager.utils.SmartGlassesConnectionState;
33
+ import com.squareup.picasso.Picasso
34
+ import com.squareup.picasso.Target
35
+ // import com.augmentos.augmentos_core.smarterglassesmanager.eventbusmessages.BatteryLevelEvent;
36
+ // import com.augmentos.augmentos_core.smarterglassesmanager.eventbusmessages.GlassesBluetoothSearchDiscoverEvent;
37
+ // import com.augmentos.augmentos_core.smarterglassesmanager.eventbusmessages.GlassesDisplayPowerEvent;
38
+ // import com.augmentos.augmentos_core.smarterglassesmanager.supportedglasses.SmartGlassesDevice;
39
+ import com.vuzix.ultralite.Anchor
40
+ import com.vuzix.ultralite.BatteryStatus
41
+ import com.vuzix.ultralite.EventListener
42
+ import com.vuzix.ultralite.Layout
43
+ import com.vuzix.ultralite.TextAlignment
44
+ import com.vuzix.ultralite.TextWrapMode
45
+ import com.vuzix.ultralite.UltraliteColor
46
+ import com.vuzix.ultralite.UltraliteSDK
47
+
48
+ import org.greenrobot.eventbus.EventBus
49
+
50
+ import java.util.ArrayList
51
+ import java.util.Arrays
52
+ import java.util.Collections
53
+
54
+
55
+ //communicate with ActiveLook smart glasses
56
+ class Mach1 : SGCManager() {
57
+
58
+ companion object {
59
+ private const val TAG = "WearableAi_UltraliteSGC"
60
+ const val cardLingerTime = 15
61
+
62
+ private const val TAP_DEBOUNCE_TIME = 80L // milliseconds
63
+
64
+ @JvmStatic
65
+ fun maybeReverseRTLString(text: String): String {
66
+ val result = StringBuilder()
67
+ val rtlBuffer = StringBuilder()
68
+
69
+ for (c in text.toCharArray()) {
70
+ if (isRTLCharacter(c)) {
71
+ rtlBuffer.append(c) // Append RTL characters to a buffer
72
+ } else {
73
+ if (rtlBuffer.length > 0) {
74
+ result.append(rtlBuffer.reverse()) // Reverse and append RTL text when a non-RTL character is found
75
+ rtlBuffer.setLength(0) // Clear the buffer
76
+ }
77
+ result.append(c) // Append non-RTL characters directly to the result
78
+ }
79
+ }
80
+
81
+ if (rtlBuffer.length > 0) {
82
+ result.append(rtlBuffer.reverse()) // Append any remaining RTL text in reverse
83
+ }
84
+
85
+ return result.toString()
86
+ }
87
+
88
+ private fun isRTLCharacter(c: Char): Boolean {
89
+ val block = Character.UnicodeBlock.of(c)
90
+ return block == Character.UnicodeBlock.ARABIC ||
91
+ block == Character.UnicodeBlock.HEBREW ||
92
+ block == Character.UnicodeBlock.SYRIAC ||
93
+ block == Character.UnicodeBlock.ARABIC_SUPPLEMENT ||
94
+ block == Character.UnicodeBlock.THAANA ||
95
+ block == Character.UnicodeBlock.NKO ||
96
+ block == Character.UnicodeBlock.SAMARITAN ||
97
+ block == Character.UnicodeBlock.MANDAIC ||
98
+ block == Character.UnicodeBlock.ARABIC_EXTENDED_A
99
+ // Add other RTL blocks as needed
100
+ }
101
+ }
102
+
103
+ var ultraliteSdk: UltraliteSDK? = null
104
+ var ultraliteCanvas: UltraliteSDK.Canvas? = null
105
+ var ultraliteListener: UltraliteListener? = null
106
+ var currentUltraliteLayout: Layout? = null
107
+ var screenToggleOff = false //should we keep the screen off?
108
+ var context: Context? = null
109
+
110
+ private var rowTextsLiveNow: ArrayList<Int>? = null
111
+
112
+ //ultralite pixel buffer on left side of screen
113
+ var ultraliteLeftSidePixelBuffer = 40
114
+
115
+ //handler to turn off screen
116
+ var goHomeHandler: Handler? = null
117
+ var goHomeRunnable: Runnable? = null
118
+
119
+ //handler to turn off screen/toggle
120
+ var screenOffHandler: Handler? = null
121
+ var screenOffRunnable: Runnable? = null
122
+
123
+ //handler to check battery life
124
+ var batteryHandler: Handler? = null
125
+ var batteryRunnable: Runnable? = null
126
+
127
+ //handler to disconnect
128
+ var killHandler: Handler? = null
129
+
130
+ var hasUltraliteControl = false
131
+ var screenIsClear = false
132
+ var isHeadUp = false // Dashboard state toggled by taps
133
+ // SmartGlassesDevice smartGlassesDevice;
134
+ private var lastTapTime = 0L
135
+ private var totalDashboardsIdk = 0
136
+
137
+ private fun hasBattery(): Boolean {
138
+ val level = DeviceStore.get("glasses", "batteryLevel")
139
+ return level is Number && level.toInt() != -1
140
+ }
141
+
142
+ private fun updateConnectionState(state: String) {
143
+ val isEqual = state == connectionState
144
+ if (isEqual) {
145
+ return
146
+ }
147
+
148
+ // Update the connection state
149
+ DeviceStore.apply("glasses", "connectionState", state)
150
+
151
+ if (state == ConnTypes.CONNECTED) {
152
+ // Match iOS: only declare fully booted once we have battery info too
153
+ if (hasBattery()) {
154
+ DeviceStore.apply("glasses", "connected", true)
155
+ DeviceStore.apply("glasses", "fullyBooted", true)
156
+ }
157
+ } else if (state == ConnTypes.DISCONNECTED) {
158
+ DeviceStore.apply("glasses", "fullyBooted", false)
159
+ DeviceStore.apply("glasses", "connected", false)
160
+ }
161
+ }
162
+
163
+ override fun setMicEnabled(enabled: Boolean) {
164
+ }
165
+
166
+ override fun sortMicRanking(list: MutableList<String>): MutableList<String> {
167
+ return list
168
+ }
169
+
170
+ override fun requestPhoto(request: PhotoRequest) {
171
+
172
+ }
173
+
174
+ override fun startStream(message: MutableMap<String, Any>) {
175
+
176
+ }
177
+
178
+ override fun stopStream() {
179
+
180
+ }
181
+
182
+ override fun sendStreamKeepAlive(message: MutableMap<String, Any>) {
183
+
184
+ }
185
+
186
+ override fun startVideoRecording(requestId: String, save: Boolean, sound: Boolean) {
187
+
188
+ }
189
+
190
+ override fun stopVideoRecording(requestId: String) {
191
+
192
+ }
193
+
194
+ override fun sendButtonPhotoSettings() {
195
+
196
+ }
197
+
198
+ override fun sendButtonVideoRecordingSettings() {
199
+
200
+ }
201
+
202
+ override fun sendButtonMaxRecordingTime() {
203
+
204
+ }
205
+
206
+ override fun sendCameraFovSetting() {
207
+ }
208
+
209
+ override fun setBrightness(level: Int, autoMode: Boolean) {
210
+ Bridge.log("Mach1: setBrightness() - level: " + level + "%, autoMode: " + autoMode)
211
+ updateGlassesBrightness(level)
212
+ updateGlassesAutoBrightness(autoMode)
213
+ }
214
+
215
+ override fun clearDisplay() {
216
+ Bridge.log("Mach1: clearDisplay()")
217
+ blankScreen()
218
+ }
219
+
220
+ override fun sendText(text: String) {
221
+ Bridge.log("Mach1: sendText() - text: " + text)
222
+ displayTextWall(text)
223
+ }
224
+
225
+ override fun sendTextWall(text: String) {
226
+ Bridge.log("Mach1: sendTextWall()")
227
+ displayTextWall(text)
228
+ }
229
+
230
+ override fun sendDoubleTextWall(top: String, bottom: String) {
231
+ Bridge.log("Mach1: sendDoubleTextWall()")
232
+ displayDoubleTextWall(top, bottom)
233
+ }
234
+
235
+ override fun displayBitmap(base64ImageData: String, x: Int?, y: Int?, width: Int?, height: Int?): Boolean {
236
+ try {
237
+ Bridge.log("Mach1: displayBitmap() - decoding base64")
238
+ // Decode base64 to byte array
239
+ val bmpData = android.util.Base64.decode(base64ImageData, android.util.Base64.DEFAULT)
240
+
241
+ if (bmpData == null || bmpData.isEmpty()) {
242
+ Log.e(TAG, "Failed to decode base64 image data")
243
+ return false
244
+ }
245
+
246
+ // Convert byte array to Bitmap
247
+ val bitmap = BitmapFactory.decodeByteArray(bmpData, 0, bmpData.size)
248
+
249
+ if (bitmap == null) {
250
+ Log.e(TAG, "Failed to decode bitmap from byte array")
251
+ return false
252
+ }
253
+
254
+ // Call internal implementation
255
+ displayBitmap(bitmap)
256
+ return true
257
+ } catch (e: Exception) {
258
+ Log.e(TAG, "Error displaying bitmap from base64", e)
259
+ return false
260
+ }
261
+ }
262
+
263
+ override fun showDashboard() {
264
+
265
+ }
266
+
267
+ override fun ping() {
268
+ }
269
+
270
+ override fun dbg1() {}
271
+
272
+ override fun dbg2() {}
273
+
274
+ override fun setDashboardPosition(height: Int, depth: Int) {
275
+
276
+ }
277
+
278
+ override fun setHeadUpAngle(angle: Int) {
279
+
280
+ }
281
+
282
+ override fun getBatteryStatus() {
283
+
284
+ }
285
+
286
+ override fun setSilentMode(enabled: Boolean) {
287
+
288
+ }
289
+
290
+ override fun exit() {
291
+
292
+ }
293
+
294
+ override fun sendShutdown() {
295
+ Bridge.log("sendShutdown - not supported on Mach1")
296
+ }
297
+
298
+ override fun sendReboot() {
299
+ Bridge.log("sendReboot - not supported on Mach1")
300
+ }
301
+
302
+ override fun sendRgbLedControl(requestId: String, packageName: String?, action: String, color: String?, onDurationMs: Int, offDurationMs: Int, count: Int) {
303
+ Bridge.log("sendRgbLedControl - not supported on Mach1")
304
+ Bridge.sendRgbLedControlResponse(requestId, false, "device_not_supported")
305
+ }
306
+
307
+ override fun disconnect() {
308
+ Bridge.log("Mach1: disconnect()")
309
+ if (ultraliteSdk != null) {
310
+ ultraliteSdk!!.releaseControl()
311
+ updateConnectionState(ConnTypes.DISCONNECTED)
312
+ }
313
+ }
314
+
315
+ override fun forget() {
316
+ Bridge.log("Mach1: forget()")
317
+ // Release control and clean up
318
+ destroy()
319
+ }
320
+
321
+ override fun findCompatibleDevices() {
322
+ Bridge.log("Mach1: findCompatibleDevices()")
323
+ findCompatibleDeviceNames()
324
+ }
325
+
326
+ override fun stopScan() {
327
+ Bridge.log("Mach1: stopScan() - no active BLE scanner owned by Mach1")
328
+ }
329
+
330
+ override fun connectById(id: String) {
331
+ Bridge.log("Mach1: connectById() - id: " + id)
332
+ // The Mach1 uses UltraliteSDK which handles connection internally
333
+ // We just need to trigger the connection process
334
+ connectToSmartGlasses()
335
+ }
336
+
337
+ override fun getConnectedBluetoothName(): String {
338
+ // Mach1/Ultralite SDK doesn't expose the peripheral name directly
339
+ // Return device type if connected
340
+ if (ultraliteSdk != null) {
341
+ val connected = ultraliteSdk!!.getConnected()
342
+ if (connected != null && java.lang.Boolean.TRUE == connected.value) {
343
+ return "Vuzix Ultralite"
344
+ }
345
+ }
346
+ return ""
347
+ }
348
+
349
+ override fun cleanup() {
350
+ destroy()
351
+ }
352
+
353
+ override fun requestWifiScan(scanId: String?) {
354
+
355
+ }
356
+
357
+ override fun sendWifiCredentials(ssid: String, password: String) {
358
+
359
+ }
360
+
361
+ override fun forgetWifiNetwork(ssid: String) {
362
+ // Mach1 doesn't support WiFi
363
+ }
364
+
365
+ override fun sendHotspotState(enabled: Boolean) {
366
+ // Mach1 doesn't support hotspot
367
+ }
368
+
369
+ override fun sendUserEmailToGlasses(email: String) {
370
+ // Mach1 doesn't support user email (no ASG client)
371
+ }
372
+
373
+ override fun sendIncidentId(incidentId: String, apiBaseUrl: String?) {
374
+ // Mach1 doesn't support incident reporting (no ASG client)
375
+ }
376
+
377
+ override fun queryGalleryStatus() {
378
+
379
+ }
380
+
381
+ override fun sendGalleryMode() {
382
+ // Mach1 doesn't have a built-in camera/gallery system
383
+ Bridge.log("Mach1: sendGalleryModeActive - not supported on Mach1")
384
+ }
385
+
386
+ override fun requestVersionInfo() {
387
+ // Mach1 doesn't support version info requests
388
+ Bridge.log("Mach1: requestVersionInfo - not supported on Mach1")
389
+ }
390
+
391
+ inner class UltraliteListener : EventListener {
392
+ override fun onTap(tapCount: Int) {
393
+ val currentTime = System.currentTimeMillis()
394
+ if (currentTime - lastTapTime < TAP_DEBOUNCE_TIME) {
395
+ Log.d(TAG, "Ignoring duplicate tap event")
396
+ return
397
+ }
398
+ totalDashboardsIdk++
399
+ Log.d(TAG, "TOTAL NUMBER OF DASHBOARD TOGGLEZ: " + totalDashboardsIdk)
400
+
401
+ lastTapTime = currentTime
402
+ Log.d(TAG, "Ultralite go tap n times: " + tapCount)
403
+
404
+ // Toggle dashboard on 2+ taps (same as iOS implementation)
405
+ if (tapCount >= 2) {
406
+ isHeadUp = !isHeadUp
407
+ // Notify DeviceManager of head up state change (same as G1 does with IMU)
408
+ DeviceStore.apply("glasses", "headUp", isHeadUp)
409
+ Log.d(TAG, "Mach1: Dashboard toggled via tap, isHeadUp: " + isHeadUp)
410
+
411
+ // Auto turn off the dashboard after 15 seconds
412
+ if (isHeadUp) {
413
+ goHomeHandler!!.postDelayed({
414
+ if (isHeadUp) {
415
+ isHeadUp = false
416
+ DeviceStore.apply("glasses", "headUp", false)
417
+ Log.d(TAG, "Mach1: Auto-disabling dashboard after 15 seconds")
418
+ }
419
+ }, 15000L)
420
+ }
421
+ }
422
+ }
423
+
424
+ override fun onDisplayTimeout() {
425
+ Log.d(TAG, "Ultralite display timeout.")
426
+ }
427
+
428
+ override fun onPowerButtonPress(turningOn: Boolean) {
429
+ //since we implement our own state for the power turn on/off, we ignore what the ultralite thinks ('turningOn') and use our own state
430
+ Log.d(TAG, "Ultralites power button pressed: " + turningOn)
431
+
432
+ //flip value of screen toggle
433
+ screenToggleOff = !screenToggleOff
434
+
435
+ if (!screenToggleOff) {
436
+ Log.d(TAG, "screen toggle off NOT on, showing turn ON message")
437
+ // EventBus.getDefault().post(new GlassesDisplayPowerEvent(screenToggleOff));
438
+ } else {
439
+ Log.d(TAG, "screen toggle off IS on")
440
+ }
441
+ }
442
+ }
443
+
444
+ private var ultraliteConnectedLive: LiveData<Boolean>? = null
445
+ private var ultraliteControlled: LiveData<Boolean>? = null
446
+ private var batteryStatusObserver: LiveData<BatteryStatus>? = null
447
+
448
+ // Observer references for cleanup
449
+ private var connectedObserver: Observer<Boolean>? = null
450
+ private var controlledObserver: Observer<Boolean>? = null
451
+ private var batteryObserver: Observer<BatteryStatus?>? = null
452
+
453
+ init {
454
+ this.type = DeviceTypes.MACH1
455
+ Log.d(TAG, "Mach1 constructor started")
456
+
457
+ try {
458
+ // Get context from Bridge (like G1 does)
459
+ this.context = Bridge.getContext()
460
+ Log.d(TAG, "Mach1: Got context from Bridge")
461
+
462
+ hasUltraliteControl = false
463
+ screenIsClear = true
464
+ goHomeHandler = Handler(Looper.getMainLooper())
465
+ screenOffHandler = Handler(Looper.getMainLooper())
466
+ killHandler = Handler(Looper.getMainLooper())
467
+ Log.d(TAG, "Mach1: Handlers created")
468
+
469
+ rowTextsLiveNow = ArrayList<Int>()
470
+
471
+ // Initialize UltraliteSDK with valid context
472
+ Log.d(TAG, "Mach1: About to initialize UltraliteSDK")
473
+ ultraliteSdk = UltraliteSDK.get(context)
474
+ Log.d(TAG, "Mach1: UltraliteSDK initialized")
475
+
476
+ ultraliteListener = UltraliteListener()
477
+ ultraliteSdk!!.addEventListener(ultraliteListener)
478
+ Log.d(TAG, "Mach1: Event listener added")
479
+
480
+ // Set up LiveData observers using observeForever (no LifecycleOwner needed)
481
+ ultraliteConnectedLive = ultraliteSdk!!.getConnected()
482
+ ultraliteControlled = ultraliteSdk!!.getControlledByMe()
483
+ batteryStatusObserver = ultraliteSdk!!.getBatteryStatus()
484
+ Log.d(TAG, "Mach1: LiveData references obtained")
485
+
486
+ // Create observers
487
+ connectedObserver = Observer { isConnected ->
488
+ onUltraliteConnectedChange(isConnected)
489
+ }
490
+
491
+ controlledObserver = Observer { isControlled ->
492
+ onUltraliteControlChanged(isControlled)
493
+ }
494
+
495
+ batteryObserver = Observer { batteryStatus ->
496
+ onUltraliteBatteryChanged(batteryStatus)
497
+ }
498
+
499
+ // Register observers on main thread (observeForever requires main thread)
500
+ Handler(Looper.getMainLooper()).post {
501
+ try {
502
+ ultraliteConnectedLive!!.observeForever(connectedObserver!!)
503
+ Log.d(TAG, "Mach1: Connected observer registered")
504
+
505
+ ultraliteControlled!!.observeForever(controlledObserver!!)
506
+ Log.d(TAG, "Mach1: Controlled observer registered")
507
+
508
+ batteryStatusObserver!!.observeForever(batteryObserver!!)
509
+ Log.d(TAG, "Mach1: Battery observer registered")
510
+
511
+ Log.d(TAG, "Mach1: All observers registered on main thread")
512
+ } catch (e: Exception) {
513
+ Log.e(TAG, "Mach1: Failed to register observers: " + e.message, e)
514
+ }
515
+ }
516
+
517
+ Log.d(TAG, "Mach1 initialized with context and observers")
518
+ } catch (e: Exception) {
519
+ Log.e(TAG, "Mach1 constructor FAILED with exception: " + e.message, e)
520
+ Bridge.log("Mach1 constructor FAILED: " + e.message)
521
+ }
522
+ }
523
+
524
+ fun updateGlassesBrightness(brightness: Int) {
525
+ // TODO: Implement this method
526
+ }
527
+
528
+ fun updateGlassesAutoBrightness(autoBrightness: Boolean) {
529
+ // TODO: Implement this method
530
+ }
531
+
532
+ private fun onUltraliteConnectedChange(isConnected: Boolean) {
533
+ Log.d(TAG, "Ultralite CONNECT changed to: " + isConnected)
534
+ if (isConnected) {
535
+ Log.d(TAG, "Ultralite requesting control...")
536
+ val isControlled = ultraliteSdk!!.requestControl()
537
+ if (isControlled) {
538
+ // setupUltraliteCanvas();
539
+ // changeUltraliteLayout(Layout.CANVAS);
540
+ showHomeScreen()
541
+ } else {
542
+ return
543
+ }
544
+ Log.d(TAG, "Ultralite RESULT control request: " + isControlled)
545
+ updateConnectionState(ConnTypes.CONNECTED)
546
+ // connectionEvent(SmartGlassesConnectionState.CONNECTED);
547
+ } else {
548
+ Log.d(TAG, "Ultralite not connected.")
549
+ updateConnectionState(ConnTypes.DISCONNECTED)
550
+ // connectionEvent(SmartGlassesConnectionState.DISCONNECTED);
551
+ }
552
+ }
553
+
554
+ private fun onUltraliteControlChanged(isControlledByMe: Boolean) {
555
+ Log.d(TAG, "Ultralite CONTROL changed to: " + isControlledByMe)
556
+ if (isControlledByMe) {
557
+ hasUltraliteControl = true
558
+ // connectionEvent(SmartGlassesConnectionState.CONNECTED);
559
+ updateConnectionState(ConnTypes.CONNECTED)
560
+ } else {
561
+ hasUltraliteControl = false
562
+ }
563
+ }
564
+
565
+ private fun onUltraliteBatteryChanged(batteryStatus: BatteryStatus?) {
566
+ // Guard against null batteryStatus which can occur during connection/disconnection
567
+ // See: GLASSLY-OS-154
568
+ if (batteryStatus == null) {
569
+ Log.d(TAG, "Ultralite battery status is null, ignoring")
570
+ return
571
+ }
572
+ Log.d(TAG, "Ultralite new battery status: " + batteryStatus.level)
573
+ DeviceStore.apply("glasses", "batteryLevel", batteryStatus.level)
574
+
575
+ // Match iOS: if we're already connected but weren't fully booted yet (waiting
576
+ // for battery), now that we have battery info we can declare fully booted.
577
+ if (connectionState == ConnTypes.CONNECTED && !fullyBooted) {
578
+ DeviceStore.apply("glasses", "connected", true)
579
+ DeviceStore.apply("glasses", "fullyBooted", true)
580
+ }
581
+ }
582
+
583
+
584
+ protected fun setFontSizes() {
585
+ }
586
+
587
+ fun findCompatibleDeviceNames() {
588
+ // EventBus.getDefault().post(new GlassesBluetoothSearchDiscoverEvent(smartGlassesDevice.deviceModelName, "NOTREQUIREDSKIP"));
589
+ Bridge.sendDiscoveredDevice(this.type, "NOTREQUIREDSKIP") // Use this.type to support both Mach1 and Z100
590
+ //this.destroy();
591
+ }
592
+
593
+ fun connectToSmartGlasses() {
594
+ Log.d(TAG, "connectToSmartGlasses running...")
595
+ // int mCount = 10;
596
+ // while ((mConnectState != 2) && (!hasUltraliteControl) && (mCount > 0)){
597
+ // mCount--;
598
+ // try {
599
+ // Log.d(TAG, "Don't have Ultralite yet, let's wait for it...");
600
+ // Thread.sleep(200);
601
+ // } catch (InterruptedException e) {
602
+ // e.printStackTrace();
603
+ // }
604
+ // }
605
+ // Log.d(TAG, "Connected to Ultralites.");
606
+ // Log.d(TAG, "mCOnnectestate: " + mConnectState);
607
+ // Log.d(TAG, "mCOunt: " + mCount);
608
+ // displayReferenceCardSimple("Connected to AugmentOS", "");
609
+ // connectionEvent(mConnectState);
610
+ Log.d(TAG, "connectToSmartGlasses finished")
611
+ }
612
+
613
+ fun displayTextLine(text: String) {
614
+ displayReferenceCardSimple("", text)
615
+ }
616
+
617
+ /**
618
+ * Display pre-wrapped text on the glasses.
619
+ *
620
+ * Text wrapping and processing is handled by DisplayProcessor in React Native.
621
+ * This method is a "dumb pipe" - it just sends the text to the Vuzix SDK.
622
+ */
623
+ fun displayTextWall(text: String) {
624
+ if (screenToggleOff) {
625
+ return
626
+ }
627
+
628
+ goHomeHandler!!.removeCallbacksAndMessages(null)
629
+ goHomeHandler!!.removeCallbacksAndMessages(goHomeRunnable)
630
+
631
+ // Text is already wrapped by DisplayProcessor - just send it
632
+ changeUltraliteLayout(Layout.TEXT_BOTTOM_LEFT_ALIGN)
633
+ ultraliteSdk!!.sendText(text)
634
+
635
+ if (ultraliteCanvas != null) {
636
+ ultraliteCanvas!!.commit()
637
+ }
638
+ screenIsClear = false
639
+ }
640
+
641
+ /**
642
+ * Display pre-composed double text wall (two columns) on the glasses.
643
+ *
644
+ * NOTE: DisplayProcessor now composes double_text_wall into a single text_wall
645
+ * with pixel-precise column alignment using ColumnComposer. This method may
646
+ * not be called anymore, but is kept for backwards compatibility.
647
+ *
648
+ * Column composition is handled by DisplayProcessor in React Native.
649
+ * This method is a "dumb pipe" - it just sends the text to the Vuzix SDK.
650
+ */
651
+ fun displayDoubleTextWall(textTop: String, textBottom: String) {
652
+ if (screenToggleOff) {
653
+ return
654
+ }
655
+
656
+ goHomeHandler!!.removeCallbacksAndMessages(null)
657
+ goHomeHandler!!.removeCallbacksAndMessages(goHomeRunnable)
658
+
659
+ // Text is already composed by DisplayProcessor's ColumnComposer
660
+ // Just combine and send - no custom logic needed
661
+ val combinedText = textTop + "\n\n\n" + textBottom
662
+
663
+ changeUltraliteLayout(Layout.TEXT_BOTTOM_LEFT_ALIGN)
664
+ ultraliteSdk!!.sendText(combinedText)
665
+
666
+ if (ultraliteCanvas != null) {
667
+ ultraliteCanvas!!.commit()
668
+ }
669
+ screenIsClear = false
670
+ }
671
+
672
+ fun displayCustomContent(json: String) {
673
+ displayReferenceCardSimple("CustomDisplayNotImplemented", json)
674
+ }
675
+
676
+
677
+ fun showNaturalLanguageCommandScreen(prompt: String, naturalLanguageInput: String) {
678
+ // int boxDelta = 3;
679
+ //
680
+ // if (connectedGlasses != null) {
681
+ // connectedGlasses.clear();
682
+ // showPromptCircle();
683
+ //
684
+ // //show the prompt
685
+ // lastLocNaturalLanguageArgsTextView = displayText(new TextLineSG(prompt, SMALL_FONT), new Point(0, 11), true);
686
+ // lastLocNaturalLanguageArgsTextView = new Point(lastLocNaturalLanguageArgsTextView.x, lastLocNaturalLanguageArgsTextView.y + boxDelta); //margin down a tad
687
+ //
688
+ // //show the final "finish command" prompt
689
+ // int finishY = 90;
690
+ // displayLine(new Point(0, finishY), new Point(100, finishY));
691
+ // displayText(new TextLineSG(finishNaturalLanguageString, SMALL_FONT), new Point(0, finishY + 2), true);
692
+ //
693
+ // //show the natural language args in a scroll box
694
+ //// ArrayList<TextLineSG> nli = new ArrayList<>();
695
+ //// nli.add(new TextLineSG(naturalLanguageInput, SMALL_FONT));
696
+ //// lastLocNaturalLanguageArgsTextView = scrollTextShow(nli, startScrollBoxY.y + boxDelta, finishY - boxDelta);
697
+ // }
698
+ }
699
+
700
+ fun updateNaturalLanguageCommandScreen(naturalLanguageArgs: String) {
701
+ // Log.d(TAG, "Displaynig: " + naturalLanguageArgs);
702
+ // displayText(new TextLineSG(naturalLanguageArgs, SMALL_FONT), new Point(0, lastLocNaturalLanguageArgsTextView.y));
703
+ }
704
+
705
+ fun blankScreen() {
706
+ // if (connectedGlasses != null){
707
+ // connectedGlasses.clear();
708
+ // }
709
+ }
710
+
711
+ fun destroy() {
712
+ try {
713
+ // Remove LiveData observers (using observeForever, so use removeObserver)
714
+ if (ultraliteConnectedLive != null && connectedObserver != null) {
715
+ ultraliteConnectedLive!!.removeObserver(connectedObserver!!)
716
+ }
717
+ if (ultraliteControlled != null && controlledObserver != null) {
718
+ ultraliteControlled!!.removeObserver(controlledObserver!!)
719
+ }
720
+ if (batteryStatusObserver != null && batteryObserver != null) {
721
+ batteryStatusObserver!!.removeObserver(batteryObserver!!)
722
+ }
723
+
724
+ if (ultraliteSdk != null) {
725
+ // Remove event listeners and release control
726
+ ultraliteSdk!!.removeEventListener(ultraliteListener)
727
+ ultraliteSdk!!.releaseControl()
728
+ ultraliteSdk = null // Nullify reference
729
+ }
730
+
731
+ // Cancel all pending handlers and callbacks
732
+ if (goHomeHandler != null) {
733
+ goHomeHandler!!.removeCallbacksAndMessages(null)
734
+ }
735
+ if (screenOffHandler != null) {
736
+ screenOffHandler!!.removeCallbacksAndMessages(null)
737
+ }
738
+ if (killHandler != null) {
739
+ killHandler!!.removeCallbacksAndMessages(null)
740
+ }
741
+
742
+ // Clear canvas and other resources
743
+ if (ultraliteCanvas != null) {
744
+ ultraliteCanvas!!.clear()
745
+ ultraliteCanvas!!.commit()
746
+ ultraliteCanvas = null
747
+ }
748
+
749
+ // Reset state variables
750
+ rowTextsLiveNow!!.clear()
751
+ screenToggleOff = false
752
+ screenIsClear = true
753
+ lastTapTime = 0
754
+ totalDashboardsIdk = 0
755
+ currentUltraliteLayout = null
756
+
757
+ // Free up references
758
+ this.context = null
759
+ connectedObserver = null
760
+ controlledObserver = null
761
+ batteryObserver = null
762
+
763
+ Log.d(TAG, "UltraliteSGC destroyed successfully.")
764
+ } catch (e: Exception) {
765
+ Log.e(TAG, "Error during destroy: ", e)
766
+ }
767
+ }
768
+
769
+
770
+ fun showHomeScreen() {
771
+ Log.d(TAG, "SHOW HOME SCREEN")
772
+ ultraliteSdk!!.screenOff()
773
+ screenIsClear = true
774
+ }
775
+
776
+ fun setupUltraliteCanvas() {
777
+ Log.d(TAG, "Setting up ultralite canvas")
778
+ if (ultraliteSdk != null) {
779
+ ultraliteCanvas = ultraliteSdk!!.getCanvas()
780
+ }
781
+ }
782
+
783
+ fun changeUltraliteLayout(chosenLayout: Layout) {
784
+ //don't update layout if it's already setup
785
+ if (currentUltraliteLayout != null && currentUltraliteLayout == chosenLayout) {
786
+ return
787
+ }
788
+
789
+ ultraliteSdk!!.screenOn()
790
+
791
+ currentUltraliteLayout = chosenLayout
792
+ ultraliteSdk!!.setLayout(chosenLayout, 0, true, false, 2)
793
+
794
+ if (chosenLayout == Layout.CANVAS) {
795
+ if (ultraliteCanvas == null) {
796
+ setupUltraliteCanvas()
797
+ }
798
+ }
799
+ }
800
+
801
+ // public void startScrollingTextViewMode(String title){
802
+ // super.startScrollingTextViewMode(title);
803
+
804
+ // if (ultraliteSdk == null) {
805
+ // return;
806
+ // }
807
+
808
+ // //clear the screen
809
+ // ultraliteCanvas.clear();
810
+ // drawTextOnUltralite(title);
811
+ // }
812
+
813
+
814
+ /**
815
+ * Draw text on Ultralite canvas.
816
+ * Text is expected to be pre-wrapped by DisplayProcessor.
817
+ */
818
+ fun drawTextOnUltralite(text: String) {
819
+ val ultraliteColor = UltraliteColor.WHITE
820
+ val ultraliteAnchor = Anchor.TOP_LEFT
821
+ val ultraliteAlignment = TextAlignment.LEFT
822
+ changeUltraliteLayout(Layout.CANVAS)
823
+ ultraliteCanvas!!.clear()
824
+ ultraliteCanvas!!.clearBackground(UltraliteColor.DIM)
825
+ ultraliteCanvas!!.createText(text, ultraliteAlignment, ultraliteColor, ultraliteAnchor, true)
826
+ ultraliteCanvas!!.commit()
827
+ screenIsClear = false
828
+ }
829
+
830
+ // public Bitmap getBitmapFromDrawable(Resources res) {
831
+ // return BitmapFactory.decodeResource(res, R.drawable.vuzix_shield);
832
+ // }
833
+
834
+ // public void displayReferenceCardSimple(String title, String body, int lingerTime){
835
+ // if (!isConnected()) {
836
+ // Log.d(TAG, "Not showing reference card because not connected to Ultralites...");
837
+ // return;
838
+ // }
839
+ //
840
+ //// String [] bulletPoints = {"first one", "second one", "dogs and cats"};
841
+ //// displayBulletList("Cool Bullets:", bulletPoints, 15);
842
+ //
843
+ // Log.d(TAG, "Sending text to Ultralite SDK: \n" + body);
844
+ //// ultraliteSdk.sendText("hello world"); //this is BROKEN in Vuzix ultralite 0.4.2 SDK - crashes Vuzix OEM Platform android app
845
+ //
846
+ // //edit the text to add new lines to it because ultralite wrapping doesn't work
847
+ //// String titleWrapped = addNewlineEveryNWords(title, 6);
848
+ //// String bodyWrapped = addNewlineEveryNWords(body, 6);
849
+ //
850
+ // //display the title at the top of the screen
851
+ // UltraliteColor ultraliteColor = UltraliteColor.WHITE;
852
+ // Anchor ultraliteAnchor = Anchor.TOP_LEFT;
853
+ // TextAlignment ultraliteAlignment = TextAlignment.LEFT;
854
+ // changeUltraliteLayout(Layout.CANVAS);
855
+ // ultraliteCanvas.clear();
856
+ // ultraliteCanvas.createText(title, TextAlignment.AUTO, UltraliteColor.WHITE, Anchor.TOP_LEFT, ultraliteLeftSidePixelBuffer, 120, 640 - ultraliteLeftSidePixelBuffer, -1, TextWrapMode.WRAP, true);
857
+ // ultraliteCanvas.createText(body, TextAlignment.AUTO, UltraliteColor.WHITE, Anchor.MIDDLE_LEFT, ultraliteLeftSidePixelBuffer, 0, 640 - ultraliteLeftSidePixelBuffer, -1, TextWrapMode.WRAP, true);
858
+ // ultraliteCanvas.commit();
859
+ // screenIsClear = false;
860
+ //
861
+ // homeScreenInNSeconds(lingerTime);
862
+ // }
863
+
864
+ // public void setFontSize(SmartGlassesFontSize fontSize){
865
+ // int textSize;
866
+ // switch (fontSize){
867
+ // case SMALL:
868
+ // textSize = 24;
869
+ // maxLines = 14;
870
+ // maxCharsPerLine = 42;
871
+ // break;
872
+ // case MEDIUM:
873
+ // textSize = 29;
874
+ // maxLines = 12; // Adjusted from 11.5 for practical use
875
+ // maxCharsPerLine = 38; // Assuming max 27 characters fit per line on your display
876
+ // break;
877
+ // case LARGE:
878
+ // textSize = 40;
879
+ // maxLines = 7;
880
+ // maxCharsPerLine = 28;
881
+ // break;
882
+ // default:
883
+ // throw new IllegalArgumentException("Unknown font size: " + fontSize);
884
+ // }
885
+ // ultraliteSdk.setFont(null, 0, textSize);
886
+ // }
887
+
888
+ fun displayReferenceCardSimple(titleStr: String, bodyStr: String) {
889
+ if (screenToggleOff) {
890
+ return
891
+ }
892
+
893
+ val title = maybeReverseRTLString(titleStr)
894
+ val body = maybeReverseRTLString(bodyStr)
895
+ if (connectionState != ConnTypes.CONNECTED) {
896
+ Log.d(TAG, "Not showing reference card because not connected to Ultralites...")
897
+ return
898
+ }
899
+
900
+ changeUltraliteLayout(Layout.CANVAS)
901
+ ultraliteCanvas!!.clear()
902
+
903
+ // String [] bulletPoints = {"first one", "second one", "dogs and cats"};
904
+ // displayBulletList("Cool Bullets:", bulletPoints, 15);
905
+
906
+ Log.d(TAG, "Sending text to Ultralite SDK: \n" + body)
907
+ // ultraliteSdk.sendText("hello world"); //this is BROKEN in Vuzix ultralite 0.4.2 SDK - crashes Vuzix OEM Platform android app
908
+
909
+ //edit the text to add new lines to it because ultralite wrapping doesn't work
910
+ // String titleWrapped = addNewlineEveryNWords(title, 6);
911
+ // String bodyWrapped = addNewlineEveryNWords(body, 6);
912
+
913
+ //display title top of scren adn text middle of screen
914
+ // UltraliteColor ultraliteColor = UltraliteColor.WHITE;
915
+ // Anchor ultraliteAnchor = Anchor.TOP_LEFT;
916
+ // TextAlignment ultraliteAlignment = TextAlignment.LEFT;
917
+ // ultraliteCanvas.createText(title, TextAlignment.AUTO, UltraliteColor.WHITE, Anchor.TOP_LEFT, ultraliteLeftSidePixelBuffer, 120, 640 - ultraliteLeftSidePixelBuffer, -1, TextWrapMode.WRAP, true);
918
+ // ultraliteCanvas.createText(body, TextAlignment.AUTO, UltraliteColor.WHITE, Anchor.MIDDLE_LEFT, ultraliteLeftSidePixelBuffer, 0, 640 - ultraliteLeftSidePixelBuffer, -1, TextWrapMode.WRAP, true);
919
+
920
+ //concat body and title, put text on top right of screen (to not block main view)
921
+ val ultraliteColor = UltraliteColor.WHITE
922
+ val ultraliteAnchor = Anchor.TOP_CENTER
923
+ val ultraliteAlignment = TextAlignment.LEFT
924
+ //ultraliteCanvas.createText(body, TextAlignment.AUTO, UltraliteColor.WHITE, Anchor.TOP_RIGHT, 0, 0, (640 / 2) - ultraliteLeftSidePixelBuffer, -1, TextWrapMode.WRAP, true);
925
+ if (!title.isEmpty() && title != "") {
926
+ ultraliteCanvas!!.createText(title + ": " + body, TextAlignment.AUTO, UltraliteColor.WHITE, Anchor.TOP_RIGHT, 0, 0, 640 / 2, -1, TextWrapMode.WRAP, true)
927
+ } else {
928
+ ultraliteCanvas!!.createText(body, TextAlignment.AUTO, UltraliteColor.WHITE, Anchor.TOP_RIGHT, 0, 0, 640 / 2, -1, TextWrapMode.WRAP, true)
929
+ }
930
+
931
+ //NOTE:
932
+ // int createText(@NonNull
933
+ // String text,
934
+ // @NonNull
935
+ // TextAlignment alignment,
936
+ // @NonNull
937
+ // UltraliteColor color,
938
+ // @NonNull
939
+ // Anchor anchor,
940
+ // int offsetX,
941
+ // int offsetY,
942
+ // int width,
943
+ // int height,
944
+ // @Nullable
945
+ // TextWrapMode wrap,
946
+ // boolean visible)
947
+
948
+ ultraliteCanvas!!.commit()
949
+ screenIsClear = false
950
+ }
951
+
952
+
953
+ fun displayBulletList(title: String, bullets: Array<String>) {
954
+ displayBulletList(title, bullets, 14)
955
+ }
956
+
957
+ fun displayRowsCard(rowStrings: Array<String>) {
958
+ displayRowsCard(rowStrings, cardLingerTime)
959
+ }
960
+
961
+ fun displayRowsCard(rowStringList: Array<String>, lingerTime: Int) {
962
+ if (screenToggleOff) {
963
+ return
964
+ }
965
+
966
+ val rowStrings = maybeReverseRTLStringList(rowStringList)
967
+ if (connectionState != ConnTypes.CONNECTED) {
968
+ Log.d(TAG, "Not showing rows card because not connected to Ultralites...")
969
+ return
970
+ }
971
+
972
+ // changeUltraliteLayout(Layout.CANVAS);
973
+ // ultraliteCanvas.clear();
974
+
975
+ //make lines to draw on screen to delineate rows
976
+ val line_thickness = 3
977
+ var y = 120
978
+ while (y < 480) {
979
+ ultraliteCanvas!!.clearBackgroundRect(0, y, 640, line_thickness, UltraliteColor.DIM)
980
+ y += 120
981
+ }
982
+
983
+ //clear old text
984
+ for (i in 0 until rowTextsLiveNow!!.size) {
985
+ ultraliteCanvas!!.removeText(i)
986
+ }
987
+ //old way to clear old text - vuzix ultralite sdk bug that clear background doesn't clear text?
988
+ // for (int y = 0; y < 480; y += 120) {
989
+ // //clear previous text
990
+ // ultraliteCanvas.clearBackgroundRect(0, y + line_thickness, 640, 120 - line_thickness, UltraliteColor.DIM);
991
+ // ultraliteCanvas.clearBackgroundRect(0, y + line_thickness, 640, 120 - line_thickness, UltraliteColor.BLACK);
992
+ // }
993
+ // ultraliteCanvas.commit();
994
+
995
+ //display the title at the top of the screen
996
+ val ultraliteColor = UltraliteColor.WHITE
997
+ val ultraliteAnchor = Anchor.TOP_LEFT
998
+ val ultraliteAlignment = TextAlignment.LEFT
999
+
1000
+ //if no input, just show the lines
1001
+ if (rowStrings.isEmpty()) {
1002
+ ultraliteCanvas!!.commit()
1003
+ screenIsClear = false
1004
+ return
1005
+ }
1006
+
1007
+ //go throw rows, draw the text, don't do more than 4
1008
+ val y_start_height = 55
1009
+ // Reverse rowStrings array
1010
+ rowStrings.reverse()
1011
+ val numRows = 4
1012
+ val actualRows = Math.min(rowStrings.size, numRows)
1013
+ for (i in 0 until actualRows) {
1014
+ // Calculate the offset to start from the bottom for 1, 2, or 3 values
1015
+ val yOffset = (numRows - actualRows) * 112
1016
+ val textId = ultraliteCanvas!!.createText(rowStrings[i], TextAlignment.CENTER, UltraliteColor.WHITE, Anchor.TOP_LEFT, ultraliteLeftSidePixelBuffer, y_start_height + yOffset + (i * 112), 640 - ultraliteLeftSidePixelBuffer, -1, TextWrapMode.WRAP, true)
1017
+ rowTextsLiveNow!!.add(textId)
1018
+ }
1019
+
1020
+ ultraliteCanvas!!.commit()
1021
+ screenIsClear = false
1022
+ }
1023
+
1024
+ fun displayBulletList(title: String, bulletList: Array<String>, lingerTime: Int) {
1025
+ if (screenToggleOff) {
1026
+ return
1027
+ }
1028
+
1029
+ val bullets = maybeReverseRTLStringList(bulletList)
1030
+ if (connectionState != ConnTypes.CONNECTED) {
1031
+ Log.d(TAG, "Not showing bullet point list because not connected to Ultralites...")
1032
+ return
1033
+ }
1034
+
1035
+ Log.d(TAG, "Sending bullets to Ultralite SDK: " + title)
1036
+
1037
+ //display the title at the top of the screen
1038
+ val ultraliteColor = UltraliteColor.WHITE
1039
+ val ultraliteAnchor = Anchor.TOP_LEFT
1040
+ val ultraliteAlignment = TextAlignment.LEFT
1041
+ changeUltraliteLayout(Layout.CANVAS)
1042
+ ultraliteCanvas!!.clear()
1043
+
1044
+ ultraliteCanvas!!.createText(title, TextAlignment.AUTO, UltraliteColor.WHITE, Anchor.TOP_LEFT, 0, 0, 640, -1, TextWrapMode.WRAP, true)
1045
+ var displaceY = 25
1046
+ val displaceX = 25
1047
+ for (bullet in bullets) {
1048
+ ultraliteCanvas!!.createText("⬤ " + bullet, TextAlignment.AUTO, UltraliteColor.WHITE, Anchor.TOP_LEFT, displaceX, displaceY, 640 - displaceX, -1, TextWrapMode.WRAP, true)
1049
+ displaceY += 125
1050
+ }
1051
+
1052
+ ultraliteCanvas!!.commit()
1053
+ screenIsClear = false
1054
+ }
1055
+
1056
+ // public void homeScreenInNSeconds(int n){
1057
+ // if (n == -1){
1058
+ // return;
1059
+ // }
1060
+ //
1061
+ // //disconnect after slight delay, so our above text gets a chance to show up
1062
+ // goHomeHandler.removeCallbacksAndMessages(null);
1063
+ // goHomeHandler.removeCallbacksAndMessages(goHomeRunnable);
1064
+ // goHomeRunnable = new Runnable() {
1065
+ // @Override
1066
+ // public void run() {
1067
+ // showHomeScreen();
1068
+ // }};
1069
+ // goHomeHandler.postDelayed(goHomeRunnable, n * 1000);
1070
+ // }
1071
+
1072
+ fun displayBitmap(bmp: Bitmap) {
1073
+ val resizedBmp = Bitmap.createScaledBitmap(bmp, 620, 460, true) // 640 x 480
1074
+
1075
+ changeUltraliteLayout(Layout.CANVAS)
1076
+ screenIsClear = false
1077
+
1078
+ Log.d(TAG, "Sending bitmap to Ultralite")
1079
+ ultraliteCanvas!!.drawBackground(resizedBmp, 50, 80)
1080
+ ultraliteCanvas!!.commit()
1081
+ }
1082
+
1083
+ //don't show images on activelook (screen is too low res)
1084
+ fun displayReferenceCardImage(title: String, body: String, imgUrl: String) {
1085
+ if (screenToggleOff) {
1086
+ return
1087
+ }
1088
+
1089
+ changeUltraliteLayout(Layout.CANVAS)
1090
+ ultraliteCanvas!!.clear()
1091
+
1092
+ //make image
1093
+ //below works, but only for very, very low res/size images
1094
+ val ultraliteImageAnchor = Anchor.CENTER
1095
+ Picasso.get()
1096
+ .load(imgUrl)
1097
+ .into(object : Target {
1098
+ override fun onBitmapLoaded(bitmap: Bitmap?, from: Picasso.LoadedFrom?) {
1099
+ // Use the bitmap
1100
+ // LVGLImage ultraliteImage = LVGLImage.fromBitmap(getBitmapFromDrawable(context.getResources()), CF_INDEXED_2_BIT);
1101
+ // LVGLImage ultraliteImage = LVGLImage.fromBitmap(bitmap, CF_INDEXED_2_BIT);
1102
+ changeUltraliteLayout(Layout.CANVAS)
1103
+
1104
+ //send text first, cuz this is fast
1105
+ ultraliteCanvas!!.createText(title, TextAlignment.AUTO, UltraliteColor.WHITE, Anchor.TOP_LEFT, 0, 0, 640, -1, TextWrapMode.WRAP, true)
1106
+ ultraliteCanvas!!.createText(body, TextAlignment.AUTO, UltraliteColor.WHITE, Anchor.BOTTOM_LEFT, 0, 0, 640, -1, TextWrapMode.WRAP, true)
1107
+ ultraliteCanvas!!.commit()
1108
+ screenIsClear = false
1109
+
1110
+ Log.d(TAG, "Sending image to Ultralite")
1111
+ // ultraliteCanvas.createImage(ultraliteImage, ultraliteImageAnchor, 0, 0, true);
1112
+ ultraliteCanvas!!.drawBackground(bitmap!!, 0, 0)
1113
+
1114
+ //sending text again to ultralite in case image overwrote it
1115
+ // ultraliteCanvas.createText(title + "2", TextAlignment.AUTO, UltraliteColor.WHITE, Anchor.BOTTOM_LEFT, 0, 0, 640, -1, TextWrapMode.WRAP, true);
1116
+ // ultraliteCanvas.createText(body + "2", TextAlignment.AUTO, UltraliteColor.WHITE, Anchor.MIDDLE_LEFT, 0, 0, 640, -1, TextWrapMode.WRAP, true);
1117
+ // ultraliteCanvas.commit();
1118
+
1119
+ // //display the title at the top of the screen
1120
+ // UltraliteColor ultraliteColor = UltraliteColor.WHITE;
1121
+ // TextAlignment ultraliteAlignment = TextAlignment.LEFT;
1122
+ // // ultraliteCanvas.clearBackground(UltraliteColor.DIM);
1123
+ // ultraliteCanvas.createText(titleWrapped, ultraliteAlignment, ultraliteColor, Anchor.TOP_LEFT, true); //, 0, 0, -1, -1, TextWrapMode.WRAP, true);
1124
+ // ultraliteCanvas.createText(bodyWrapped, ultraliteAlignment, ultraliteColor, Anchor.BOTTOM_LEFT, true); //, 0, 0, -1, -1, TextWrapMode.WRAP, true);
1125
+ // ultraliteCanvas.commit();
1126
+ }
1127
+
1128
+ override fun onBitmapFailed(e: Exception?, errorDrawable: Drawable?) {
1129
+ // Handle the error
1130
+ Log.d(TAG, "Bitmap failed")
1131
+ e!!.printStackTrace()
1132
+ }
1133
+
1134
+ override fun onPrepareLoad(placeHolderDrawable: Drawable?) {
1135
+ // Called before the image is loaded. You can set a placeholder if needed.
1136
+ }
1137
+ })
1138
+
1139
+ //edit the text to add new lines to it because ultralite wrapping doesn't work
1140
+ // String titleWrapped = addNewlineEveryNWords(title, 6);
1141
+ // String bodyWrapped = addNewlineEveryNWords(body, 6);
1142
+ //
1143
+ // //display the title at the top of the screen
1144
+ // UltraliteColor ultraliteColor = UltraliteColor.WHITE;
1145
+ // TextAlignment ultraliteAlignment = TextAlignment.LEFT;
1146
+ // //ultraliteCanvas.clearBackground(UltraliteColor.DIM);
1147
+ // ultraliteCanvas.createText(titleWrapped, ultraliteAlignment, ultraliteColor, Anchor.TOP_LEFT, true); //, 0, 0, -1, -1, TextWrapMode.WRAP, true);
1148
+ // ultraliteCanvas.createText(bodyWrapped, ultraliteAlignment, ultraliteColor, Anchor.BOTTOM_LEFT, true); //, 0, 0, -1, -1, TextWrapMode.WRAP, true);
1149
+ // ultraliteCanvas.commit();
1150
+ // screenIsClear = false;
1151
+ }
1152
+
1153
+ //handles text wrapping, returns final position of last line printed
1154
+ // private Point displayText(TextLineSG textLine, Point percentLoc, boolean centered){
1155
+ // if (!isConnected()){
1156
+ // return null;
1157
+ // }
1158
+ //
1159
+ // //get info about the wrapping
1160
+ // Pair wrapInfo = computeStringWrapInfo(textLine);
1161
+ // int numWraps = (int)wrapInfo.first;
1162
+ // int wrapLenNumChars = (int)wrapInfo.second;
1163
+ //
1164
+ // //loop through the text, writing out individual lines to the glasses
1165
+ // ArrayList<String> chunkedText = new ArrayList<>();
1166
+ // Point textPoint = percentLoc;
1167
+ // int textMarginY = computeMarginPercent(textLine.getFontSizeCode()); //(fontToSize.get(textLine.getFontSize()) * 1.3)
1168
+ // for (int i = 0; i <= numWraps; i++){
1169
+ // int startIdx = wrapLenNumChars * i;
1170
+ // int endIdx = Math.min(startIdx + wrapLenNumChars, textLine.getText().length());
1171
+ // String subText = textLine.getText().substring(startIdx, endIdx).trim();
1172
+ // chunkedText.add(subText);
1173
+ // TextLineSG thisTextLine = new TextLineSG(subText, textLine.getFontSizeCode());
1174
+ // if (!centered) {
1175
+ // sendTextToGlasses(thisTextLine, textPoint);
1176
+ // } else {
1177
+ // int xPercentLoc = computeStringCenterInfo(thisTextLine);
1178
+ // sendTextToGlasses(thisTextLine, new Point(xPercentLoc, textPoint.y));
1179
+ // }
1180
+ // textPoint = new Point(textPoint.x, textPoint.y + pixelToPercent(displayHeightPixels, fontToSize.get(textLine.getFontSizeCode())) + textMarginY); //lower our text for the next loop
1181
+ // }
1182
+ //
1183
+ // return textPoint;
1184
+ // }
1185
+
1186
+ fun stopScrollingTextViewMode() {
1187
+ // if (connectedGlasses == null) {
1188
+ // return;
1189
+ // }
1190
+ //
1191
+ // //clear the screen
1192
+ // connectedGlasses.clear();
1193
+ }
1194
+
1195
+ fun scrollingTextViewIntermediateText(text: String) {
1196
+ }
1197
+
1198
+ fun scrollingTextViewFinalText(text: String) {
1199
+ if (connectionState != ConnTypes.CONNECTED) {
1200
+ return
1201
+ }
1202
+
1203
+ // //save to our saved list of final scrolling text strings
1204
+ // finalScrollingTextStrings.add(text);
1205
+ //
1206
+ // //get the max number of wraps allows
1207
+ // float allowedTextRows = computeAllowedTextRows(fontToSize.get(scrollingTextTitleFontSize), fontToSize.get(scrollingTextTextFontSize), percentToPixel(displayHeightPixels, computeMarginPercent(scrollingTextTextFontSize)));
1208
+ //
1209
+ // //figure out the maximum we can display
1210
+ // int totalRows = 0;
1211
+ // ArrayList<String> finalTextToDisplay = new ArrayList<>();
1212
+ // boolean hitBottom = false;
1213
+ // for (int i = finalScrollingTextStrings.toArray().length - 1; i >= 0; i--){
1214
+ // String finalText = finalScrollingTextStrings.get(i);
1215
+ // //convert to a TextLine type with small font
1216
+ // TextLineSG tlString = new TextLineSG(finalText, SMALL_FONT);
1217
+ // //get info about the wrapping of this string
1218
+ // Pair wrapInfo = computeStringWrapInfo(tlString);
1219
+ // int numWraps = (int)wrapInfo.first;
1220
+ // int wrapLenNumChars = (int)wrapInfo.second;
1221
+ // totalRows += numWraps + 1;
1222
+ //
1223
+ // if (totalRows > allowedTextRows){
1224
+ // finalScrollingTextStrings = finalTextToDisplay;
1225
+ // lastLocScrollingTextView = belowTitleLocScrollingTextView;
1226
+ // //clear the glasses as we hit our limit and need to redraw
1227
+ // connectedGlasses.color((byte)0x00);
1228
+ // connectedGlasses.rectf(percentScreenToPixelsLocation(belowTitleLocScrollingTextView.x, belowTitleLocScrollingTextView.y), percentScreenToPixelsLocation(100, 100));
1229
+ // //stop looping, as we've ran out of room
1230
+ // hitBottom = true;
1231
+ // } else {
1232
+ // finalTextToDisplay.add(0, finalText);
1233
+ // }
1234
+ // }
1235
+ //
1236
+ // //display all of the text that we can
1237
+ // if (hitBottom) { //if we ran out of room, we need to redraw all the text
1238
+ // for (String finalString : finalTextToDisplay) {
1239
+ // TextLineSG tlString = new TextLineSG(finalString, scrollingTextTextFontSize);
1240
+ // //write this text at the last location + margin
1241
+ // Log.d(TAG, "Writing string: " + tlString.getText() + finalTextToDisplay.size());
1242
+ // lastLocScrollingTextView = displayText(tlString, new Point(0, lastLocScrollingTextView.y));
1243
+ // }
1244
+ // } else { //if we didn't hit the bottom, and there's room, we can just display the next line
1245
+ // TextLineSG tlString = new TextLineSG(text, scrollingTextTextFontSize);
1246
+ // lastLocScrollingTextView = displayText(tlString, new Point(0, lastLocScrollingTextView.y));
1247
+ // }
1248
+
1249
+ }
1250
+
1251
+ fun maybeReverseRTLStringList(input: Array<String>): Array<String> {
1252
+ val out = arrayOfNulls<String>(input.size)
1253
+ for (i in 0 until input.size)
1254
+ out[i] = maybeReverseRTLString(input[i])
1255
+ @Suppress("UNCHECKED_CAST")
1256
+ return out as Array<String>
1257
+ }
1258
+
1259
+ fun displayPromptView(prompt: String, options: Array<String>?) {
1260
+ if (connectionState != ConnTypes.CONNECTED) {
1261
+ return
1262
+ }
1263
+
1264
+ // ultraliteCanvas.clear();
1265
+ // connectedGlasses.clear();
1266
+ // showPromptCircle();
1267
+ //
1268
+ // //show the prompt and options, if any
1269
+ // ArrayList<Object> promptPageElements = new ArrayList<>();
1270
+ // promptPageElements.add(new TextLineSG(prompt, LARGE_FONT));
1271
+ // if (options != null) {
1272
+ // //make an array list of options
1273
+ // for (String s : options){
1274
+ // promptPageElements.add(new TextLineSG(s, SMALL_FONT));
1275
+ // }
1276
+ // }
1277
+ // displayLinearStuff(promptPageElements, new Point(0, 11), true);
1278
+ }
1279
+
1280
+ }