@mentra/engine 0.1.0-dev.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (787) hide show
  1. package/README.md +79 -0
  2. package/build/devtools.d.ts +11 -0
  3. package/build/devtools.d.ts.map +1 -0
  4. package/build/devtools.js +13 -0
  5. package/build/devtools.js.map +1 -0
  6. package/build/engine.d.ts +261 -0
  7. package/build/engine.d.ts.map +1 -0
  8. package/build/engine.js +170 -0
  9. package/build/engine.js.map +1 -0
  10. package/build/facades/dev.d.ts +57 -0
  11. package/build/facades/dev.d.ts.map +1 -0
  12. package/build/facades/dev.js +187 -0
  13. package/build/facades/dev.js.map +1 -0
  14. package/build/facades/display.d.ts +21 -0
  15. package/build/facades/display.d.ts.map +1 -0
  16. package/build/facades/display.js +17 -0
  17. package/build/facades/display.js.map +1 -0
  18. package/build/facades/displayMirror.d.ts +15 -0
  19. package/build/facades/displayMirror.d.ts.map +1 -0
  20. package/build/facades/displayMirror.js +29 -0
  21. package/build/facades/displayMirror.js.map +1 -0
  22. package/build/facades/gallery.d.ts +62 -0
  23. package/build/facades/gallery.d.ts.map +1 -0
  24. package/build/facades/gallery.js +61 -0
  25. package/build/facades/gallery.js.map +1 -0
  26. package/build/facades/glasses.d.ts +141 -0
  27. package/build/facades/glasses.d.ts.map +1 -0
  28. package/build/facades/glasses.js +199 -0
  29. package/build/facades/glasses.js.map +1 -0
  30. package/build/facades/glassesSettings.d.ts +13 -0
  31. package/build/facades/glassesSettings.d.ts.map +1 -0
  32. package/build/facades/glassesSettings.js +54 -0
  33. package/build/facades/glassesSettings.js.map +1 -0
  34. package/build/facades/glassesWifi.d.ts +25 -0
  35. package/build/facades/glassesWifi.d.ts.map +1 -0
  36. package/build/facades/glassesWifi.js +57 -0
  37. package/build/facades/glassesWifi.js.map +1 -0
  38. package/build/facades/miniapps.d.ts +43 -0
  39. package/build/facades/miniapps.d.ts.map +1 -0
  40. package/build/facades/miniapps.js +49 -0
  41. package/build/facades/miniapps.js.map +1 -0
  42. package/build/facades/notifications.d.ts +13 -0
  43. package/build/facades/notifications.d.ts.map +1 -0
  44. package/build/facades/notifications.js +12 -0
  45. package/build/facades/notifications.js.map +1 -0
  46. package/build/facades/ota.d.ts +103 -0
  47. package/build/facades/ota.d.ts.map +1 -0
  48. package/build/facades/ota.js +156 -0
  49. package/build/facades/ota.js.map +1 -0
  50. package/build/facades/pairing.d.ts +114 -0
  51. package/build/facades/pairing.d.ts.map +1 -0
  52. package/build/facades/pairing.js +275 -0
  53. package/build/facades/pairing.js.map +1 -0
  54. package/build/facades/permissions.d.ts +23 -0
  55. package/build/facades/permissions.d.ts.map +1 -0
  56. package/build/facades/permissions.js +145 -0
  57. package/build/facades/permissions.js.map +1 -0
  58. package/build/facades/phoneNotifications.d.ts +21 -0
  59. package/build/facades/phoneNotifications.d.ts.map +1 -0
  60. package/build/facades/phoneNotifications.js +51 -0
  61. package/build/facades/phoneNotifications.js.map +1 -0
  62. package/build/facades/reports.d.ts +36 -0
  63. package/build/facades/reports.d.ts.map +1 -0
  64. package/build/facades/reports.js +134 -0
  65. package/build/facades/reports.js.map +1 -0
  66. package/build/facades/session.d.ts +21 -0
  67. package/build/facades/session.d.ts.map +1 -0
  68. package/build/facades/session.js +52 -0
  69. package/build/facades/session.js.map +1 -0
  70. package/build/facades/settings.d.ts +37 -0
  71. package/build/facades/settings.d.ts.map +1 -0
  72. package/build/facades/settings.js +55 -0
  73. package/build/facades/settings.js.map +1 -0
  74. package/build/facades/speech.d.ts +30 -0
  75. package/build/facades/speech.d.ts.map +1 -0
  76. package/build/facades/speech.js +37 -0
  77. package/build/facades/speech.js.map +1 -0
  78. package/build/index.d.ts +43 -0
  79. package/build/index.d.ts.map +1 -0
  80. package/build/index.js +45 -0
  81. package/build/index.js.map +1 -0
  82. package/build/internal.d.ts +66 -0
  83. package/build/internal.d.ts.map +1 -0
  84. package/build/internal.js +89 -0
  85. package/build/internal.js.map +1 -0
  86. package/build/runtime/bootstrap.d.ts +83 -0
  87. package/build/runtime/bootstrap.d.ts.map +1 -0
  88. package/build/runtime/bootstrap.js +56 -0
  89. package/build/runtime/bootstrap.js.map +1 -0
  90. package/build/runtime/config.d.ts +146 -0
  91. package/build/runtime/config.d.ts.map +1 -0
  92. package/build/runtime/config.js +18 -0
  93. package/build/runtime/config.js.map +1 -0
  94. package/build/runtime/streamConfig.d.ts +4 -0
  95. package/build/runtime/streamConfig.d.ts.map +1 -0
  96. package/build/runtime/streamConfig.js +38 -0
  97. package/build/runtime/streamConfig.js.map +1 -0
  98. package/build/services/AppRegistry.d.ts +303 -0
  99. package/build/services/AppRegistry.d.ts.map +1 -0
  100. package/build/services/AppRegistry.js +1029 -0
  101. package/build/services/AppRegistry.js.map +1 -0
  102. package/build/services/AudioCloudUplink.d.ts +3 -0
  103. package/build/services/AudioCloudUplink.d.ts.map +1 -0
  104. package/build/services/AudioCloudUplink.js +33 -0
  105. package/build/services/AudioCloudUplink.js.map +1 -0
  106. package/build/services/AudioPlaybackService.d.ts +144 -0
  107. package/build/services/AudioPlaybackService.d.ts.map +1 -0
  108. package/build/services/AudioPlaybackService.js +533 -0
  109. package/build/services/AudioPlaybackService.js.map +1 -0
  110. package/build/services/AutomaticReportResult.d.ts +20 -0
  111. package/build/services/AutomaticReportResult.d.ts.map +1 -0
  112. package/build/services/AutomaticReportResult.js +29 -0
  113. package/build/services/AutomaticReportResult.js.map +1 -0
  114. package/build/services/BlobStore.d.ts +91 -0
  115. package/build/services/BlobStore.d.ts.map +1 -0
  116. package/build/services/BlobStore.js +668 -0
  117. package/build/services/BlobStore.js.map +1 -0
  118. package/build/services/CaptionsTesterReportService.d.ts +4 -0
  119. package/build/services/CaptionsTesterReportService.d.ts.map +1 -0
  120. package/build/services/CaptionsTesterReportService.js +80 -0
  121. package/build/services/CaptionsTesterReportService.js.map +1 -0
  122. package/build/services/CloudAudioSubscriptionSync.d.ts +24 -0
  123. package/build/services/CloudAudioSubscriptionSync.d.ts.map +1 -0
  124. package/build/services/CloudAudioSubscriptionSync.js +39 -0
  125. package/build/services/CloudAudioSubscriptionSync.js.map +1 -0
  126. package/build/services/CloudClientService.d.ts +143 -0
  127. package/build/services/CloudClientService.d.ts.map +1 -0
  128. package/build/services/CloudClientService.js +627 -0
  129. package/build/services/CloudClientService.js.map +1 -0
  130. package/build/services/CloudTranscriptE2EMetrics.d.ts +4 -0
  131. package/build/services/CloudTranscriptE2EMetrics.d.ts.map +1 -0
  132. package/build/services/CloudTranscriptE2EMetrics.js +24 -0
  133. package/build/services/CloudTranscriptE2EMetrics.js.map +1 -0
  134. package/build/services/ConnectionCoordinator.d.ts +51 -0
  135. package/build/services/ConnectionCoordinator.d.ts.map +1 -0
  136. package/build/services/ConnectionCoordinator.js +34 -0
  137. package/build/services/ConnectionCoordinator.js.map +1 -0
  138. package/build/services/DevServerBridge.d.ts +63 -0
  139. package/build/services/DevServerBridge.d.ts.map +1 -0
  140. package/build/services/DevServerBridge.js +294 -0
  141. package/build/services/DevServerBridge.js.map +1 -0
  142. package/build/services/DeviceEventRouter.d.ts +3 -0
  143. package/build/services/DeviceEventRouter.d.ts.map +1 -0
  144. package/build/services/DeviceEventRouter.js +190 -0
  145. package/build/services/DeviceEventRouter.js.map +1 -0
  146. package/build/services/DeviceStoreHydration.d.ts +38 -0
  147. package/build/services/DeviceStoreHydration.d.ts.map +1 -0
  148. package/build/services/DeviceStoreHydration.js +124 -0
  149. package/build/services/DeviceStoreHydration.js.map +1 -0
  150. package/build/services/DisplayProcessor.d.ts +223 -0
  151. package/build/services/DisplayProcessor.d.ts.map +1 -0
  152. package/build/services/DisplayProcessor.js +552 -0
  153. package/build/services/DisplayProcessor.js.map +1 -0
  154. package/build/services/GlassesReadiness.d.ts +41 -0
  155. package/build/services/GlassesReadiness.d.ts.map +1 -0
  156. package/build/services/GlassesReadiness.js +82 -0
  157. package/build/services/GlassesReadiness.js.map +1 -0
  158. package/build/services/GlassesSettingsSync.d.ts +33 -0
  159. package/build/services/GlassesSettingsSync.d.ts.map +1 -0
  160. package/build/services/GlassesSettingsSync.js +121 -0
  161. package/build/services/GlassesSettingsSync.js.map +1 -0
  162. package/build/services/GlassesStatusProjection.d.ts +3 -0
  163. package/build/services/GlassesStatusProjection.d.ts.map +1 -0
  164. package/build/services/GlassesStatusProjection.js +65 -0
  165. package/build/services/GlassesStatusProjection.js.map +1 -0
  166. package/build/services/HeadingService.d.ts +27 -0
  167. package/build/services/HeadingService.d.ts.map +1 -0
  168. package/build/services/HeadingService.js +96 -0
  169. package/build/services/HeadingService.js.map +1 -0
  170. package/build/services/LocalDisplayManager.d.ts +139 -0
  171. package/build/services/LocalDisplayManager.d.ts.map +1 -0
  172. package/build/services/LocalDisplayManager.js +579 -0
  173. package/build/services/LocalDisplayManager.js.map +1 -0
  174. package/build/services/LocalMiniappRuntime.d.ts +433 -0
  175. package/build/services/LocalMiniappRuntime.d.ts.map +1 -0
  176. package/build/services/LocalMiniappRuntime.js +3561 -0
  177. package/build/services/LocalMiniappRuntime.js.map +1 -0
  178. package/build/services/LocalSttFallbackCoordinator.d.ts +54 -0
  179. package/build/services/LocalSttFallbackCoordinator.d.ts.map +1 -0
  180. package/build/services/LocalSttFallbackCoordinator.js +131 -0
  181. package/build/services/LocalSttFallbackCoordinator.js.map +1 -0
  182. package/build/services/MentraJSCrashController.d.ts +97 -0
  183. package/build/services/MentraJSCrashController.d.ts.map +1 -0
  184. package/build/services/MentraJSCrashController.js +138 -0
  185. package/build/services/MentraJSCrashController.js.map +1 -0
  186. package/build/services/MentraJSCrashloopReportService.d.ts +9 -0
  187. package/build/services/MentraJSCrashloopReportService.d.ts.map +1 -0
  188. package/build/services/MentraJSCrashloopReportService.js +54 -0
  189. package/build/services/MentraJSCrashloopReportService.js.map +1 -0
  190. package/build/services/MentraJSLogPipeline.d.ts +87 -0
  191. package/build/services/MentraJSLogPipeline.d.ts.map +1 -0
  192. package/build/services/MentraJSLogPipeline.js +137 -0
  193. package/build/services/MentraJSLogPipeline.js.map +1 -0
  194. package/build/services/MentraJSRouter.d.ts +203 -0
  195. package/build/services/MentraJSRouter.d.ts.map +1 -0
  196. package/build/services/MentraJSRouter.js +480 -0
  197. package/build/services/MentraJSRouter.js.map +1 -0
  198. package/build/services/MentraUIRouter.d.ts +137 -0
  199. package/build/services/MentraUIRouter.d.ts.map +1 -0
  200. package/build/services/MentraUIRouter.js +210 -0
  201. package/build/services/MentraUIRouter.js.map +1 -0
  202. package/build/services/MicStateCoordinator.d.ts +37 -0
  203. package/build/services/MicStateCoordinator.d.ts.map +1 -0
  204. package/build/services/MicStateCoordinator.js +81 -0
  205. package/build/services/MicStateCoordinator.js.map +1 -0
  206. package/build/services/MiniappEngine.d.ts +31 -0
  207. package/build/services/MiniappEngine.d.ts.map +1 -0
  208. package/build/services/MiniappEngine.js +119 -0
  209. package/build/services/MiniappEngine.js.map +1 -0
  210. package/build/services/MiniappLauncher.d.ts +129 -0
  211. package/build/services/MiniappLauncher.d.ts.map +1 -0
  212. package/build/services/MiniappLauncher.js +291 -0
  213. package/build/services/MiniappLauncher.js.map +1 -0
  214. package/build/services/MiniappRunningRegistry.d.ts +24 -0
  215. package/build/services/MiniappRunningRegistry.d.ts.map +1 -0
  216. package/build/services/MiniappRunningRegistry.js +52 -0
  217. package/build/services/MiniappRunningRegistry.js.map +1 -0
  218. package/build/services/NavigationHandlers.d.ts +90 -0
  219. package/build/services/NavigationHandlers.d.ts.map +1 -0
  220. package/build/services/NavigationHandlers.js +379 -0
  221. package/build/services/NavigationHandlers.js.map +1 -0
  222. package/build/services/NavigationService.d.ts +254 -0
  223. package/build/services/NavigationService.d.ts.map +1 -0
  224. package/build/services/NavigationService.js +553 -0
  225. package/build/services/NavigationService.js.map +1 -0
  226. package/build/services/NotificationsEmitter.d.ts +28 -0
  227. package/build/services/NotificationsEmitter.d.ts.map +1 -0
  228. package/build/services/NotificationsEmitter.js +22 -0
  229. package/build/services/NotificationsEmitter.js.map +1 -0
  230. package/build/services/OfflineSpeechModelService.d.ts +33 -0
  231. package/build/services/OfflineSpeechModelService.d.ts.map +1 -0
  232. package/build/services/OfflineSpeechModelService.js +136 -0
  233. package/build/services/OfflineSpeechModelService.js.map +1 -0
  234. package/build/services/OtaInstallCoordinator.d.ts +195 -0
  235. package/build/services/OtaInstallCoordinator.d.ts.map +1 -0
  236. package/build/services/OtaInstallCoordinator.js +1047 -0
  237. package/build/services/OtaInstallCoordinator.js.map +1 -0
  238. package/build/services/OtaService.d.ts +3 -0
  239. package/build/services/OtaService.d.ts.map +1 -0
  240. package/build/services/OtaService.js +65 -0
  241. package/build/services/OtaService.js.map +1 -0
  242. package/build/services/OtaUpdateCheckService.d.ts +65 -0
  243. package/build/services/OtaUpdateCheckService.d.ts.map +1 -0
  244. package/build/services/OtaUpdateCheckService.js +260 -0
  245. package/build/services/OtaUpdateCheckService.js.map +1 -0
  246. package/build/services/PairingIdentity.d.ts +80 -0
  247. package/build/services/PairingIdentity.d.ts.map +1 -0
  248. package/build/services/PairingIdentity.js +145 -0
  249. package/build/services/PairingIdentity.js.map +1 -0
  250. package/build/services/PhoneLocationService.d.ts +36 -0
  251. package/build/services/PhoneLocationService.d.ts.map +1 -0
  252. package/build/services/PhoneLocationService.js +115 -0
  253. package/build/services/PhoneLocationService.js.map +1 -0
  254. package/build/services/PhoneNotificationsSync.d.ts +3 -0
  255. package/build/services/PhoneNotificationsSync.d.ts.map +1 -0
  256. package/build/services/PhoneNotificationsSync.js +35 -0
  257. package/build/services/PhoneNotificationsSync.js.map +1 -0
  258. package/build/services/PhonePhotoCoordinator.d.ts +86 -0
  259. package/build/services/PhonePhotoCoordinator.d.ts.map +1 -0
  260. package/build/services/PhonePhotoCoordinator.js +274 -0
  261. package/build/services/PhonePhotoCoordinator.js.map +1 -0
  262. package/build/services/PhoneStreamCoordinator.d.ts +168 -0
  263. package/build/services/PhoneStreamCoordinator.d.ts.map +1 -0
  264. package/build/services/PhoneStreamCoordinator.js +632 -0
  265. package/build/services/PhoneStreamCoordinator.js.map +1 -0
  266. package/build/services/PhoneVideoCoordinator.d.ts +50 -0
  267. package/build/services/PhoneVideoCoordinator.d.ts.map +1 -0
  268. package/build/services/PhoneVideoCoordinator.js +147 -0
  269. package/build/services/PhoneVideoCoordinator.js.map +1 -0
  270. package/build/services/STTModelManager.d.ts +65 -0
  271. package/build/services/STTModelManager.d.ts.map +1 -0
  272. package/build/services/STTModelManager.js +292 -0
  273. package/build/services/STTModelManager.js.map +1 -0
  274. package/build/services/SceneRenderer.d.ts +90 -0
  275. package/build/services/SceneRenderer.d.ts.map +1 -0
  276. package/build/services/SceneRenderer.js +248 -0
  277. package/build/services/SceneRenderer.js.map +1 -0
  278. package/build/services/StreamLifecycleController.d.ts +67 -0
  279. package/build/services/StreamLifecycleController.d.ts.map +1 -0
  280. package/build/services/StreamLifecycleController.js +152 -0
  281. package/build/services/StreamLifecycleController.js.map +1 -0
  282. package/build/services/TTSModelManager.d.ts +90 -0
  283. package/build/services/TTSModelManager.d.ts.map +1 -0
  284. package/build/services/TTSModelManager.js +366 -0
  285. package/build/services/TTSModelManager.js.map +1 -0
  286. package/build/services/WebviewBridge.d.ts +22 -0
  287. package/build/services/WebviewBridge.d.ts.map +1 -0
  288. package/build/services/WebviewBridge.js +47 -0
  289. package/build/services/WebviewBridge.js.map +1 -0
  290. package/build/services/asg/GalleryMediaIntegrityReportService.d.ts +17 -0
  291. package/build/services/asg/GalleryMediaIntegrityReportService.d.ts.map +1 -0
  292. package/build/services/asg/GalleryMediaIntegrityReportService.js +43 -0
  293. package/build/services/asg/GalleryMediaIntegrityReportService.js.map +1 -0
  294. package/build/services/asg/asgCameraApi.d.ts +165 -0
  295. package/build/services/asg/asgCameraApi.d.ts.map +1 -0
  296. package/build/services/asg/asgCameraApi.js +997 -0
  297. package/build/services/asg/asgCameraApi.js.map +1 -0
  298. package/build/services/asg/galleryMediaValidation.d.ts +29 -0
  299. package/build/services/asg/galleryMediaValidation.d.ts.map +1 -0
  300. package/build/services/asg/galleryMediaValidation.js +149 -0
  301. package/build/services/asg/galleryMediaValidation.js.map +1 -0
  302. package/build/services/asg/galleryNotices.d.ts +33 -0
  303. package/build/services/asg/galleryNotices.d.ts.map +1 -0
  304. package/build/services/asg/galleryNotices.js +29 -0
  305. package/build/services/asg/galleryNotices.js.map +1 -0
  306. package/build/services/asg/gallerySettingsService.d.ts +19 -0
  307. package/build/services/asg/gallerySettingsService.d.ts.map +1 -0
  308. package/build/services/asg/gallerySettingsService.js +51 -0
  309. package/build/services/asg/gallerySettingsService.js.map +1 -0
  310. package/build/services/asg/gallerySyncNotifications.d.ts +56 -0
  311. package/build/services/asg/gallerySyncNotifications.d.ts.map +1 -0
  312. package/build/services/asg/gallerySyncNotifications.js +198 -0
  313. package/build/services/asg/gallerySyncNotifications.js.map +1 -0
  314. package/build/services/asg/gallerySyncService.d.ts +137 -0
  315. package/build/services/asg/gallerySyncService.d.ts.map +1 -0
  316. package/build/services/asg/gallerySyncService.js +1839 -0
  317. package/build/services/asg/gallerySyncService.js.map +1 -0
  318. package/build/services/asg/localStorageService.d.ts +128 -0
  319. package/build/services/asg/localStorageService.d.ts.map +1 -0
  320. package/build/services/asg/localStorageService.js +423 -0
  321. package/build/services/asg/localStorageService.js.map +1 -0
  322. package/build/services/asg/mediaProcessingQueue.d.ts +60 -0
  323. package/build/services/asg/mediaProcessingQueue.d.ts.map +1 -0
  324. package/build/services/asg/mediaProcessingQueue.js +320 -0
  325. package/build/services/asg/mediaProcessingQueue.js.map +1 -0
  326. package/build/services/asgOtaVersionUrl.d.ts +2 -0
  327. package/build/services/asgOtaVersionUrl.d.ts.map +1 -0
  328. package/build/services/asgOtaVersionUrl.js +36 -0
  329. package/build/services/asgOtaVersionUrl.js.map +1 -0
  330. package/build/services/blobPaths.d.ts +31 -0
  331. package/build/services/blobPaths.d.ts.map +1 -0
  332. package/build/services/blobPaths.js +86 -0
  333. package/build/services/blobPaths.js.map +1 -0
  334. package/build/services/cloudStreamApi.d.ts +59 -0
  335. package/build/services/cloudStreamApi.d.ts.map +1 -0
  336. package/build/services/cloudStreamApi.js +81 -0
  337. package/build/services/cloudStreamApi.js.map +1 -0
  338. package/build/services/gallerySyncClock.d.ts +17 -0
  339. package/build/services/gallerySyncClock.d.ts.map +1 -0
  340. package/build/services/gallerySyncClock.js +21 -0
  341. package/build/services/gallerySyncClock.js.map +1 -0
  342. package/build/services/glassesClockSync.d.ts +20 -0
  343. package/build/services/glassesClockSync.d.ts.map +1 -0
  344. package/build/services/glassesClockSync.js +97 -0
  345. package/build/services/glassesClockSync.js.map +1 -0
  346. package/build/services/manifestVersionGate.d.ts +28 -0
  347. package/build/services/manifestVersionGate.d.ts.map +1 -0
  348. package/build/services/manifestVersionGate.js +41 -0
  349. package/build/services/manifestVersionGate.js.map +1 -0
  350. package/build/services/mentraUiShim.d.ts +38 -0
  351. package/build/services/mentraUiShim.d.ts.map +1 -0
  352. package/build/services/mentraUiShim.js +360 -0
  353. package/build/services/mentraUiShim.js.map +1 -0
  354. package/build/services/navigation/roadNameResolver.d.ts +67 -0
  355. package/build/services/navigation/roadNameResolver.d.ts.map +1 -0
  356. package/build/services/navigation/roadNameResolver.js +96 -0
  357. package/build/services/navigation/roadNameResolver.js.map +1 -0
  358. package/build/services/navigation/routesApiCodec.d.ts +38 -0
  359. package/build/services/navigation/routesApiCodec.d.ts.map +1 -0
  360. package/build/services/navigation/routesApiCodec.js +68 -0
  361. package/build/services/navigation/routesApiCodec.js.map +1 -0
  362. package/build/services/otaDisplayState.d.ts +42 -0
  363. package/build/services/otaDisplayState.d.ts.map +1 -0
  364. package/build/services/otaDisplayState.js +92 -0
  365. package/build/services/otaDisplayState.js.map +1 -0
  366. package/build/services/otaInstallPolicy.d.ts +81 -0
  367. package/build/services/otaInstallPolicy.d.ts.map +1 -0
  368. package/build/services/otaInstallPolicy.js +96 -0
  369. package/build/services/otaInstallPolicy.js.map +1 -0
  370. package/build/services/otaLegacyMapping.d.ts +22 -0
  371. package/build/services/otaLegacyMapping.d.ts.map +1 -0
  372. package/build/services/otaLegacyMapping.js +56 -0
  373. package/build/services/otaLegacyMapping.js.map +1 -0
  374. package/build/services/slimStreamStatus.d.ts +7 -0
  375. package/build/services/slimStreamStatus.d.ts.map +1 -0
  376. package/build/services/slimStreamStatus.js +26 -0
  377. package/build/services/slimStreamStatus.js.map +1 -0
  378. package/build/stores/apps.d.ts +104 -0
  379. package/build/stores/apps.d.ts.map +1 -0
  380. package/build/stores/apps.js +492 -0
  381. package/build/stores/apps.js.map +1 -0
  382. package/build/stores/bluetoothSettingKeys.d.ts +4 -0
  383. package/build/stores/bluetoothSettingKeys.d.ts.map +1 -0
  384. package/build/stores/bluetoothSettingKeys.js +31 -0
  385. package/build/stores/bluetoothSettingKeys.js.map +1 -0
  386. package/build/stores/cloudClientStatus.d.ts +9 -0
  387. package/build/stores/cloudClientStatus.d.ts.map +1 -0
  388. package/build/stores/cloudClientStatus.js +24 -0
  389. package/build/stores/cloudClientStatus.js.map +1 -0
  390. package/build/stores/connection.d.ts +22 -0
  391. package/build/stores/connection.d.ts.map +1 -0
  392. package/build/stores/connection.js +43 -0
  393. package/build/stores/connection.js.map +1 -0
  394. package/build/stores/core.d.ts +15 -0
  395. package/build/stores/core.d.ts.map +1 -0
  396. package/build/stores/core.js +21 -0
  397. package/build/stores/core.js.map +1 -0
  398. package/build/stores/display.d.ts +24 -0
  399. package/build/stores/display.d.ts.map +1 -0
  400. package/build/stores/display.js +96 -0
  401. package/build/stores/display.js.map +1 -0
  402. package/build/stores/gallerySync.d.ts +101 -0
  403. package/build/stores/gallerySync.d.ts.map +1 -0
  404. package/build/stores/gallerySync.js +217 -0
  405. package/build/stores/gallerySync.js.map +1 -0
  406. package/build/stores/glasses.d.ts +62 -0
  407. package/build/stores/glasses.d.ts.map +1 -0
  408. package/build/stores/glasses.js +203 -0
  409. package/build/stores/glasses.js.map +1 -0
  410. package/build/stores/settings.d.ts +37 -0
  411. package/build/stores/settings.d.ts.map +1 -0
  412. package/build/stores/settings.js +915 -0
  413. package/build/stores/settings.js.map +1 -0
  414. package/build/types/applet.d.ts +96 -0
  415. package/build/types/applet.d.ts.map +1 -0
  416. package/build/types/applet.js +5 -0
  417. package/build/types/applet.js.map +1 -0
  418. package/build/types/asg.d.ts +46 -0
  419. package/build/types/asg.d.ts.map +1 -0
  420. package/build/types/asg.js +2 -0
  421. package/build/types/asg.js.map +1 -0
  422. package/build/types/capabilities/even-realities-g1.d.ts +12 -0
  423. package/build/types/capabilities/even-realities-g1.d.ts.map +1 -0
  424. package/build/types/capabilities/even-realities-g1.js +55 -0
  425. package/build/types/capabilities/even-realities-g1.js.map +1 -0
  426. package/build/types/capabilities/even-realities-g2.d.ts +12 -0
  427. package/build/types/capabilities/even-realities-g2.d.ts.map +1 -0
  428. package/build/types/capabilities/even-realities-g2.js +75 -0
  429. package/build/types/capabilities/even-realities-g2.js.map +1 -0
  430. package/build/types/capabilities/mentra-display.d.ts +12 -0
  431. package/build/types/capabilities/mentra-display.d.ts.map +1 -0
  432. package/build/types/capabilities/mentra-display.js +63 -0
  433. package/build/types/capabilities/mentra-display.js.map +1 -0
  434. package/build/types/capabilities/mentra-live.d.ts +12 -0
  435. package/build/types/capabilities/mentra-live.d.ts.map +1 -0
  436. package/build/types/capabilities/mentra-live.js +92 -0
  437. package/build/types/capabilities/mentra-live.js.map +1 -0
  438. package/build/types/capabilities/none.d.ts +13 -0
  439. package/build/types/capabilities/none.d.ts.map +1 -0
  440. package/build/types/capabilities/none.js +65 -0
  441. package/build/types/capabilities/none.js.map +1 -0
  442. package/build/types/capabilities/simulated-glasses.d.ts +13 -0
  443. package/build/types/capabilities/simulated-glasses.d.ts.map +1 -0
  444. package/build/types/capabilities/simulated-glasses.js +65 -0
  445. package/build/types/capabilities/simulated-glasses.js.map +1 -0
  446. package/build/types/capabilities/vuzix-z100.d.ts +12 -0
  447. package/build/types/capabilities/vuzix-z100.d.ts.map +1 -0
  448. package/build/types/capabilities/vuzix-z100.js +52 -0
  449. package/build/types/capabilities/vuzix-z100.js.map +1 -0
  450. package/build/types/enums.d.ts +40 -0
  451. package/build/types/enums.d.ts.map +1 -0
  452. package/build/types/enums.js +44 -0
  453. package/build/types/enums.js.map +1 -0
  454. package/build/types/hardware.d.ts +160 -0
  455. package/build/types/hardware.d.ts.map +1 -0
  456. package/build/types/hardware.js +36 -0
  457. package/build/types/hardware.js.map +1 -0
  458. package/build/types/index.d.ts +11 -0
  459. package/build/types/index.d.ts.map +1 -0
  460. package/build/types/index.js +10 -0
  461. package/build/types/index.js.map +1 -0
  462. package/build/utils/GlobalEventEmitter.d.ts +10 -0
  463. package/build/utils/GlobalEventEmitter.d.ts.map +1 -0
  464. package/build/utils/GlobalEventEmitter.js +13 -0
  465. package/build/utils/GlobalEventEmitter.js.map +1 -0
  466. package/build/utils/cloudClient/RnUdpAdapter.d.ts +3 -0
  467. package/build/utils/cloudClient/RnUdpAdapter.d.ts.map +1 -0
  468. package/build/utils/cloudClient/RnUdpAdapter.js +41 -0
  469. package/build/utils/cloudClient/RnUdpAdapter.js.map +1 -0
  470. package/build/utils/cloudClient/cloudSecureStore.d.ts +3 -0
  471. package/build/utils/cloudClient/cloudSecureStore.d.ts.map +1 -0
  472. package/build/utils/cloudClient/cloudSecureStore.js +26 -0
  473. package/build/utils/cloudClient/cloudSecureStore.js.map +1 -0
  474. package/build/utils/debouncedPatch.d.ts +6 -0
  475. package/build/utils/debouncedPatch.d.ts.map +1 -0
  476. package/build/utils/debouncedPatch.js +25 -0
  477. package/build/utils/debouncedPatch.js.map +1 -0
  478. package/build/utils/devLogging.d.ts +26 -0
  479. package/build/utils/devLogging.d.ts.map +1 -0
  480. package/build/utils/devLogging.js +116 -0
  481. package/build/utils/devLogging.js.map +1 -0
  482. package/build/utils/devMiniappLaunch.d.ts +44 -0
  483. package/build/utils/devMiniappLaunch.d.ts.map +1 -0
  484. package/build/utils/devMiniappLaunch.js +52 -0
  485. package/build/utils/devMiniappLaunch.js.map +1 -0
  486. package/build/utils/diagnosticContext.d.ts +3 -0
  487. package/build/utils/diagnosticContext.d.ts.map +1 -0
  488. package/build/utils/diagnosticContext.js +119 -0
  489. package/build/utils/diagnosticContext.js.map +1 -0
  490. package/build/utils/display/composer/ColumnComposer.d.ts +131 -0
  491. package/build/utils/display/composer/ColumnComposer.d.ts.map +1 -0
  492. package/build/utils/display/composer/ColumnComposer.js +204 -0
  493. package/build/utils/display/composer/ColumnComposer.js.map +1 -0
  494. package/build/utils/display/composer/index.d.ts +9 -0
  495. package/build/utils/display/composer/index.d.ts.map +1 -0
  496. package/build/utils/display/composer/index.js +9 -0
  497. package/build/utils/display/composer/index.js.map +1 -0
  498. package/build/utils/display/helpers/DisplayHelpers.d.ts +165 -0
  499. package/build/utils/display/helpers/DisplayHelpers.d.ts.map +1 -0
  500. package/build/utils/display/helpers/DisplayHelpers.js +312 -0
  501. package/build/utils/display/helpers/DisplayHelpers.js.map +1 -0
  502. package/build/utils/display/helpers/ScrollView.d.ts +183 -0
  503. package/build/utils/display/helpers/ScrollView.d.ts.map +1 -0
  504. package/build/utils/display/helpers/ScrollView.js +257 -0
  505. package/build/utils/display/helpers/ScrollView.js.map +1 -0
  506. package/build/utils/display/helpers/index.d.ts +11 -0
  507. package/build/utils/display/helpers/index.d.ts.map +1 -0
  508. package/build/utils/display/helpers/index.js +10 -0
  509. package/build/utils/display/helpers/index.js.map +1 -0
  510. package/build/utils/display/index.d.ts +174 -0
  511. package/build/utils/display/index.d.ts.map +1 -0
  512. package/build/utils/display/index.js +185 -0
  513. package/build/utils/display/index.js.map +1 -0
  514. package/build/utils/display/measurer/TextMeasurer.d.ts +160 -0
  515. package/build/utils/display/measurer/TextMeasurer.d.ts.map +1 -0
  516. package/build/utils/display/measurer/TextMeasurer.js +273 -0
  517. package/build/utils/display/measurer/TextMeasurer.js.map +1 -0
  518. package/build/utils/display/measurer/index.d.ts +10 -0
  519. package/build/utils/display/measurer/index.d.ts.map +1 -0
  520. package/build/utils/display/measurer/index.js +11 -0
  521. package/build/utils/display/measurer/index.js.map +1 -0
  522. package/build/utils/display/measurer/script-detection.d.ts +53 -0
  523. package/build/utils/display/measurer/script-detection.d.ts.map +1 -0
  524. package/build/utils/display/measurer/script-detection.js +184 -0
  525. package/build/utils/display/measurer/script-detection.js.map +1 -0
  526. package/build/utils/display/profiles/g1.d.ts +33 -0
  527. package/build/utils/display/profiles/g1.d.ts.map +1 -0
  528. package/build/utils/display/profiles/g1.js +213 -0
  529. package/build/utils/display/profiles/g1.js.map +1 -0
  530. package/build/utils/display/profiles/g2.d.ts +13 -0
  531. package/build/utils/display/profiles/g2.d.ts.map +1 -0
  532. package/build/utils/display/profiles/g2.js +34 -0
  533. package/build/utils/display/profiles/g2.js.map +1 -0
  534. package/build/utils/display/profiles/index.d.ts +12 -0
  535. package/build/utils/display/profiles/index.d.ts.map +1 -0
  536. package/build/utils/display/profiles/index.js +15 -0
  537. package/build/utils/display/profiles/index.js.map +1 -0
  538. package/build/utils/display/profiles/nex.d.ts +10 -0
  539. package/build/utils/display/profiles/nex.d.ts.map +1 -0
  540. package/build/utils/display/profiles/nex.js +150 -0
  541. package/build/utils/display/profiles/nex.js.map +1 -0
  542. package/build/utils/display/profiles/types.d.ts +103 -0
  543. package/build/utils/display/profiles/types.d.ts.map +1 -0
  544. package/build/utils/display/profiles/types.js +2 -0
  545. package/build/utils/display/profiles/types.js.map +1 -0
  546. package/build/utils/display/profiles/z100.d.ts +33 -0
  547. package/build/utils/display/profiles/z100.d.ts.map +1 -0
  548. package/build/utils/display/profiles/z100.js +182 -0
  549. package/build/utils/display/profiles/z100.js.map +1 -0
  550. package/build/utils/display/scene/degrade.d.ts +25 -0
  551. package/build/utils/display/scene/degrade.d.ts.map +1 -0
  552. package/build/utils/display/scene/degrade.js +64 -0
  553. package/build/utils/display/scene/degrade.js.map +1 -0
  554. package/build/utils/display/scene/differ.d.ts +38 -0
  555. package/build/utils/display/scene/differ.d.ts.map +1 -0
  556. package/build/utils/display/scene/differ.js +107 -0
  557. package/build/utils/display/scene/differ.js.map +1 -0
  558. package/build/utils/display/scene/index.d.ts +10 -0
  559. package/build/utils/display/scene/index.d.ts.map +1 -0
  560. package/build/utils/display/scene/index.js +6 -0
  561. package/build/utils/display/scene/index.js.map +1 -0
  562. package/build/utils/display/scene/process.d.ts +35 -0
  563. package/build/utils/display/scene/process.d.ts.map +1 -0
  564. package/build/utils/display/scene/process.js +187 -0
  565. package/build/utils/display/scene/process.js.map +1 -0
  566. package/build/utils/display/scene/store.d.ts +48 -0
  567. package/build/utils/display/scene/store.d.ts.map +1 -0
  568. package/build/utils/display/scene/store.js +0 -0
  569. package/build/utils/display/scene/store.js.map +1 -0
  570. package/build/utils/display/scene/types.d.ts +120 -0
  571. package/build/utils/display/scene/types.d.ts.map +1 -0
  572. package/build/utils/display/scene/types.js +0 -0
  573. package/build/utils/display/scene/types.js.map +1 -0
  574. package/build/utils/display/wrapper/TextWrapper.d.ts +102 -0
  575. package/build/utils/display/wrapper/TextWrapper.d.ts.map +1 -0
  576. package/build/utils/display/wrapper/TextWrapper.js +471 -0
  577. package/build/utils/display/wrapper/TextWrapper.js.map +1 -0
  578. package/build/utils/display/wrapper/index.d.ts +12 -0
  579. package/build/utils/display/wrapper/index.d.ts.map +1 -0
  580. package/build/utils/display/wrapper/index.js +12 -0
  581. package/build/utils/display/wrapper/index.js.map +1 -0
  582. package/build/utils/display/wrapper/types.d.ts +75 -0
  583. package/build/utils/display/wrapper/types.d.ts.map +1 -0
  584. package/build/utils/display/wrapper/types.js +11 -0
  585. package/build/utils/display/wrapper/types.js.map +1 -0
  586. package/build/utils/e2eMetrics.d.ts +6 -0
  587. package/build/utils/e2eMetrics.d.ts.map +1 -0
  588. package/build/utils/e2eMetrics.js +27 -0
  589. package/build/utils/e2eMetrics.js.map +1 -0
  590. package/build/utils/hardware/hardware.d.ts +42 -0
  591. package/build/utils/hardware/hardware.d.ts.map +1 -0
  592. package/build/utils/hardware/hardware.js +127 -0
  593. package/build/utils/hardware/hardware.js.map +1 -0
  594. package/build/utils/hardware/index.d.ts +2 -0
  595. package/build/utils/hardware/index.d.ts.map +1 -0
  596. package/build/utils/hardware/index.js +2 -0
  597. package/build/utils/hardware/index.js.map +1 -0
  598. package/build/utils/miniappGlobals.d.ts +60 -0
  599. package/build/utils/miniappGlobals.d.ts.map +1 -0
  600. package/build/utils/miniappGlobals.js +224 -0
  601. package/build/utils/miniappGlobals.js.map +1 -0
  602. package/build/utils/permissions/MediaLibraryPermissions.d.ts +34 -0
  603. package/build/utils/permissions/MediaLibraryPermissions.d.ts.map +1 -0
  604. package/build/utils/permissions/MediaLibraryPermissions.js +122 -0
  605. package/build/utils/permissions/MediaLibraryPermissions.js.map +1 -0
  606. package/build/utils/permissions/galleryDisplayName.d.ts +8 -0
  607. package/build/utils/permissions/galleryDisplayName.d.ts.map +1 -0
  608. package/build/utils/permissions/galleryDisplayName.js +25 -0
  609. package/build/utils/permissions/galleryDisplayName.js.map +1 -0
  610. package/build/utils/storage/index.d.ts +3 -0
  611. package/build/utils/storage/index.d.ts.map +1 -0
  612. package/build/utils/storage/index.js +3 -0
  613. package/build/utils/storage/index.js.map +1 -0
  614. package/build/utils/storage/storage.d.ts +24 -0
  615. package/build/utils/storage/storage.d.ts.map +1 -0
  616. package/build/utils/storage/storage.js +85 -0
  617. package/build/utils/storage/storage.js.map +1 -0
  618. package/build/utils/storage/zip.d.ts +3 -0
  619. package/build/utils/storage/zip.d.ts.map +1 -0
  620. package/build/utils/storage/zip.js +14 -0
  621. package/build/utils/storage/zip.js.map +1 -0
  622. package/build/utils/timers/index.d.ts +3 -0
  623. package/build/utils/timers/index.d.ts.map +1 -0
  624. package/build/utils/timers/index.js +3 -0
  625. package/build/utils/timers/index.js.map +1 -0
  626. package/build/utils/timers/timers.d.ts +9 -0
  627. package/build/utils/timers/timers.d.ts.map +1 -0
  628. package/build/utils/timers/timers.js +105 -0
  629. package/build/utils/timers/timers.js.map +1 -0
  630. package/package.json +119 -0
  631. package/src/devtools.ts +13 -0
  632. package/src/engine.ts +173 -0
  633. package/src/facades/dev.ts +197 -0
  634. package/src/facades/display.ts +17 -0
  635. package/src/facades/displayMirror.ts +33 -0
  636. package/src/facades/gallery.ts +69 -0
  637. package/src/facades/glasses.ts +206 -0
  638. package/src/facades/glassesSettings.ts +56 -0
  639. package/src/facades/glassesWifi.ts +68 -0
  640. package/src/facades/miniapps.ts +55 -0
  641. package/src/facades/notifications.ts +15 -0
  642. package/src/facades/ota.ts +174 -0
  643. package/src/facades/pairing.ts +329 -0
  644. package/src/facades/permissions.ts +151 -0
  645. package/src/facades/phoneNotifications.ts +50 -0
  646. package/src/facades/reports.ts +185 -0
  647. package/src/facades/session.ts +55 -0
  648. package/src/facades/settings.ts +57 -0
  649. package/src/facades/speech.ts +38 -0
  650. package/src/index.ts +191 -0
  651. package/src/internal.ts +158 -0
  652. package/src/runtime/bootstrap.ts +118 -0
  653. package/src/runtime/config.ts +147 -0
  654. package/src/runtime/streamConfig.ts +34 -0
  655. package/src/services/AppRegistry.ts +1139 -0
  656. package/src/services/AudioCloudUplink.ts +34 -0
  657. package/src/services/AudioPlaybackService.ts +624 -0
  658. package/src/services/AutomaticReportResult.ts +48 -0
  659. package/src/services/BlobStore.ts +746 -0
  660. package/src/services/CaptionsTesterReportService.ts +107 -0
  661. package/src/services/CloudAudioSubscriptionSync.ts +41 -0
  662. package/src/services/CloudClientService.ts +668 -0
  663. package/src/services/CloudTranscriptE2EMetrics.ts +27 -0
  664. package/src/services/ConnectionCoordinator.ts +65 -0
  665. package/src/services/DevServerBridge.ts +332 -0
  666. package/src/services/DeviceEventRouter.ts +238 -0
  667. package/src/services/DeviceStoreHydration.ts +130 -0
  668. package/src/services/DisplayProcessor.ts +775 -0
  669. package/src/services/GlassesReadiness.ts +103 -0
  670. package/src/services/GlassesSettingsSync.ts +134 -0
  671. package/src/services/GlassesStatusProjection.ts +73 -0
  672. package/src/services/HeadingService.ts +98 -0
  673. package/src/services/LocalDisplayManager.ts +703 -0
  674. package/src/services/LocalMiniappRuntime.ts +4038 -0
  675. package/src/services/LocalSttFallbackCoordinator.ts +140 -0
  676. package/src/services/MentraJSCrashController.ts +189 -0
  677. package/src/services/MentraJSCrashloopReportService.ts +66 -0
  678. package/src/services/MentraJSLogPipeline.ts +166 -0
  679. package/src/services/MentraJSRouter.ts +557 -0
  680. package/src/services/MentraUIRouter.ts +244 -0
  681. package/src/services/MicStateCoordinator.ts +94 -0
  682. package/src/services/MiniappEngine.ts +143 -0
  683. package/src/services/MiniappLauncher.ts +340 -0
  684. package/src/services/MiniappRunningRegistry.ts +57 -0
  685. package/src/services/NavigationHandlers.ts +423 -0
  686. package/src/services/NavigationService.ts +731 -0
  687. package/src/services/NotificationsEmitter.ts +48 -0
  688. package/src/services/OfflineSpeechModelService.ts +168 -0
  689. package/src/services/OtaInstallCoordinator.ts +1205 -0
  690. package/src/services/OtaService.ts +83 -0
  691. package/src/services/OtaUpdateCheckService.ts +386 -0
  692. package/src/services/PairingIdentity.ts +154 -0
  693. package/src/services/PhoneLocationService.ts +122 -0
  694. package/src/services/PhoneNotificationsSync.ts +44 -0
  695. package/src/services/PhonePhotoCoordinator.ts +337 -0
  696. package/src/services/PhoneStreamCoordinator.ts +777 -0
  697. package/src/services/PhoneVideoCoordinator.ts +189 -0
  698. package/src/services/STTModelManager.ts +360 -0
  699. package/src/services/SceneRenderer.ts +292 -0
  700. package/src/services/StreamLifecycleController.ts +213 -0
  701. package/src/services/TTSModelManager.ts +466 -0
  702. package/src/services/WebviewBridge.ts +50 -0
  703. package/src/services/asg/GalleryMediaIntegrityReportService.ts +70 -0
  704. package/src/services/asg/asgCameraApi.ts +1204 -0
  705. package/src/services/asg/galleryMediaValidation.ts +183 -0
  706. package/src/services/asg/galleryNotices.ts +60 -0
  707. package/src/services/asg/gallerySettingsService.ts +65 -0
  708. package/src/services/asg/gallerySyncNotifications.ts +236 -0
  709. package/src/services/asg/gallerySyncService.ts +2167 -0
  710. package/src/services/asg/localStorageService.ts +497 -0
  711. package/src/services/asg/mediaProcessingQueue.ts +371 -0
  712. package/src/services/asgOtaVersionUrl.ts +41 -0
  713. package/src/services/blobPaths.ts +86 -0
  714. package/src/services/cloudStreamApi.ts +154 -0
  715. package/src/services/gallerySyncClock.ts +39 -0
  716. package/src/services/glassesClockSync.ts +115 -0
  717. package/src/services/manifestVersionGate.ts +43 -0
  718. package/src/services/mentraUiShim.ts +366 -0
  719. package/src/services/navigation/roadNameResolver.ts +112 -0
  720. package/src/services/navigation/routesApiCodec.ts +69 -0
  721. package/src/services/otaDisplayState.ts +115 -0
  722. package/src/services/otaInstallPolicy.ts +106 -0
  723. package/src/services/otaLegacyMapping.ts +71 -0
  724. package/src/services/slimStreamStatus.ts +28 -0
  725. package/src/stores/apps.ts +614 -0
  726. package/src/stores/bluetoothSettingKeys.ts +36 -0
  727. package/src/stores/cloudClientStatus.ts +37 -0
  728. package/src/stores/connection.ts +69 -0
  729. package/src/stores/core.ts +32 -0
  730. package/src/stores/display.ts +121 -0
  731. package/src/stores/gallerySync.ts +380 -0
  732. package/src/stores/glasses.ts +309 -0
  733. package/src/stores/settings.ts +993 -0
  734. package/src/types/applet.ts +112 -0
  735. package/src/types/asg.ts +51 -0
  736. package/src/types/capabilities/even-realities-g1.ts +67 -0
  737. package/src/types/capabilities/even-realities-g2.ts +88 -0
  738. package/src/types/capabilities/mentra-display.ts +75 -0
  739. package/src/types/capabilities/mentra-live.ts +103 -0
  740. package/src/types/capabilities/none.ts +76 -0
  741. package/src/types/capabilities/simulated-glasses.ts +76 -0
  742. package/src/types/capabilities/vuzix-z100.ts +64 -0
  743. package/src/types/enums.ts +43 -0
  744. package/src/types/hardware.ts +203 -0
  745. package/src/types/index.ts +37 -0
  746. package/src/utils/GlobalEventEmitter.ts +14 -0
  747. package/src/utils/cloudClient/RnUdpAdapter.ts +47 -0
  748. package/src/utils/cloudClient/cloudSecureStore.ts +28 -0
  749. package/src/utils/debouncedPatch.ts +28 -0
  750. package/src/utils/devLogging.ts +140 -0
  751. package/src/utils/devMiniappLaunch.ts +68 -0
  752. package/src/utils/diagnosticContext.ts +155 -0
  753. package/src/utils/display/composer/ColumnComposer.ts +285 -0
  754. package/src/utils/display/composer/index.ts +15 -0
  755. package/src/utils/display/helpers/DisplayHelpers.ts +413 -0
  756. package/src/utils/display/helpers/ScrollView.ts +337 -0
  757. package/src/utils/display/helpers/index.ts +14 -0
  758. package/src/utils/display/index.ts +273 -0
  759. package/src/utils/display/measurer/TextMeasurer.ts +346 -0
  760. package/src/utils/display/measurer/index.ts +21 -0
  761. package/src/utils/display/measurer/script-detection.ts +218 -0
  762. package/src/utils/display/profiles/g1.ts +236 -0
  763. package/src/utils/display/profiles/g2.ts +39 -0
  764. package/src/utils/display/profiles/index.ts +28 -0
  765. package/src/utils/display/profiles/nex.ts +166 -0
  766. package/src/utils/display/profiles/types.ts +132 -0
  767. package/src/utils/display/profiles/z100.ts +198 -0
  768. package/src/utils/display/scene/degrade.ts +80 -0
  769. package/src/utils/display/scene/differ.ts +128 -0
  770. package/src/utils/display/scene/index.ts +21 -0
  771. package/src/utils/display/scene/process.ts +214 -0
  772. package/src/utils/display/scene/store.ts +0 -0
  773. package/src/utils/display/scene/types.ts +0 -0
  774. package/src/utils/display/wrapper/TextWrapper.ts +546 -0
  775. package/src/utils/display/wrapper/index.ts +15 -0
  776. package/src/utils/display/wrapper/types.ts +102 -0
  777. package/src/utils/e2eMetrics.ts +30 -0
  778. package/src/utils/hardware/hardware.ts +166 -0
  779. package/src/utils/hardware/index.ts +1 -0
  780. package/src/utils/miniappGlobals.ts +260 -0
  781. package/src/utils/permissions/MediaLibraryPermissions.ts +130 -0
  782. package/src/utils/permissions/galleryDisplayName.ts +28 -0
  783. package/src/utils/storage/index.ts +2 -0
  784. package/src/utils/storage/storage.ts +101 -0
  785. package/src/utils/storage/zip.ts +13 -0
  786. package/src/utils/timers/index.ts +2 -0
  787. package/src/utils/timers/timers.ts +139 -0
