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