@@ -0,0 +1,533 @@
1
+ import { createAudioPlayer, setAudioModeAsync } from "expo-audio";
2
+ import BluetoothSdk from "@mentra/bluetooth-sdk/internal";
3
+ import { BgTimer } from "../utils/timers";
4
+ const RESTORE_GLASSES_VOLUME_AFTER_PLAYBACK = false;
5
+ class AudioPlaybackService {
6
+ static instance = null;
7
+ // Reuse a single AudioPlayer to avoid AudioTrack exhaustion
8
+ // Creating new ExoPlayer instances per request leads to -12 ENOMEM errors
9
+ player = null;
10
+ currentPlayback = null;
11
+ // Live PCM streams (speaker.createStream), keyed by streamId. The runtime
12
+ // enforces one per app; stopOtherAudio interrupts across apps.
13
+ streams = new Map();
14
+ audioModeConfigured = false;
15
+ // Debounce timer for notifying native that audio stopped
16
+ // Prevents mic toggle flicker when playing back-to-back audio
17
+ // Uses BgTimer to work reliably when app is backgrounded on Android
18
+ audioStopDebounceTimer = null;
19
+ // Original glasses media volume captured before we bump it for A2DP playback.
20
+ glassesVolumeRestoreLevel = null;
21
+ static AUDIO_STOP_DEBOUNCE_MS = 1500;
22
+ static A2DP_TAIL_DRAIN_MS = 900;
23
+ /** If glasses report step volume at or below this, bump to FLOOR before A2DP playback. */
24
+ static GLASSES_VOLUME_LOW_THRESHOLD = 2;
25
+ static GLASSES_VOLUME_FLOOR = 9;
26
+ constructor() { }
27
+ /**
28
+ * Configure audio mode for playback, re-asserting it on EVERY play.
29
+ *
30
+ * This must run before each play — not just once — because other parts of the
31
+ * app put the shared iOS AVAudioSession into a record-oriented category and
32
+ * never restore it. In particular the phone mic (PhoneMic.swift) switches the
33
+ * session to `.playAndRecord` (sometimes `.voiceChat`/earpiece routing) while
34
+ * capturing and only deactivates it on stop, leaving the category sticky. A
35
+ * miniapp like the Recorder records and then immediately plays back through
36
+ * this service; if we kept the old "configure once" guard, playback would land
37
+ * in the leftover `.playAndRecord` session and be inaudible on the phone
38
+ * speaker (the symptom: the progress bar runs but no sound comes out). Calling
39
+ * setAudioModeAsync with no `allowsRecording` maps to category `.playback`,
40
+ * reclaiming the speaker route. `audioModeConfigured` is kept only to gate the
41
+ * one-time log.
42
+ */
43
+ async ensureAudioModeConfigured() {
44
+ try {
45
+ await setAudioModeAsync({
46
+ shouldPlayInBackground: true,
47
+ playsInSilentMode: true,
48
+ interruptionMode: "duckOthers",
49
+ });
50
+ if (!this.audioModeConfigured) {
51
+ this.audioModeConfigured = true;
52
+ console.log("AUDIO: Audio mode configured for playback");
53
+ }
54
+ }
55
+ catch (error) {
56
+ console.error("AUDIO: Failed to configure audio mode:", error);
57
+ // Don't block playback if audio mode config fails
58
+ }
59
+ }
60
+ static getInstance() {
61
+ if (!AudioPlaybackService.instance) {
62
+ AudioPlaybackService.instance = new AudioPlaybackService();
63
+ }
64
+ return AudioPlaybackService.instance;
65
+ }
66
+ /**
67
+ * Ensure we have a reusable player instance
68
+ */
69
+ ensurePlayer() {
70
+ if (!this.player) {
71
+ console.log("AUDIO: Creating reusable AudioPlayer instance");
72
+ this.player = createAudioPlayer(null);
73
+ // Add status listener once - it will handle all playback completions
74
+ this.player.addListener("playbackStatusUpdate", (status) => {
75
+ this.onPlaybackStatusUpdate(status);
76
+ });
77
+ }
78
+ return this.player;
79
+ }
80
+ async getGlassesMediaVolumeWithTiming() {
81
+ const startedAt = Date.now();
82
+ try {
83
+ const result = await BluetoothSdk.getGlassesMediaVolume();
84
+ console.log(`AUDIO: Glasses media volume read completed in ${Date.now() - startedAt}ms`);
85
+ return result;
86
+ }
87
+ catch (error) {
88
+ console.warn(`AUDIO: Glasses media volume read failed after ${Date.now() - startedAt}ms:`, error instanceof Error ? error.message : String(error));
89
+ throw error;
90
+ }
91
+ }
92
+ async setGlassesMediaVolumeWithTiming(level) {
93
+ const startedAt = Date.now();
94
+ try {
95
+ const result = await BluetoothSdk.setGlassesMediaVolume(level);
96
+ console.log(`AUDIO: Glasses media volume set(${level}) completed in ${Date.now() - startedAt}ms`);
97
+ return result;
98
+ }
99
+ catch (error) {
100
+ console.warn(`AUDIO: Glasses media volume set(${level}) failed after ${Date.now() - startedAt}ms:`, error instanceof Error ? error.message : String(error));
101
+ throw error;
102
+ }
103
+ }
104
+ /**
105
+ * Mentra Live: raise glasses media volume over BLE when it is very low so A2DP prompts are audible.
106
+ * Fail-open on unsupported devices, timeouts, or errors.
107
+ */
108
+ async ensureGlassesMediaVolumeForA2dp(playback) {
109
+ if (this.glassesVolumeRestoreLevel !== null) {
110
+ console.log(`AUDIO: Keeping bumped glasses media volume at ${AudioPlaybackService.GLASSES_VOLUME_FLOOR} during ongoing playback`);
111
+ return;
112
+ }
113
+ try {
114
+ const raw = await this.getGlassesMediaVolumeWithTiming();
115
+ const level = Number(raw.level);
116
+ const statusCode = Number(raw.statusCode);
117
+ if (!Number.isFinite(level)) {
118
+ console.log("AUDIO: Received glasses media volume response without numeric level:", JSON.stringify(raw));
119
+ return;
120
+ }
121
+ const k900S = Number.isFinite(statusCode) && statusCode >= 0 ? ` K900_S=${statusCode}` : "";
122
+ console.log(`AUDIO: Glasses media step volume (wearable knob, 0-15 scale): ${level}/15.${k900S}`);
123
+ if (level > AudioPlaybackService.GLASSES_VOLUME_LOW_THRESHOLD) {
124
+ return;
125
+ }
126
+ if (this.currentPlayback !== playback || playback.completed) {
127
+ console.log("AUDIO: Skipping glasses volume bump; playback already ended");
128
+ return;
129
+ }
130
+ console.log(`AUDIO: Raising glasses media volume (was ${level})`);
131
+ await this.setGlassesMediaVolumeWithTiming(AudioPlaybackService.GLASSES_VOLUME_FLOOR);
132
+ if (this.currentPlayback === playback && !playback.completed) {
133
+ this.glassesVolumeRestoreLevel = level;
134
+ }
135
+ else if (RESTORE_GLASSES_VOLUME_AFTER_PLAYBACK) {
136
+ console.log("AUDIO: Restoring glasses volume immediately; playback ended during volume bump");
137
+ await this.setGlassesMediaVolumeWithTiming(level);
138
+ }
139
+ else {
140
+ console.log("AUDIO: Leaving bumped glasses media volume unchanged after playback");
141
+ }
142
+ }
143
+ catch (e) {
144
+ const msg = e instanceof Error ? e.message : String(e);
145
+ console.warn("AUDIO: Skipping glasses volume bump:", msg);
146
+ }
147
+ }
148
+ /**
149
+ * Restore the user's original glasses media step volume after A2DP playback finishes.
150
+ */
151
+ async restoreGlassesMediaVolume() {
152
+ const restoreLevel = this.glassesVolumeRestoreLevel;
153
+ if (restoreLevel === null) {
154
+ return;
155
+ }
156
+ if (!RESTORE_GLASSES_VOLUME_AFTER_PLAYBACK) {
157
+ this.glassesVolumeRestoreLevel = null;
158
+ console.log("AUDIO: Leaving bumped glasses media volume unchanged after playback");
159
+ return;
160
+ }
161
+ try {
162
+ console.log(`AUDIO: Restoring glasses media volume to ${restoreLevel}`);
163
+ await this.setGlassesMediaVolumeWithTiming(restoreLevel);
164
+ }
165
+ catch (e) {
166
+ const msg = e instanceof Error ? e.message : String(e);
167
+ console.warn(`AUDIO: Failed to restore glasses volume to ${restoreLevel}:`, msg);
168
+ }
169
+ finally {
170
+ this.glassesVolumeRestoreLevel = null;
171
+ }
172
+ }
173
+ pauseFinishedPlayerAfterTail(playback) {
174
+ BgTimer.setTimeout(() => {
175
+ if (this.currentPlayback)
176
+ return;
177
+ if (!this.player)
178
+ return;
179
+ try {
180
+ this.player.pause();
181
+ console.log(`AUDIO: Paused finished player for ${playback.requestId} after ${AudioPlaybackService.A2DP_TAIL_DRAIN_MS}ms tail drain`);
182
+ }
183
+ catch (e) {
184
+ console.warn("AUDIO: Error pausing player after tail drain:", e);
185
+ }
186
+ }, AudioPlaybackService.A2DP_TAIL_DRAIN_MS);
187
+ }
188
+ /**
189
+ * Play audio from a URL.
190
+ * Returns a promise that resolves with playback result when audio finishes or errors.
191
+ */
192
+ async play(request, onComplete) {
193
+ const { requestId, audioUrl, appId, volume = 1.0, stopOtherAudio = true } = request;
194
+ console.log(`AUDIO: Play request ${requestId}${appId ? ` from ${appId}` : ""}: ${audioUrl}`);
195
+ try {
196
+ // Ensure audio mode is configured for background playback
197
+ await this.ensureAudioModeConfigured();
198
+ // Stop current playback if any (notify previous callback)
199
+ if (stopOtherAudio && this.currentPlayback && !this.currentPlayback.completed) {
200
+ console.log(`AUDIO: Interrupting current playback for new request`);
201
+ this.interruptCurrentPlayback(true);
202
+ }
203
+ // Live PCM streams count as "other audio" too.
204
+ if (stopOtherAudio) {
205
+ await this.abortAllStreams();
206
+ }
207
+ // Get or create the reusable player
208
+ const player = this.ensurePlayer();
209
+ // Set volume
210
+ player.volume = Math.max(0, Math.min(1, volume));
211
+ // Store the new playback state
212
+ const playback = {
213
+ requestId,
214
+ appId,
215
+ startTime: Date.now(),
216
+ completed: false,
217
+ onComplete,
218
+ };
219
+ this.currentPlayback = playback;
220
+ // Replace the source and play
221
+ // Using replace() reuses the existing ExoPlayer/AudioTrack instead of creating new ones
222
+ player.replace({ uri: audioUrl });
223
+ player.play();
224
+ // Mentra Live volume reads can block up to 5s when the glasses don't
225
+ // answer. Do not put that in front of playback; guard it against late
226
+ // completion so a stale volume response cannot bump after this request is
227
+ // already over.
228
+ void this.ensureGlassesMediaVolumeForA2dp(playback);
229
+ // Notify native that our app is playing audio
230
+ // Used to suspend LC3 mic during audio playback to avoid MCU overload
231
+ // Cancel any pending "stop" notification first (handles back-to-back audio)
232
+ if (this.audioStopDebounceTimer !== null) {
233
+ BgTimer.clearTimeout(this.audioStopDebounceTimer);
234
+ this.audioStopDebounceTimer = null;
235
+ }
236
+ BluetoothSdk.setOwnAppAudioPlaying(true).catch((e) => {
237
+ console.warn("AUDIO: Failed to notify native of audio start:", e);
238
+ });
239
+ console.log(`AUDIO: Started playback for ${requestId}`);
240
+ }
241
+ catch (error) {
242
+ const errorMessage = error instanceof Error ? error.message : "Unknown error loading audio";
243
+ console.error(`AUDIO: Failed to play ${requestId}:`, errorMessage);
244
+ void this.restoreGlassesMediaVolume();
245
+ onComplete(requestId, false, errorMessage, null);
246
+ }
247
+ }
248
+ /**
249
+ * Interrupt current playback and notify its callback
250
+ */
251
+ interruptCurrentPlayback(preserveGlassesMediaVolume = false) {
252
+ if (!this.currentPlayback || this.currentPlayback.completed)
253
+ return;
254
+ const playback = this.currentPlayback;
255
+ playback.completed = true;
256
+ this.currentPlayback = null;
257
+ // Stop the player
258
+ if (this.player) {
259
+ try {
260
+ this.player.pause();
261
+ }
262
+ catch (error) {
263
+ console.error("AUDIO: Error pausing player:", error);
264
+ }
265
+ }
266
+ // Notify native that our app stopped playing audio (debounced)
267
+ this.notifyAudioStopDebounced();
268
+ if (!preserveGlassesMediaVolume) {
269
+ void this.restoreGlassesMediaVolume();
270
+ }
271
+ // Notify that playback was interrupted
272
+ const elapsedMs = Date.now() - playback.startTime;
273
+ playback.onComplete(playback.requestId, true, null, elapsedMs);
274
+ console.log(`AUDIO: Interrupted ${playback.requestId} after ${elapsedMs}ms`);
275
+ }
276
+ /**
277
+ * Handle playback status updates from expo-audio
278
+ */
279
+ onPlaybackStatusUpdate(status) {
280
+ const playback = this.currentPlayback;
281
+ // Guard against callbacks for unknown or completed playbacks
282
+ if (!playback || playback.completed) {
283
+ return;
284
+ }
285
+ // Check if playback finished
286
+ if (status.didJustFinish) {
287
+ const durationMs = (status.duration || 0) * 1000; // expo-audio uses seconds
288
+ console.log(`AUDIO: Playback finished for ${playback.requestId}, duration: ${durationMs}ms`);
289
+ playback.completed = true;
290
+ // ExoPlayer can report finished before an A2DP sink has audibly drained
291
+ // the last buffered audio. Pausing immediately can clip the tail on
292
+ // Mentra Live; defer cleanup unless another playback has started.
293
+ this.pauseFinishedPlayerAfterTail(playback);
294
+ playback.onComplete(playback.requestId, true, null, durationMs);
295
+ this.currentPlayback = null;
296
+ // Notify native that our app stopped playing audio (debounced)
297
+ this.notifyAudioStopDebounced();
298
+ void this.restoreGlassesMediaVolume();
299
+ return;
300
+ }
301
+ // Detect silent playback failures: expo-audio doesn't surface errors to JS,
302
+ // so when ExoPlayer fails to load/play a URL (network error, HTTP 500, etc.),
303
+ // the player state goes to "idle" with nothing loaded and no buffering.
304
+ // We wait 1500ms after play() to avoid false positives during initial load.
305
+ if (status.playbackState === "idle" && !status.isBuffering && !status.isLoaded) {
306
+ const elapsedMs = Date.now() - playback.startTime;
307
+ if (elapsedMs > 1500) {
308
+ console.error(`AUDIO: Playback failed for ${playback.requestId} (player went idle after ${elapsedMs}ms)`);
309
+ playback.completed = true;
310
+ playback.onComplete(playback.requestId, false, "Playback failed (player went idle)", null);
311
+ this.currentPlayback = null;
312
+ this.notifyAudioStopDebounced();
313
+ void this.restoreGlassesMediaVolume();
314
+ }
315
+ }
316
+ }
317
+ /**
318
+ * Notify native that audio stopped, with debouncing to prevent mic toggle flicker
319
+ * when playing back-to-back audio files
320
+ */
321
+ notifyAudioStopDebounced() {
322
+ // Clear any existing timer
323
+ if (this.audioStopDebounceTimer !== null) {
324
+ BgTimer.clearTimeout(this.audioStopDebounceTimer);
325
+ }
326
+ // Set a new timer - if new audio starts within this window, the timer gets cancelled
327
+ // Uses BgTimer to work reliably when app is backgrounded on Android
328
+ this.audioStopDebounceTimer = BgTimer.setTimeout(() => {
329
+ this.audioStopDebounceTimer = null;
330
+ BluetoothSdk.setOwnAppAudioPlaying(false).catch((e) => {
331
+ console.warn("AUDIO: Failed to notify native of audio stop:", e);
332
+ });
333
+ }, AudioPlaybackService.AUDIO_STOP_DEBOUNCE_MS);
334
+ }
335
+ // ── live PCM output streams (miniapp speaker.createStream) ────────────────
336
+ /**
337
+ * Open a live PCM stream session. Chunks are pushed with writeStreamChunk
338
+ * into native streaming audio (AudioTrack on Android, AVAudioEngine on iOS),
339
+ * following the media route such as A2DP to connected glasses.
340
+ */
341
+ async openStream(request) {
342
+ const { streamId, appId, sampleRate, channels, volume = 1.0, stopOtherAudio = true } = request;
343
+ console.log(`AUDIO: Stream open ${streamId} from ${appId}: rate=${sampleRate} ch=${channels}`);
344
+ await this.ensureAudioModeConfigured();
345
+ if (stopOtherAudio) {
346
+ if (this.currentPlayback && !this.currentPlayback.completed) {
347
+ console.log("AUDIO: Interrupting current playback for new stream");
348
+ this.interruptCurrentPlayback(true);
349
+ }
350
+ await this.abortAllStreams(streamId);
351
+ }
352
+ await BluetoothSdk.pcmStreamOpen(streamId, sampleRate, channels, Math.max(0, Math.min(1, volume)));
353
+ const stream = { streamId, appId, startTime: Date.now(), ended: false, onEnded: request.onEnded };
354
+ this.streams.set(streamId, stream);
355
+ // Same LC3-mic-suspend dance as play(): cancel any pending "stopped"
356
+ // notification and mark our app as playing audio.
357
+ if (this.audioStopDebounceTimer !== null) {
358
+ BgTimer.clearTimeout(this.audioStopDebounceTimer);
359
+ this.audioStopDebounceTimer = null;
360
+ }
361
+ BluetoothSdk.setOwnAppAudioPlaying(true).catch((e) => {
362
+ console.warn("AUDIO: Failed to notify native of stream audio start:", e);
363
+ });
364
+ // Guarded against the stream ending mid-read, same as the play() path.
365
+ void this.ensureGlassesMediaVolumeForA2dpStream(stream);
366
+ }
367
+ /**
368
+ * Append base64 PCM to an open stream. Resolves with the host-side backlog
369
+ * in ms; the native write blocks while the backlog is above the
370
+ * backpressure ceiling, so awaited writes self-throttle to realtime.
371
+ */
372
+ async writeStreamChunk(streamId, base64) {
373
+ const stream = this.streams.get(streamId);
374
+ if (!stream || stream.ended) {
375
+ throw new Error(`stream ${streamId} is not open`);
376
+ }
377
+ try {
378
+ return await BluetoothSdk.pcmStreamWrite(streamId, base64);
379
+ }
380
+ catch (error) {
381
+ const message = error instanceof Error ? error.message : String(error);
382
+ this.endStream(stream, false, message, Date.now() - stream.startTime);
383
+ throw error;
384
+ }
385
+ }
386
+ /** Drain the backlog, then finish. Resolves with the total played duration. */
387
+ async closeStream(streamId) {
388
+ const stream = this.streams.get(streamId);
389
+ if (!stream || stream.ended) {
390
+ throw new Error(`stream ${streamId} is not open`);
391
+ }
392
+ try {
393
+ const result = await BluetoothSdk.pcmStreamClose(streamId);
394
+ this.endStream(stream, true, null, result?.durationMs ?? Date.now() - stream.startTime);
395
+ return result ?? {};
396
+ }
397
+ catch (error) {
398
+ const message = error instanceof Error ? error.message : String(error);
399
+ this.endStream(stream, false, message, Date.now() - stream.startTime);
400
+ throw error;
401
+ }
402
+ }
403
+ /** Stop immediately, dropping the backlog. Safe on unknown/ended ids. */
404
+ async abortStream(streamId) {
405
+ const stream = this.streams.get(streamId);
406
+ await BluetoothSdk.pcmStreamAbort(streamId).catch((e) => {
407
+ console.warn(`AUDIO: Stream abort ${streamId} native call failed:`, e);
408
+ });
409
+ if (stream) {
410
+ this.endStream(stream, true, null, Date.now() - stream.startTime);
411
+ }
412
+ }
413
+ /** Abort every active stream (optionally sparing one about to replace them). */
414
+ async abortAllStreams(exceptStreamId) {
415
+ const streamIds = [...this.streams.values()]
416
+ .filter((stream) => stream.streamId !== exceptStreamId)
417
+ .map((stream) => stream.streamId);
418
+ await Promise.all(streamIds.map((streamId) => this.abortStream(streamId)));
419
+ }
420
+ /** Terminal bookkeeping for a stream: dedup, unregister, notify. */
421
+ endStream(stream, success, error, durationMs) {
422
+ if (stream.ended)
423
+ return;
424
+ stream.ended = true;
425
+ this.streams.delete(stream.streamId);
426
+ // Only signal "audio stopped" when nothing else is making noise.
427
+ if (this.streams.size === 0 && (!this.currentPlayback || this.currentPlayback.completed)) {
428
+ this.notifyAudioStopDebounced();
429
+ void this.restoreGlassesMediaVolume();
430
+ }
431
+ stream.onEnded(stream.streamId, success, error, durationMs);
432
+ }
433
+ /** Stream twin of ensureGlassesMediaVolumeForA2dp, guarded by stream.ended. */
434
+ async ensureGlassesMediaVolumeForA2dpStream(stream) {
435
+ if (this.glassesVolumeRestoreLevel !== null)
436
+ return;
437
+ try {
438
+ const raw = await this.getGlassesMediaVolumeWithTiming();
439
+ const level = Number(raw.level);
440
+ if (!Number.isFinite(level) || level > AudioPlaybackService.GLASSES_VOLUME_LOW_THRESHOLD)
441
+ return;
442
+ if (stream.ended)
443
+ return;
444
+ console.log(`AUDIO: Raising glasses media volume for stream (was ${level})`);
445
+ await this.setGlassesMediaVolumeWithTiming(AudioPlaybackService.GLASSES_VOLUME_FLOOR);
446
+ if (!stream.ended) {
447
+ this.glassesVolumeRestoreLevel = level;
448
+ }
449
+ else {
450
+ await this.setGlassesMediaVolumeWithTiming(level);
451
+ }
452
+ }
453
+ catch (e) {
454
+ console.warn("AUDIO: Skipping glasses volume bump for stream:", e instanceof Error ? e.message : String(e));
455
+ }
456
+ }
457
+ /**
458
+ * Stop playback for a specific app.
459
+ * If appId is not provided, stops all playback.
460
+ */
461
+ async stopForApp(appId) {
462
+ // Abort this app's live PCM streams too (miniapp stop/disconnect path).
463
+ const streamIds = [...this.streams.values()]
464
+ .filter((stream) => !appId || stream.appId === appId)
465
+ .map((stream) => stream.streamId);
466
+ await Promise.all(streamIds.map((streamId) => this.abortStream(streamId)));
467
+ if (!this.currentPlayback || this.currentPlayback.completed)
468
+ return;
469
+ if (!appId || this.currentPlayback.appId === appId) {
470
+ console.log(`AUDIO: Stopping playback for app ${appId || "(all)"}`);
471
+ this.interruptCurrentPlayback();
472
+ }
473
+ }
474
+ /**
475
+ * Stop all audio playback
476
+ */
477
+ async stopAll() {
478
+ await this.abortAllStreams();
479
+ if (this.currentPlayback && !this.currentPlayback.completed) {
480
+ console.log("AUDIO: Stopping all playback");
481
+ this.interruptCurrentPlayback();
482
+ }
483
+ }
484
+ /**
485
+ * Check if audio is currently playing
486
+ */
487
+ isPlaying() {
488
+ return (this.currentPlayback !== null && !this.currentPlayback.completed) || this.streams.size > 0;
489
+ }
490
+ /**
491
+ * Get current playback app IDs (all active)
492
+ */
493
+ getActiveAppIds() {
494
+ const appIds = new Set();
495
+ if (this.currentPlayback && !this.currentPlayback.completed && this.currentPlayback.appId) {
496
+ appIds.add(this.currentPlayback.appId);
497
+ }
498
+ for (const stream of this.streams.values())
499
+ appIds.add(stream.appId);
500
+ return [...appIds];
501
+ }
502
+ /**
503
+ * Get number of active playbacks
504
+ */
505
+ getActiveCount() {
506
+ return (this.currentPlayback && !this.currentPlayback.completed ? 1 : 0) + this.streams.size;
507
+ }
508
+ /**
509
+ * Release the player entirely (call when app is shutting down)
510
+ */
511
+ release() {
512
+ void this.abortAllStreams();
513
+ if (this.currentPlayback && !this.currentPlayback.completed) {
514
+ this.interruptCurrentPlayback();
515
+ }
516
+ else {
517
+ void this.restoreGlassesMediaVolume();
518
+ }
519
+ if (this.player) {
520
+ try {
521
+ this.player.remove();
522
+ console.log("AUDIO: Released AudioPlayer");
523
+ }
524
+ catch (error) {
525
+ console.error("AUDIO: Error releasing player:", error);
526
+ }
527
+ this.player = null;
528
+ }
529
+ }
530
+ }
531
+ const audioPlaybackService = AudioPlaybackService.getInstance();
532
+ export default audioPlaybackService;
533
+ //# sourceMappingURL=AudioPlaybackService.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AudioPlaybackService.js","sourceRoot":"","sources":["../../src/services/AudioPlaybackService.ts"],"names":[],"mappings":"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","sourcesContent":["import {createAudioPlayer, AudioPlayer, AudioStatus, setAudioModeAsync} from \"expo-audio\"\nimport BluetoothSdk from \"@mentra/bluetooth-sdk/internal\"\nimport {BgTimer} from \"../utils/timers\"\n\nconst RESTORE_GLASSES_VOLUME_AFTER_PLAYBACK = false\n\ninterface AudioPlayRequest {\n requestId: string\n audioUrl: string\n appId?: string\n volume?: number\n stopOtherAudio?: boolean\n}\n\ninterface PlaybackState {\n requestId: string\n appId?: string\n startTime: number\n completed: boolean // Guard against double callbacks\n onComplete: (requestId: string, success: boolean, error: string | null, duration: number | null) => void\n}\n\n/** Open request for a live PCM output stream (miniapp speaker.createStream). */\nexport interface AudioStreamOpenRequest {\n streamId: string\n appId: string\n /** PCM sample rate in Hz (16000 / 24000 / 48000). */\n sampleRate: number\n /** Channel count. v1 is mono. */\n channels: number\n volume?: number\n stopOtherAudio?: boolean\n /**\n * Called when the stream ends for any reason (drained after close, aborted,\n * interrupted by other audio, or native error).\n */\n onEnded: (streamId: string, success: boolean, error: string | null, durationMs: number | null) => void\n}\n\n/** One live PCM stream session, backed by native streaming audio. */\ninterface StreamState {\n streamId: string\n appId: string\n startTime: number\n ended: boolean // Guard against double onEnded\n onEnded: AudioStreamOpenRequest[\"onEnded\"]\n}\n\nclass AudioPlaybackService {\n private static instance: AudioPlaybackService | null = null\n // Reuse a single AudioPlayer to avoid AudioTrack exhaustion\n // Creating new ExoPlayer instances per request leads to -12 ENOMEM errors\n private player: AudioPlayer | null = null\n private currentPlayback: PlaybackState | null = null\n // Live PCM streams (speaker.createStream), keyed by streamId. The runtime\n // enforces one per app; stopOtherAudio interrupts across apps.\n private streams = new Map<string, StreamState>()\n private audioModeConfigured: boolean = false\n // Debounce timer for notifying native that audio stopped\n // Prevents mic toggle flicker when playing back-to-back audio\n // Uses BgTimer to work reliably when app is backgrounded on Android\n private audioStopDebounceTimer: number | null = null\n // Original glasses media volume captured before we bump it for A2DP playback.\n private glassesVolumeRestoreLevel: number | null = null\n private static readonly AUDIO_STOP_DEBOUNCE_MS = 1500\n private static readonly A2DP_TAIL_DRAIN_MS = 900\n /** If glasses report step volume at or below this, bump to FLOOR before A2DP playback. */\n private static readonly GLASSES_VOLUME_LOW_THRESHOLD = 2\n private static readonly GLASSES_VOLUME_FLOOR = 9\n\n private constructor() {}\n\n /**\n * Configure audio mode for playback, re-asserting it on EVERY play.\n *\n * This must run before each play — not just once — because other parts of the\n * app put the shared iOS AVAudioSession into a record-oriented category and\n * never restore it. In particular the phone mic (PhoneMic.swift) switches the\n * session to `.playAndRecord` (sometimes `.voiceChat`/earpiece routing) while\n * capturing and only deactivates it on stop, leaving the category sticky. A\n * miniapp like the Recorder records and then immediately plays back through\n * this service; if we kept the old \"configure once\" guard, playback would land\n * in the leftover `.playAndRecord` session and be inaudible on the phone\n * speaker (the symptom: the progress bar runs but no sound comes out). Calling\n * setAudioModeAsync with no `allowsRecording` maps to category `.playback`,\n * reclaiming the speaker route. `audioModeConfigured` is kept only to gate the\n * one-time log.\n */\n private async ensureAudioModeConfigured(): Promise<void> {\n try {\n await setAudioModeAsync({\n shouldPlayInBackground: true,\n playsInSilentMode: true,\n interruptionMode: \"duckOthers\",\n })\n if (!this.audioModeConfigured) {\n this.audioModeConfigured = true\n console.log(\"AUDIO: Audio mode configured for playback\")\n }\n } catch (error) {\n console.error(\"AUDIO: Failed to configure audio mode:\", error)\n // Don't block playback if audio mode config fails\n }\n }\n\n public static getInstance(): AudioPlaybackService {\n if (!AudioPlaybackService.instance) {\n AudioPlaybackService.instance = new AudioPlaybackService()\n }\n return AudioPlaybackService.instance\n }\n\n /**\n * Ensure we have a reusable player instance\n */\n private ensurePlayer(): AudioPlayer {\n if (!this.player) {\n console.log(\"AUDIO: Creating reusable AudioPlayer instance\")\n this.player = createAudioPlayer(null)\n\n // Add status listener once - it will handle all playback completions\n this.player.addListener(\"playbackStatusUpdate\", (status: AudioStatus) => {\n this.onPlaybackStatusUpdate(status)\n })\n }\n return this.player\n }\n\n private async getGlassesMediaVolumeWithTiming() {\n const startedAt = Date.now()\n try {\n const result = await BluetoothSdk.getGlassesMediaVolume()\n console.log(`AUDIO: Glasses media volume read completed in ${Date.now() - startedAt}ms`)\n return result\n } catch (error) {\n console.warn(\n `AUDIO: Glasses media volume read failed after ${Date.now() - startedAt}ms:`,\n error instanceof Error ? error.message : String(error),\n )\n throw error\n }\n }\n\n private async setGlassesMediaVolumeWithTiming(level: number) {\n const startedAt = Date.now()\n try {\n const result = await BluetoothSdk.setGlassesMediaVolume(level)\n console.log(`AUDIO: Glasses media volume set(${level}) completed in ${Date.now() - startedAt}ms`)\n return result\n } catch (error) {\n console.warn(\n `AUDIO: Glasses media volume set(${level}) failed after ${Date.now() - startedAt}ms:`,\n error instanceof Error ? error.message : String(error),\n )\n throw error\n }\n }\n\n /**\n * Mentra Live: raise glasses media volume over BLE when it is very low so A2DP prompts are audible.\n * Fail-open on unsupported devices, timeouts, or errors.\n */\n private async ensureGlassesMediaVolumeForA2dp(playback: PlaybackState): Promise<void> {\n if (this.glassesVolumeRestoreLevel !== null) {\n console.log(\n `AUDIO: Keeping bumped glasses media volume at ${AudioPlaybackService.GLASSES_VOLUME_FLOOR} during ongoing playback`,\n )\n return\n }\n\n try {\n const raw = await this.getGlassesMediaVolumeWithTiming()\n const level = Number(raw.level)\n const statusCode = Number(raw.statusCode)\n if (!Number.isFinite(level)) {\n console.log(\"AUDIO: Received glasses media volume response without numeric level:\", JSON.stringify(raw))\n return\n }\n const k900S = Number.isFinite(statusCode) && statusCode >= 0 ? ` K900_S=${statusCode}` : \"\"\n console.log(`AUDIO: Glasses media step volume (wearable knob, 0-15 scale): ${level}/15.${k900S}`)\n if (level > AudioPlaybackService.GLASSES_VOLUME_LOW_THRESHOLD) {\n return\n }\n if (this.currentPlayback !== playback || playback.completed) {\n console.log(\"AUDIO: Skipping glasses volume bump; playback already ended\")\n return\n }\n console.log(`AUDIO: Raising glasses media volume (was ${level})`)\n await this.setGlassesMediaVolumeWithTiming(AudioPlaybackService.GLASSES_VOLUME_FLOOR)\n if (this.currentPlayback === playback && !playback.completed) {\n this.glassesVolumeRestoreLevel = level\n } else if (RESTORE_GLASSES_VOLUME_AFTER_PLAYBACK) {\n console.log(\"AUDIO: Restoring glasses volume immediately; playback ended during volume bump\")\n await this.setGlassesMediaVolumeWithTiming(level)\n } else {\n console.log(\"AUDIO: Leaving bumped glasses media volume unchanged after playback\")\n }\n } catch (e) {\n const msg = e instanceof Error ? e.message : String(e)\n console.warn(\"AUDIO: Skipping glasses volume bump:\", msg)\n }\n }\n\n /**\n * Restore the user's original glasses media step volume after A2DP playback finishes.\n */\n private async restoreGlassesMediaVolume(): Promise<void> {\n const restoreLevel = this.glassesVolumeRestoreLevel\n if (restoreLevel === null) {\n return\n }\n if (!RESTORE_GLASSES_VOLUME_AFTER_PLAYBACK) {\n this.glassesVolumeRestoreLevel = null\n console.log(\"AUDIO: Leaving bumped glasses media volume unchanged after playback\")\n return\n }\n\n try {\n console.log(`AUDIO: Restoring glasses media volume to ${restoreLevel}`)\n await this.setGlassesMediaVolumeWithTiming(restoreLevel)\n } catch (e) {\n const msg = e instanceof Error ? e.message : String(e)\n console.warn(`AUDIO: Failed to restore glasses volume to ${restoreLevel}:`, msg)\n } finally {\n this.glassesVolumeRestoreLevel = null\n }\n }\n\n private pauseFinishedPlayerAfterTail(playback: PlaybackState): void {\n BgTimer.setTimeout(() => {\n if (this.currentPlayback) return\n if (!this.player) return\n try {\n this.player.pause()\n console.log(\n `AUDIO: Paused finished player for ${playback.requestId} after ${AudioPlaybackService.A2DP_TAIL_DRAIN_MS}ms tail drain`,\n )\n } catch (e) {\n console.warn(\"AUDIO: Error pausing player after tail drain:\", e)\n }\n }, AudioPlaybackService.A2DP_TAIL_DRAIN_MS)\n }\n\n /**\n * Play audio from a URL.\n * Returns a promise that resolves with playback result when audio finishes or errors.\n */\n public async play(\n request: AudioPlayRequest,\n onComplete: (requestId: string, success: boolean, error: string | null, duration: number | null) => void,\n ): Promise<void> {\n const {requestId, audioUrl, appId, volume = 1.0, stopOtherAudio = true} = request\n\n console.log(`AUDIO: Play request ${requestId}${appId ? ` from ${appId}` : \"\"}: ${audioUrl}`)\n\n try {\n // Ensure audio mode is configured for background playback\n await this.ensureAudioModeConfigured()\n\n // Stop current playback if any (notify previous callback)\n if (stopOtherAudio && this.currentPlayback && !this.currentPlayback.completed) {\n console.log(`AUDIO: Interrupting current playback for new request`)\n this.interruptCurrentPlayback(true)\n }\n // Live PCM streams count as \"other audio\" too.\n if (stopOtherAudio) {\n await this.abortAllStreams()\n }\n\n // Get or create the reusable player\n const player = this.ensurePlayer()\n\n // Set volume\n player.volume = Math.max(0, Math.min(1, volume))\n\n // Store the new playback state\n const playback: PlaybackState = {\n requestId,\n appId,\n startTime: Date.now(),\n completed: false,\n onComplete,\n }\n this.currentPlayback = playback\n\n // Replace the source and play\n // Using replace() reuses the existing ExoPlayer/AudioTrack instead of creating new ones\n player.replace({uri: audioUrl})\n player.play()\n\n // Mentra Live volume reads can block up to 5s when the glasses don't\n // answer. Do not put that in front of playback; guard it against late\n // completion so a stale volume response cannot bump after this request is\n // already over.\n void this.ensureGlassesMediaVolumeForA2dp(playback)\n\n // Notify native that our app is playing audio\n // Used to suspend LC3 mic during audio playback to avoid MCU overload\n // Cancel any pending \"stop\" notification first (handles back-to-back audio)\n if (this.audioStopDebounceTimer !== null) {\n BgTimer.clearTimeout(this.audioStopDebounceTimer)\n this.audioStopDebounceTimer = null\n }\n BluetoothSdk.setOwnAppAudioPlaying(true).catch((e) => {\n console.warn(\"AUDIO: Failed to notify native of audio start:\", e)\n })\n\n console.log(`AUDIO: Started playback for ${requestId}`)\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : \"Unknown error loading audio\"\n console.error(`AUDIO: Failed to play ${requestId}:`, errorMessage)\n void this.restoreGlassesMediaVolume()\n onComplete(requestId, false, errorMessage, null)\n }\n }\n\n /**\n * Interrupt current playback and notify its callback\n */\n private interruptCurrentPlayback(preserveGlassesMediaVolume: boolean = false): void {\n if (!this.currentPlayback || this.currentPlayback.completed) return\n\n const playback = this.currentPlayback\n playback.completed = true\n this.currentPlayback = null\n\n // Stop the player\n if (this.player) {\n try {\n this.player.pause()\n } catch (error) {\n console.error(\"AUDIO: Error pausing player:\", error)\n }\n }\n\n // Notify native that our app stopped playing audio (debounced)\n this.notifyAudioStopDebounced()\n if (!preserveGlassesMediaVolume) {\n void this.restoreGlassesMediaVolume()\n }\n\n // Notify that playback was interrupted\n const elapsedMs = Date.now() - playback.startTime\n playback.onComplete(playback.requestId, true, null, elapsedMs)\n console.log(`AUDIO: Interrupted ${playback.requestId} after ${elapsedMs}ms`)\n }\n\n /**\n * Handle playback status updates from expo-audio\n */\n private onPlaybackStatusUpdate(status: AudioStatus): void {\n const playback = this.currentPlayback\n\n // Guard against callbacks for unknown or completed playbacks\n if (!playback || playback.completed) {\n return\n }\n\n // Check if playback finished\n if (status.didJustFinish) {\n const durationMs = (status.duration || 0) * 1000 // expo-audio uses seconds\n console.log(`AUDIO: Playback finished for ${playback.requestId}, duration: ${durationMs}ms`)\n playback.completed = true\n\n // ExoPlayer can report finished before an A2DP sink has audibly drained\n // the last buffered audio. Pausing immediately can clip the tail on\n // Mentra Live; defer cleanup unless another playback has started.\n this.pauseFinishedPlayerAfterTail(playback)\n\n playback.onComplete(playback.requestId, true, null, durationMs)\n this.currentPlayback = null\n\n // Notify native that our app stopped playing audio (debounced)\n this.notifyAudioStopDebounced()\n void this.restoreGlassesMediaVolume()\n return\n }\n\n // Detect silent playback failures: expo-audio doesn't surface errors to JS,\n // so when ExoPlayer fails to load/play a URL (network error, HTTP 500, etc.),\n // the player state goes to \"idle\" with nothing loaded and no buffering.\n // We wait 1500ms after play() to avoid false positives during initial load.\n if (status.playbackState === \"idle\" && !status.isBuffering && !status.isLoaded) {\n const elapsedMs = Date.now() - playback.startTime\n if (elapsedMs > 1500) {\n console.error(`AUDIO: Playback failed for ${playback.requestId} (player went idle after ${elapsedMs}ms)`)\n playback.completed = true\n playback.onComplete(playback.requestId, false, \"Playback failed (player went idle)\", null)\n this.currentPlayback = null\n this.notifyAudioStopDebounced()\n void this.restoreGlassesMediaVolume()\n }\n }\n }\n\n /**\n * Notify native that audio stopped, with debouncing to prevent mic toggle flicker\n * when playing back-to-back audio files\n */\n private notifyAudioStopDebounced(): void {\n // Clear any existing timer\n if (this.audioStopDebounceTimer !== null) {\n BgTimer.clearTimeout(this.audioStopDebounceTimer)\n }\n\n // Set a new timer - if new audio starts within this window, the timer gets cancelled\n // Uses BgTimer to work reliably when app is backgrounded on Android\n this.audioStopDebounceTimer = BgTimer.setTimeout(() => {\n this.audioStopDebounceTimer = null\n BluetoothSdk.setOwnAppAudioPlaying(false).catch((e) => {\n console.warn(\"AUDIO: Failed to notify native of audio stop:\", e)\n })\n }, AudioPlaybackService.AUDIO_STOP_DEBOUNCE_MS)\n }\n\n // ── live PCM output streams (miniapp speaker.createStream) ────────────────\n\n /**\n * Open a live PCM stream session. Chunks are pushed with writeStreamChunk\n * into native streaming audio (AudioTrack on Android, AVAudioEngine on iOS),\n * following the media route such as A2DP to connected glasses.\n */\n public async openStream(request: AudioStreamOpenRequest): Promise<void> {\n const {streamId, appId, sampleRate, channels, volume = 1.0, stopOtherAudio = true} = request\n console.log(`AUDIO: Stream open ${streamId} from ${appId}: rate=${sampleRate} ch=${channels}`)\n\n await this.ensureAudioModeConfigured()\n\n if (stopOtherAudio) {\n if (this.currentPlayback && !this.currentPlayback.completed) {\n console.log(\"AUDIO: Interrupting current playback for new stream\")\n this.interruptCurrentPlayback(true)\n }\n await this.abortAllStreams(streamId)\n }\n\n await BluetoothSdk.pcmStreamOpen(streamId, sampleRate, channels, Math.max(0, Math.min(1, volume)))\n\n const stream: StreamState = {streamId, appId, startTime: Date.now(), ended: false, onEnded: request.onEnded}\n this.streams.set(streamId, stream)\n\n // Same LC3-mic-suspend dance as play(): cancel any pending \"stopped\"\n // notification and mark our app as playing audio.\n if (this.audioStopDebounceTimer !== null) {\n BgTimer.clearTimeout(this.audioStopDebounceTimer)\n this.audioStopDebounceTimer = null\n }\n BluetoothSdk.setOwnAppAudioPlaying(true).catch((e) => {\n console.warn(\"AUDIO: Failed to notify native of stream audio start:\", e)\n })\n\n // Guarded against the stream ending mid-read, same as the play() path.\n void this.ensureGlassesMediaVolumeForA2dpStream(stream)\n }\n\n /**\n * Append base64 PCM to an open stream. Resolves with the host-side backlog\n * in ms; the native write blocks while the backlog is above the\n * backpressure ceiling, so awaited writes self-throttle to realtime.\n */\n public async writeStreamChunk(streamId: string, base64: string): Promise<{bufferedMs: number}> {\n const stream = this.streams.get(streamId)\n if (!stream || stream.ended) {\n throw new Error(`stream ${streamId} is not open`)\n }\n try {\n return await BluetoothSdk.pcmStreamWrite(streamId, base64)\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n this.endStream(stream, false, message, Date.now() - stream.startTime)\n throw error\n }\n }\n\n /** Drain the backlog, then finish. Resolves with the total played duration. */\n public async closeStream(streamId: string): Promise<{durationMs?: number}> {\n const stream = this.streams.get(streamId)\n if (!stream || stream.ended) {\n throw new Error(`stream ${streamId} is not open`)\n }\n try {\n const result = await BluetoothSdk.pcmStreamClose(streamId)\n this.endStream(stream, true, null, result?.durationMs ?? Date.now() - stream.startTime)\n return result ?? {}\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n this.endStream(stream, false, message, Date.now() - stream.startTime)\n throw error\n }\n }\n\n /** Stop immediately, dropping the backlog. Safe on unknown/ended ids. */\n public async abortStream(streamId: string): Promise<void> {\n const stream = this.streams.get(streamId)\n await BluetoothSdk.pcmStreamAbort(streamId).catch((e) => {\n console.warn(`AUDIO: Stream abort ${streamId} native call failed:`, e)\n })\n if (stream) {\n this.endStream(stream, true, null, Date.now() - stream.startTime)\n }\n }\n\n /** Abort every active stream (optionally sparing one about to replace them). */\n private async abortAllStreams(exceptStreamId?: string): Promise<void> {\n const streamIds = [...this.streams.values()]\n .filter((stream) => stream.streamId !== exceptStreamId)\n .map((stream) => stream.streamId)\n await Promise.all(streamIds.map((streamId) => this.abortStream(streamId)))\n }\n\n /** Terminal bookkeeping for a stream: dedup, unregister, notify. */\n private endStream(stream: StreamState, success: boolean, error: string | null, durationMs: number | null): void {\n if (stream.ended) return\n stream.ended = true\n this.streams.delete(stream.streamId)\n // Only signal \"audio stopped\" when nothing else is making noise.\n if (this.streams.size === 0 && (!this.currentPlayback || this.currentPlayback.completed)) {\n this.notifyAudioStopDebounced()\n void this.restoreGlassesMediaVolume()\n }\n stream.onEnded(stream.streamId, success, error, durationMs)\n }\n\n /** Stream twin of ensureGlassesMediaVolumeForA2dp, guarded by stream.ended. */\n private async ensureGlassesMediaVolumeForA2dpStream(stream: StreamState): Promise<void> {\n if (this.glassesVolumeRestoreLevel !== null) return\n try {\n const raw = await this.getGlassesMediaVolumeWithTiming()\n const level = Number(raw.level)\n if (!Number.isFinite(level) || level > AudioPlaybackService.GLASSES_VOLUME_LOW_THRESHOLD) return\n if (stream.ended) return\n console.log(`AUDIO: Raising glasses media volume for stream (was ${level})`)\n await this.setGlassesMediaVolumeWithTiming(AudioPlaybackService.GLASSES_VOLUME_FLOOR)\n if (!stream.ended) {\n this.glassesVolumeRestoreLevel = level\n } else {\n await this.setGlassesMediaVolumeWithTiming(level)\n }\n } catch (e) {\n console.warn(\"AUDIO: Skipping glasses volume bump for stream:\", e instanceof Error ? e.message : String(e))\n }\n }\n\n /**\n * Stop playback for a specific app.\n * If appId is not provided, stops all playback.\n */\n public async stopForApp(appId?: string): Promise<void> {\n // Abort this app's live PCM streams too (miniapp stop/disconnect path).\n const streamIds = [...this.streams.values()]\n .filter((stream) => !appId || stream.appId === appId)\n .map((stream) => stream.streamId)\n await Promise.all(streamIds.map((streamId) => this.abortStream(streamId)))\n\n if (!this.currentPlayback || this.currentPlayback.completed) return\n\n if (!appId || this.currentPlayback.appId === appId) {\n console.log(`AUDIO: Stopping playback for app ${appId || \"(all)\"}`)\n this.interruptCurrentPlayback()\n }\n }\n\n /**\n * Stop all audio playback\n */\n public async stopAll(): Promise<void> {\n await this.abortAllStreams()\n if (this.currentPlayback && !this.currentPlayback.completed) {\n console.log(\"AUDIO: Stopping all playback\")\n this.interruptCurrentPlayback()\n }\n }\n\n /**\n * Check if audio is currently playing\n */\n public isPlaying(): boolean {\n return (this.currentPlayback !== null && !this.currentPlayback.completed) || this.streams.size > 0\n }\n\n /**\n * Get current playback app IDs (all active)\n */\n public getActiveAppIds(): string[] {\n const appIds = new Set<string>()\n if (this.currentPlayback && !this.currentPlayback.completed && this.currentPlayback.appId) {\n appIds.add(this.currentPlayback.appId)\n }\n for (const stream of this.streams.values()) appIds.add(stream.appId)\n return [...appIds]\n }\n\n /**\n * Get number of active playbacks\n */\n public getActiveCount(): number {\n return (this.currentPlayback && !this.currentPlayback.completed ? 1 : 0) + this.streams.size\n }\n\n /**\n * Release the player entirely (call when app is shutting down)\n */\n public release(): void {\n void this.abortAllStreams()\n if (this.currentPlayback && !this.currentPlayback.completed) {\n this.interruptCurrentPlayback()\n } else {\n void this.restoreGlassesMediaVolume()\n }\n\n if (this.player) {\n try {\n this.player.remove()\n console.log(\"AUDIO: Released AudioPlayer\")\n } catch (error) {\n console.error(\"AUDIO: Error releasing player:\", error)\n }\n this.player = null\n }\n }\n}\n\nconst audioPlaybackService = AudioPlaybackService.getInstance()\nexport default audioPlaybackService\n"]}
@@ -0,0 +1,20 @@
1
+ import type { ReportSubmitResult } from "../facades/reports";
2
+ export type AutomaticReportSubmissionStatus = {
3
+ status: "filed";
4
+ reportId: string;
5
+ } | {
6
+ status: "skipped";
7
+ reason: string;
8
+ } | {
9
+ status: "failed";
10
+ error: string;
11
+ };
12
+ export declare function toAutomaticReportSubmissionStatus(result: ReportSubmitResult): AutomaticReportSubmissionStatus;
13
+ export declare function automaticReportErrorStatus(error: unknown): Extract<AutomaticReportSubmissionStatus, {
14
+ status: "failed";
15
+ }>;
16
+ export declare function logAutomaticReportSubmissionStatus(logTag: string, result: AutomaticReportSubmissionStatus, ...throttleDetails: unknown[]): void;
17
+ export declare function logUnexpectedAutomaticReportError(logTag: string, error: unknown): Extract<AutomaticReportSubmissionStatus, {
18
+ status: "failed";
19
+ }>;
20
+ //# sourceMappingURL=AutomaticReportResult.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AutomaticReportResult.d.ts","sourceRoot":"","sources":["../../src/services/AutomaticReportResult.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,kBAAkB,EAAC,MAAM,oBAAoB,CAAA;AAE1D,MAAM,MAAM,+BAA+B,GACvC;IAAC,MAAM,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAC,GACnC;IAAC,MAAM,EAAE,SAAS,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAC,GACnC;IAAC,MAAM,EAAE,QAAQ,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAC,CAAA;AAErC,wBAAgB,iCAAiC,CAAC,MAAM,EAAE,kBAAkB,GAAG,+BAA+B,CAQ7G;AAED,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,+BAA+B,EAAE;IAAC,MAAM,EAAE,QAAQ,CAAA;CAAC,CAAC,CAEvH;AAED,wBAAgB,kCAAkC,CAChD,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,+BAA+B,EACvC,GAAG,eAAe,EAAE,OAAO,EAAE,GAC5B,IAAI,CAaN;AAED,wBAAgB,iCAAiC,CAC/C,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,OAAO,GACb,OAAO,CAAC,+BAA+B,EAAE;IAAC,MAAM,EAAE,QAAQ,CAAA;CAAC,CAAC,CAI9D"}