prismcast 1.10.2 → 1.11.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 (693) hide show
  1. package/dist/app.d.ts +6 -3
  2. package/dist/app.d.ts.map +1 -0
  3. package/dist/app.js +140 -86
  4. package/dist/app.js.map +1 -1
  5. package/dist/browser/blockedPage.d.ts +80 -0
  6. package/dist/browser/blockedPage.d.ts.map +1 -0
  7. package/dist/browser/blockedPage.js +209 -0
  8. package/dist/browser/blockedPage.js.map +1 -0
  9. package/dist/browser/browserSupervisor.d.ts +80 -0
  10. package/dist/browser/browserSupervisor.d.ts.map +1 -0
  11. package/dist/browser/browserSupervisor.js +186 -0
  12. package/dist/browser/browserSupervisor.js.map +1 -0
  13. package/dist/browser/cdp.d.ts +1 -0
  14. package/dist/browser/cdp.d.ts.map +1 -0
  15. package/dist/browser/cdp.js +6 -5
  16. package/dist/browser/cdp.js.map +1 -1
  17. package/dist/browser/channelSelection.d.ts +45 -14
  18. package/dist/browser/channelSelection.d.ts.map +1 -0
  19. package/dist/browser/channelSelection.js +81 -18
  20. package/dist/browser/channelSelection.js.map +1 -1
  21. package/dist/browser/consent.d.ts +152 -0
  22. package/dist/browser/consent.d.ts.map +1 -0
  23. package/dist/browser/consent.js +418 -0
  24. package/dist/browser/consent.js.map +1 -0
  25. package/dist/browser/display.d.ts +1 -0
  26. package/dist/browser/display.d.ts.map +1 -0
  27. package/dist/browser/hlsPlaylistObserver.d.ts +55 -0
  28. package/dist/browser/hlsPlaylistObserver.d.ts.map +1 -0
  29. package/dist/browser/hlsPlaylistObserver.js +132 -0
  30. package/dist/browser/hlsPlaylistObserver.js.map +1 -0
  31. package/dist/browser/index.d.ts +67 -40
  32. package/dist/browser/index.d.ts.map +1 -0
  33. package/dist/browser/index.js +508 -300
  34. package/dist/browser/index.js.map +1 -1
  35. package/dist/browser/launchGovernor.d.ts +89 -0
  36. package/dist/browser/launchGovernor.d.ts.map +1 -0
  37. package/dist/browser/launchGovernor.js +96 -0
  38. package/dist/browser/launchGovernor.js.map +1 -0
  39. package/dist/browser/login.d.ts +10 -2
  40. package/dist/browser/login.d.ts.map +1 -0
  41. package/dist/browser/login.js +36 -5
  42. package/dist/browser/login.js.map +1 -1
  43. package/dist/browser/manifestInterceptor.d.ts +102 -49
  44. package/dist/browser/manifestInterceptor.d.ts.map +1 -0
  45. package/dist/browser/manifestInterceptor.js +219 -237
  46. package/dist/browser/manifestInterceptor.js.map +1 -1
  47. package/dist/browser/pageStaleness.d.ts +30 -0
  48. package/dist/browser/pageStaleness.d.ts.map +1 -0
  49. package/dist/browser/pageStaleness.js +76 -0
  50. package/dist/browser/pageStaleness.js.map +1 -0
  51. package/dist/browser/precaching.d.ts +95 -3
  52. package/dist/browser/precaching.d.ts.map +1 -0
  53. package/dist/browser/precaching.js +499 -65
  54. package/dist/browser/precaching.js.map +1 -1
  55. package/dist/browser/tabNetworkObserver.d.ts +49 -0
  56. package/dist/browser/tabNetworkObserver.d.ts.map +1 -0
  57. package/dist/browser/tabNetworkObserver.js +144 -0
  58. package/dist/browser/tabNetworkObserver.js.map +1 -0
  59. package/dist/browser/tuning/cache.d.ts +61 -0
  60. package/dist/browser/tuning/cache.d.ts.map +1 -0
  61. package/dist/browser/tuning/cache.js +62 -0
  62. package/dist/browser/tuning/cache.js.map +1 -0
  63. package/dist/browser/tuning/comcastPolymer.d.ts +3 -2
  64. package/dist/browser/tuning/comcastPolymer.d.ts.map +1 -0
  65. package/dist/browser/tuning/comcastPolymer.js +79 -102
  66. package/dist/browser/tuning/comcastPolymer.js.map +1 -1
  67. package/dist/browser/tuning/cox.d.ts +1 -0
  68. package/dist/browser/tuning/cox.d.ts.map +1 -0
  69. package/dist/browser/tuning/directv.d.ts +1 -0
  70. package/dist/browser/tuning/directv.d.ts.map +1 -0
  71. package/dist/browser/tuning/directv.js +52 -46
  72. package/dist/browser/tuning/directv.js.map +1 -1
  73. package/dist/browser/tuning/fox.d.ts +1 -0
  74. package/dist/browser/tuning/fox.d.ts.map +1 -0
  75. package/dist/browser/tuning/fox.js +13 -12
  76. package/dist/browser/tuning/fox.js.map +1 -1
  77. package/dist/browser/tuning/gridSearch.d.ts +68 -0
  78. package/dist/browser/tuning/gridSearch.d.ts.map +1 -0
  79. package/dist/browser/tuning/gridSearch.js +85 -0
  80. package/dist/browser/tuning/gridSearch.js.map +1 -0
  81. package/dist/browser/tuning/hbo.d.ts +1 -0
  82. package/dist/browser/tuning/hbo.d.ts.map +1 -0
  83. package/dist/browser/tuning/hbo.js +73 -45
  84. package/dist/browser/tuning/hbo.js.map +1 -1
  85. package/dist/browser/tuning/hulu.d.ts +1 -0
  86. package/dist/browser/tuning/hulu.d.ts.map +1 -0
  87. package/dist/browser/tuning/hulu.js +128 -173
  88. package/dist/browser/tuning/hulu.js.map +1 -1
  89. package/dist/browser/tuning/shared.d.ts +75 -5
  90. package/dist/browser/tuning/shared.d.ts.map +1 -0
  91. package/dist/browser/tuning/shared.js +216 -6
  92. package/dist/browser/tuning/shared.js.map +1 -1
  93. package/dist/browser/tuning/sling.d.ts +1 -0
  94. package/dist/browser/tuning/sling.d.ts.map +1 -0
  95. package/dist/browser/tuning/sling.js +105 -126
  96. package/dist/browser/tuning/sling.js.map +1 -1
  97. package/dist/browser/tuning/spectrum.d.ts +1 -0
  98. package/dist/browser/tuning/spectrum.d.ts.map +1 -0
  99. package/dist/browser/tuning/spectrum.js +80 -125
  100. package/dist/browser/tuning/spectrum.js.map +1 -1
  101. package/dist/browser/tuning/thumbnailRow.d.ts +1 -0
  102. package/dist/browser/tuning/thumbnailRow.d.ts.map +1 -0
  103. package/dist/browser/tuning/thumbnailRow.js +8 -2
  104. package/dist/browser/tuning/thumbnailRow.js.map +1 -1
  105. package/dist/browser/tuning/tileClick.d.ts +1 -0
  106. package/dist/browser/tuning/tileClick.d.ts.map +1 -0
  107. package/dist/browser/tuning/tileClick.js +3 -2
  108. package/dist/browser/tuning/tileClick.js.map +1 -1
  109. package/dist/browser/tuning/xfinity.d.ts +1 -0
  110. package/dist/browser/tuning/xfinity.d.ts.map +1 -0
  111. package/dist/browser/tuning/youtubeTv.d.ts +1 -0
  112. package/dist/browser/tuning/youtubeTv.d.ts.map +1 -0
  113. package/dist/browser/tuning/youtubeTv.js +74 -127
  114. package/dist/browser/tuning/youtubeTv.js.map +1 -1
  115. package/dist/browser/video.d.ts +54 -14
  116. package/dist/browser/video.d.ts.map +1 -0
  117. package/dist/browser/video.js +296 -138
  118. package/dist/browser/video.js.map +1 -1
  119. package/dist/channels/index.d.ts +1 -0
  120. package/dist/channels/index.d.ts.map +1 -0
  121. package/dist/channels/index.js +12 -9
  122. package/dist/channels/index.js.map +1 -1
  123. package/dist/config/channelForm.d.ts +15 -1
  124. package/dist/config/channelForm.d.ts.map +1 -0
  125. package/dist/config/channelForm.js +28 -12
  126. package/dist/config/channelForm.js.map +1 -1
  127. package/dist/config/consistencyProbe.d.ts +1 -0
  128. package/dist/config/consistencyProbe.d.ts.map +1 -0
  129. package/dist/config/consistencyProbe.js +27 -21
  130. package/dist/config/consistencyProbe.js.map +1 -1
  131. package/dist/config/health.d.ts +41 -8
  132. package/dist/config/health.d.ts.map +1 -0
  133. package/dist/config/health.js +189 -38
  134. package/dist/config/health.js.map +1 -1
  135. package/dist/config/index.d.ts +55 -3
  136. package/dist/config/index.d.ts.map +1 -0
  137. package/dist/config/index.js +320 -69
  138. package/dist/config/index.js.map +1 -1
  139. package/dist/config/paths.d.ts +10 -9
  140. package/dist/config/paths.d.ts.map +1 -0
  141. package/dist/config/paths.js +11 -11
  142. package/dist/config/paths.js.map +1 -1
  143. package/dist/config/persistence.context.d.ts +1 -0
  144. package/dist/config/persistence.context.d.ts.map +1 -0
  145. package/dist/config/persistence.d.ts +13 -10
  146. package/dist/config/persistence.d.ts.map +1 -0
  147. package/dist/config/persistence.js +40 -21
  148. package/dist/config/persistence.js.map +1 -1
  149. package/dist/config/presets.d.ts +1 -0
  150. package/dist/config/presets.d.ts.map +1 -0
  151. package/dist/config/profiles.d.ts +22 -15
  152. package/dist/config/profiles.d.ts.map +1 -0
  153. package/dist/config/profiles.js +81 -47
  154. package/dist/config/profiles.js.map +1 -1
  155. package/dist/config/providerLineups.d.ts +47 -0
  156. package/dist/config/providerLineups.d.ts.map +1 -0
  157. package/dist/config/providerLineups.js +137 -0
  158. package/dist/config/providerLineups.js.map +1 -0
  159. package/dist/config/reactivity.d.ts +84 -0
  160. package/dist/config/reactivity.d.ts.map +1 -0
  161. package/dist/config/reactivity.js +226 -0
  162. package/dist/config/reactivity.js.map +1 -0
  163. package/dist/config/servicePacks.d.ts +18 -2
  164. package/dist/config/servicePacks.d.ts.map +1 -0
  165. package/dist/config/servicePacks.js +53 -11
  166. package/dist/config/servicePacks.js.map +1 -1
  167. package/dist/config/services.d.ts +21 -15
  168. package/dist/config/services.d.ts.map +1 -0
  169. package/dist/config/services.js +35 -24
  170. package/dist/config/services.js.map +1 -1
  171. package/dist/config/sites.d.ts +6 -4
  172. package/dist/config/sites.d.ts.map +1 -0
  173. package/dist/config/sites.js +15 -11
  174. package/dist/config/sites.js.map +1 -1
  175. package/dist/config/userChannels.d.ts +129 -30
  176. package/dist/config/userChannels.d.ts.map +1 -0
  177. package/dist/config/userChannels.js +333 -68
  178. package/dist/config/userChannels.js.map +1 -1
  179. package/dist/config/userConfig.d.ts +14 -9
  180. package/dist/config/userConfig.d.ts.map +1 -0
  181. package/dist/config/userConfig.js +87 -25
  182. package/dist/config/userConfig.js.map +1 -1
  183. package/dist/config/userProfiles.d.ts +10 -6
  184. package/dist/config/userProfiles.d.ts.map +1 -0
  185. package/dist/config/userProfiles.js +64 -39
  186. package/dist/config/userProfiles.js.map +1 -1
  187. package/dist/hdhr/channelMap.d.ts +1 -0
  188. package/dist/hdhr/channelMap.d.ts.map +1 -0
  189. package/dist/hdhr/deviceId.d.ts +1 -0
  190. package/dist/hdhr/deviceId.d.ts.map +1 -0
  191. package/dist/hdhr/discover.d.ts +1 -0
  192. package/dist/hdhr/discover.d.ts.map +1 -0
  193. package/dist/hdhr/discover.js +48 -47
  194. package/dist/hdhr/discover.js.map +1 -1
  195. package/dist/hdhr/getHandlers.d.ts +29 -0
  196. package/dist/hdhr/getHandlers.d.ts.map +1 -0
  197. package/dist/hdhr/getHandlers.js +196 -0
  198. package/dist/hdhr/getHandlers.js.map +1 -0
  199. package/dist/hdhr/identity.d.ts +36 -0
  200. package/dist/hdhr/identity.d.ts.map +1 -0
  201. package/dist/hdhr/identity.js +51 -0
  202. package/dist/hdhr/identity.js.map +1 -0
  203. package/dist/hdhr/index.d.ts +22 -4
  204. package/dist/hdhr/index.d.ts.map +1 -0
  205. package/dist/hdhr/index.js +229 -54
  206. package/dist/hdhr/index.js.map +1 -1
  207. package/dist/hdhr/protocol.d.ts +75 -0
  208. package/dist/hdhr/protocol.d.ts.map +1 -0
  209. package/dist/hdhr/protocol.js +264 -0
  210. package/dist/hdhr/protocol.js.map +1 -0
  211. package/dist/hdhr/tunerState.d.ts +24 -0
  212. package/dist/hdhr/tunerState.d.ts.map +1 -0
  213. package/dist/hdhr/tunerState.js +67 -0
  214. package/dist/hdhr/tunerState.js.map +1 -0
  215. package/dist/hdhr/udp.d.ts +43 -0
  216. package/dist/hdhr/udp.d.ts.map +1 -0
  217. package/dist/hdhr/udp.js +277 -0
  218. package/dist/hdhr/udp.js.map +1 -0
  219. package/dist/identity.d.ts +1 -0
  220. package/dist/identity.d.ts.map +1 -0
  221. package/dist/identity.js +13 -11
  222. package/dist/identity.js.map +1 -1
  223. package/dist/index.d.ts +1 -0
  224. package/dist/index.d.ts.map +1 -0
  225. package/dist/index.js +11 -12
  226. package/dist/index.js.map +1 -1
  227. package/dist/native/codecInference.d.ts +1 -0
  228. package/dist/native/codecInference.d.ts.map +1 -0
  229. package/dist/native/codecInference.js +50 -5
  230. package/dist/native/codecInference.js.map +1 -1
  231. package/dist/native/decrypt.d.ts +6 -2
  232. package/dist/native/decrypt.d.ts.map +1 -0
  233. package/dist/native/decrypt.js +15 -8
  234. package/dist/native/decrypt.js.map +1 -1
  235. package/dist/native/index.d.ts +40 -17
  236. package/dist/native/index.d.ts.map +1 -0
  237. package/dist/native/index.js +281 -120
  238. package/dist/native/index.js.map +1 -1
  239. package/dist/native/probe.d.ts +114 -18
  240. package/dist/native/probe.d.ts.map +1 -0
  241. package/dist/native/probe.js +452 -115
  242. package/dist/native/probe.js.map +1 -1
  243. package/dist/native/proxy.d.ts +57 -5
  244. package/dist/native/proxy.d.ts.map +1 -0
  245. package/dist/native/proxy.js +604 -170
  246. package/dist/native/proxy.js.map +1 -1
  247. package/dist/native/tokenExpiry.d.ts +1 -0
  248. package/dist/native/tokenExpiry.d.ts.map +1 -0
  249. package/dist/native/tokenExpiry.js +1 -1
  250. package/dist/routes/assets.d.ts +1 -0
  251. package/dist/routes/assets.d.ts.map +1 -0
  252. package/dist/routes/assets.js +4 -2
  253. package/dist/routes/assets.js.map +1 -1
  254. package/dist/routes/auth.d.ts +1 -0
  255. package/dist/routes/auth.d.ts.map +1 -0
  256. package/dist/routes/auth.js +0 -1
  257. package/dist/routes/auth.js.map +1 -1
  258. package/dist/routes/cdp.d.ts +5 -5
  259. package/dist/routes/cdp.d.ts.map +1 -0
  260. package/dist/routes/cdp.js +59 -20
  261. package/dist/routes/cdp.js.map +1 -1
  262. package/dist/routes/channels.d.ts +1 -0
  263. package/dist/routes/channels.d.ts.map +1 -0
  264. package/dist/routes/channels.js +2 -1
  265. package/dist/routes/channels.js.map +1 -1
  266. package/dist/routes/clientActions.d.ts +98 -0
  267. package/dist/routes/clientActions.d.ts.map +1 -0
  268. package/dist/routes/clientActions.js +113 -0
  269. package/dist/routes/clientActions.js.map +1 -0
  270. package/dist/routes/components.d.ts +5 -3
  271. package/dist/routes/components.d.ts.map +1 -0
  272. package/dist/routes/components.js +36 -39
  273. package/dist/routes/components.js.map +1 -1
  274. package/dist/routes/config/channels/endpoints/browse.d.ts +1 -0
  275. package/dist/routes/config/channels/endpoints/browse.d.ts.map +1 -0
  276. package/dist/routes/config/channels/endpoints/browse.js +23 -10
  277. package/dist/routes/config/channels/endpoints/browse.js.map +1 -1
  278. package/dist/routes/config/channels/endpoints/bulk.d.ts +1 -0
  279. package/dist/routes/config/channels/endpoints/bulk.d.ts.map +1 -0
  280. package/dist/routes/config/channels/endpoints/bulk.js +5 -3
  281. package/dist/routes/config/channels/endpoints/bulk.js.map +1 -1
  282. package/dist/routes/config/channels/endpoints/crud.d.ts +1 -0
  283. package/dist/routes/config/channels/endpoints/crud.d.ts.map +1 -0
  284. package/dist/routes/config/channels/endpoints/crud.js +85 -93
  285. package/dist/routes/config/channels/endpoints/crud.js.map +1 -1
  286. package/dist/routes/config/channels/endpoints/importExport.d.ts +1 -0
  287. package/dist/routes/config/channels/endpoints/importExport.d.ts.map +1 -0
  288. package/dist/routes/config/channels/endpoints/importExport.js +6 -3
  289. package/dist/routes/config/channels/endpoints/importExport.js.map +1 -1
  290. package/dist/routes/config/channels/endpoints/predefined.d.ts +1 -0
  291. package/dist/routes/config/channels/endpoints/predefined.d.ts.map +1 -0
  292. package/dist/routes/config/channels/endpoints/prefs.d.ts +1 -0
  293. package/dist/routes/config/channels/endpoints/prefs.d.ts.map +1 -0
  294. package/dist/routes/config/channels/endpoints/prefs.js +2 -1
  295. package/dist/routes/config/channels/endpoints/prefs.js.map +1 -1
  296. package/dist/routes/config/channels/endpoints/service.d.ts +2 -1
  297. package/dist/routes/config/channels/endpoints/service.d.ts.map +1 -0
  298. package/dist/routes/config/channels/endpoints/service.js +3 -1
  299. package/dist/routes/config/channels/endpoints/service.js.map +1 -1
  300. package/dist/routes/config/channels/endpoints/tags.d.ts +1 -0
  301. package/dist/routes/config/channels/endpoints/tags.d.ts.map +1 -0
  302. package/dist/routes/config/channels/endpoints/tags.js +13 -7
  303. package/dist/routes/config/channels/endpoints/tags.js.map +1 -1
  304. package/dist/routes/config/channels/healthBridge.d.ts +24 -0
  305. package/dist/routes/config/channels/healthBridge.d.ts.map +1 -0
  306. package/dist/routes/config/channels/healthBridge.js +71 -0
  307. package/dist/routes/config/channels/healthBridge.js.map +1 -0
  308. package/dist/routes/config/channels/http/handler.d.ts +1 -0
  309. package/dist/routes/config/channels/http/handler.d.ts.map +1 -0
  310. package/dist/routes/config/channels/http/playlistHint.d.ts +2 -1
  311. package/dist/routes/config/channels/http/playlistHint.d.ts.map +1 -0
  312. package/dist/routes/config/channels/http/playlistHint.js +16 -2
  313. package/dist/routes/config/channels/http/playlistHint.js.map +1 -1
  314. package/dist/routes/config/channels/http/serviceWarning.d.ts +4 -2
  315. package/dist/routes/config/channels/http/serviceWarning.d.ts.map +1 -0
  316. package/dist/routes/config/channels/http/serviceWarning.js +3 -2
  317. package/dist/routes/config/channels/http/serviceWarning.js.map +1 -1
  318. package/dist/routes/config/channels/index.d.ts +1 -0
  319. package/dist/routes/config/channels/index.d.ts.map +1 -0
  320. package/dist/routes/config/channels/setup.d.ts +1 -0
  321. package/dist/routes/config/channels/setup.d.ts.map +1 -0
  322. package/dist/routes/config/channels/table.d.ts +3 -3
  323. package/dist/routes/config/channels/table.d.ts.map +1 -0
  324. package/dist/routes/config/channels/table.js +148 -107
  325. package/dist/routes/config/channels/table.js.map +1 -1
  326. package/dist/routes/config/http/envelope.d.ts +1 -0
  327. package/dist/routes/config/http/envelope.d.ts.map +1 -0
  328. package/dist/routes/config/index.d.ts +35 -3
  329. package/dist/routes/config/index.d.ts.map +1 -0
  330. package/dist/routes/config/index.js +51 -2
  331. package/dist/routes/config/index.js.map +1 -1
  332. package/dist/routes/config/services.d.ts +5 -4
  333. package/dist/routes/config/services.d.ts.map +1 -0
  334. package/dist/routes/config/services.js +57 -43
  335. package/dist/routes/config/services.js.map +1 -1
  336. package/dist/routes/config/settings.d.ts +1 -0
  337. package/dist/routes/config/settings.d.ts.map +1 -0
  338. package/dist/routes/config/settings.js +98 -49
  339. package/dist/routes/config/settings.js.map +1 -1
  340. package/dist/routes/debug.d.ts +1 -0
  341. package/dist/routes/debug.d.ts.map +1 -0
  342. package/dist/routes/debug.js +277 -139
  343. package/dist/routes/debug.js.map +1 -1
  344. package/dist/routes/health.d.ts +39 -1
  345. package/dist/routes/health.d.ts.map +1 -0
  346. package/dist/routes/health.js +33 -27
  347. package/dist/routes/health.js.map +1 -1
  348. package/dist/routes/hls.d.ts +1 -0
  349. package/dist/routes/hls.d.ts.map +1 -0
  350. package/dist/routes/icons.d.ts +1 -0
  351. package/dist/routes/icons.d.ts.map +1 -0
  352. package/dist/routes/icons.js +1 -1
  353. package/dist/routes/index.d.ts +1 -0
  354. package/dist/routes/index.d.ts.map +1 -0
  355. package/dist/routes/logs.d.ts +1 -0
  356. package/dist/routes/logs.d.ts.map +1 -0
  357. package/dist/routes/logs.js +14 -4
  358. package/dist/routes/logs.js.map +1 -1
  359. package/dist/routes/mpegts.d.ts +1 -0
  360. package/dist/routes/mpegts.d.ts.map +1 -0
  361. package/dist/routes/play.d.ts +1 -0
  362. package/dist/routes/play.d.ts.map +1 -0
  363. package/dist/routes/playlist.d.ts +1 -0
  364. package/dist/routes/playlist.d.ts.map +1 -0
  365. package/dist/routes/playlist.js +7 -2
  366. package/dist/routes/playlist.js.map +1 -1
  367. package/dist/routes/root/content.d.ts +8 -5
  368. package/dist/routes/root/content.d.ts.map +1 -0
  369. package/dist/routes/root/content.js +29 -26
  370. package/dist/routes/root/content.js.map +1 -1
  371. package/dist/routes/root/index.d.ts +2 -1
  372. package/dist/routes/root/index.d.ts.map +1 -0
  373. package/dist/routes/root/index.js +26 -21
  374. package/dist/routes/root/index.js.map +1 -1
  375. package/dist/routes/root/scripts/channels.d.ts +6 -0
  376. package/dist/routes/root/scripts/channels.d.ts.map +1 -0
  377. package/dist/routes/root/scripts/channels.js +197 -118
  378. package/dist/routes/root/scripts/channels.js.map +1 -1
  379. package/dist/routes/root/scripts/clientEscape.d.ts +22 -0
  380. package/dist/routes/root/scripts/clientEscape.d.ts.map +1 -0
  381. package/dist/routes/root/scripts/clientEscape.js +41 -0
  382. package/dist/routes/root/scripts/clientEscape.js.map +1 -0
  383. package/dist/routes/root/scripts/clientUrl.d.ts +23 -0
  384. package/dist/routes/root/scripts/clientUrl.d.ts.map +1 -0
  385. package/dist/routes/root/scripts/clientUrl.js +44 -0
  386. package/dist/routes/root/scripts/clientUrl.js.map +1 -0
  387. package/dist/routes/root/scripts/config.d.ts +6 -0
  388. package/dist/routes/root/scripts/config.d.ts.map +1 -0
  389. package/dist/routes/root/scripts/config.js +110 -24
  390. package/dist/routes/root/scripts/config.js.map +1 -1
  391. package/dist/routes/root/scripts/index.d.ts +1 -0
  392. package/dist/routes/root/scripts/index.d.ts.map +1 -0
  393. package/dist/routes/root/scripts/shared.d.ts +1 -0
  394. package/dist/routes/root/scripts/shared.d.ts.map +1 -0
  395. package/dist/routes/root/scripts/shared.js +112 -26
  396. package/dist/routes/root/scripts/shared.js.map +1 -1
  397. package/dist/routes/root/scripts/status.d.ts +1 -0
  398. package/dist/routes/root/scripts/status.d.ts.map +1 -0
  399. package/dist/routes/root/scripts/status.handlers.d.ts +23 -33
  400. package/dist/routes/root/scripts/status.handlers.d.ts.map +1 -0
  401. package/dist/routes/root/scripts/status.handlers.js +46 -92
  402. package/dist/routes/root/scripts/status.handlers.js.map +1 -1
  403. package/dist/routes/root/scripts/status.js +21 -8
  404. package/dist/routes/root/scripts/status.js.map +1 -1
  405. package/dist/routes/root/styles.d.ts +1 -0
  406. package/dist/routes/root/styles.d.ts.map +1 -0
  407. package/dist/routes/root/styles.js +7 -4
  408. package/dist/routes/root/styles.js.map +1 -1
  409. package/dist/routes/services.d.ts +13 -1
  410. package/dist/routes/services.d.ts.map +1 -0
  411. package/dist/routes/services.js +81 -68
  412. package/dist/routes/services.js.map +1 -1
  413. package/dist/routes/sse.d.ts +1 -0
  414. package/dist/routes/sse.d.ts.map +1 -0
  415. package/dist/routes/sse.js +1 -1
  416. package/dist/routes/sse.js.map +1 -1
  417. package/dist/routes/streams.d.ts +2 -1
  418. package/dist/routes/streams.d.ts.map +1 -0
  419. package/dist/routes/streams.js +6 -4
  420. package/dist/routes/streams.js.map +1 -1
  421. package/dist/routes/theme.d.ts +3 -2
  422. package/dist/routes/theme.d.ts.map +1 -0
  423. package/dist/routes/theme.js +6 -5
  424. package/dist/routes/theme.js.map +1 -1
  425. package/dist/routes/ui.d.ts +3 -1
  426. package/dist/routes/ui.d.ts.map +1 -0
  427. package/dist/routes/ui.js +16 -4
  428. package/dist/routes/ui.js.map +1 -1
  429. package/dist/routes/upgrade.d.ts +1 -0
  430. package/dist/routes/upgrade.d.ts.map +1 -0
  431. package/dist/routes/upgrade.js +6 -2
  432. package/dist/routes/upgrade.js.map +1 -1
  433. package/dist/service/commands.context.d.ts +1 -0
  434. package/dist/service/commands.context.d.ts.map +1 -0
  435. package/dist/service/commands.context.js +4 -3
  436. package/dist/service/commands.context.js.map +1 -1
  437. package/dist/service/commands.d.ts +1 -0
  438. package/dist/service/commands.d.ts.map +1 -0
  439. package/dist/service/commands.js +10 -13
  440. package/dist/service/commands.js.map +1 -1
  441. package/dist/service/generators.context.d.ts +1 -0
  442. package/dist/service/generators.context.d.ts.map +1 -0
  443. package/dist/service/generators.context.js +1 -1
  444. package/dist/service/generators.context.js.map +1 -1
  445. package/dist/service/generators.d.ts +4 -3
  446. package/dist/service/generators.d.ts.map +1 -0
  447. package/dist/service/generators.js +111 -31
  448. package/dist/service/generators.js.map +1 -1
  449. package/dist/service/index.d.ts +1 -0
  450. package/dist/service/index.d.ts.map +1 -0
  451. package/dist/streaming/captureLock.d.ts +44 -0
  452. package/dist/streaming/captureLock.d.ts.map +1 -0
  453. package/dist/streaming/captureLock.js +95 -0
  454. package/dist/streaming/captureLock.js.map +1 -0
  455. package/dist/streaming/captureSession.d.ts +31 -0
  456. package/dist/streaming/captureSession.d.ts.map +1 -0
  457. package/dist/streaming/captureSession.js +54 -0
  458. package/dist/streaming/captureSession.js.map +1 -0
  459. package/dist/streaming/clients.d.ts +1 -0
  460. package/dist/streaming/clients.d.ts.map +1 -0
  461. package/dist/streaming/codec.d.ts +1 -0
  462. package/dist/streaming/codec.d.ts.map +1 -0
  463. package/dist/streaming/fmp4Segmenter.d.ts +29 -2
  464. package/dist/streaming/fmp4Segmenter.d.ts.map +1 -0
  465. package/dist/streaming/fmp4Segmenter.js +79 -26
  466. package/dist/streaming/fmp4Segmenter.js.map +1 -1
  467. package/dist/streaming/hls.d.ts +18 -7
  468. package/dist/streaming/hls.d.ts.map +1 -0
  469. package/dist/streaming/hls.js +220 -120
  470. package/dist/streaming/hls.js.map +1 -1
  471. package/dist/streaming/hlsResume.d.ts +1 -0
  472. package/dist/streaming/hlsResume.d.ts.map +1 -0
  473. package/dist/streaming/hlsResume.js +1 -1
  474. package/dist/streaming/hlsResume.js.map +1 -1
  475. package/dist/streaming/hlsSegments.d.ts +59 -2
  476. package/dist/streaming/hlsSegments.d.ts.map +1 -0
  477. package/dist/streaming/hlsSegments.js +147 -17
  478. package/dist/streaming/hlsSegments.js.map +1 -1
  479. package/dist/streaming/lifecycle.d.ts +4 -1
  480. package/dist/streaming/lifecycle.d.ts.map +1 -0
  481. package/dist/streaming/lifecycle.js +65 -85
  482. package/dist/streaming/lifecycle.js.map +1 -1
  483. package/dist/streaming/monitor.d.ts +6 -4
  484. package/dist/streaming/monitor.d.ts.map +1 -0
  485. package/dist/streaming/monitor.js +343 -145
  486. package/dist/streaming/monitor.js.map +1 -1
  487. package/dist/streaming/mp4Parser.d.ts +5 -4
  488. package/dist/streaming/mp4Parser.d.ts.map +1 -0
  489. package/dist/streaming/mp4Parser.js +36 -13
  490. package/dist/streaming/mp4Parser.js.map +1 -1
  491. package/dist/streaming/mpegts.d.ts +16 -0
  492. package/dist/streaming/mpegts.d.ts.map +1 -0
  493. package/dist/streaming/mpegts.js +61 -17
  494. package/dist/streaming/mpegts.js.map +1 -1
  495. package/dist/streaming/playlistBuilder.d.ts +1 -0
  496. package/dist/streaming/playlistBuilder.d.ts.map +1 -0
  497. package/dist/streaming/preroll.d.ts +32 -5
  498. package/dist/streaming/preroll.d.ts.map +1 -0
  499. package/dist/streaming/preroll.js +70 -32
  500. package/dist/streaming/preroll.js.map +1 -1
  501. package/dist/streaming/pretune.d.ts +26 -1
  502. package/dist/streaming/pretune.d.ts.map +1 -0
  503. package/dist/streaming/pretune.js +22 -24
  504. package/dist/streaming/pretune.js.map +1 -1
  505. package/dist/streaming/pretuneTimers.d.ts +24 -0
  506. package/dist/streaming/pretuneTimers.d.ts.map +1 -0
  507. package/dist/streaming/pretuneTimers.js +56 -0
  508. package/dist/streaming/pretuneTimers.js.map +1 -0
  509. package/dist/streaming/recovery.d.ts +139 -5
  510. package/dist/streaming/recovery.d.ts.map +1 -0
  511. package/dist/streaming/recovery.js +160 -16
  512. package/dist/streaming/recovery.js.map +1 -1
  513. package/dist/streaming/registry.d.ts +27 -9
  514. package/dist/streaming/registry.d.ts.map +1 -0
  515. package/dist/streaming/registry.js +21 -3
  516. package/dist/streaming/registry.js.map +1 -1
  517. package/dist/streaming/setup.d.ts +157 -29
  518. package/dist/streaming/setup.d.ts.map +1 -0
  519. package/dist/streaming/setup.js +1034 -458
  520. package/dist/streaming/setup.js.map +1 -1
  521. package/dist/streaming/showInfo.d.ts +21 -1
  522. package/dist/streaming/showInfo.d.ts.map +1 -0
  523. package/dist/streaming/showInfo.js +31 -16
  524. package/dist/streaming/showInfo.js.map +1 -1
  525. package/dist/streaming/statusEmitter.d.ts +10 -10
  526. package/dist/streaming/statusEmitter.d.ts.map +1 -0
  527. package/dist/streaming/statusEmitter.js +5 -8
  528. package/dist/streaming/statusEmitter.js.map +1 -1
  529. package/dist/types/channels.d.ts +16 -4
  530. package/dist/types/channels.d.ts.map +1 -0
  531. package/dist/types/channels.js +4 -2
  532. package/dist/types/channels.js.map +1 -1
  533. package/dist/types/config.d.ts +16 -5
  534. package/dist/types/config.d.ts.map +1 -0
  535. package/dist/types/index.d.ts +3 -2
  536. package/dist/types/index.d.ts.map +1 -0
  537. package/dist/types/profiles.d.ts +6 -4
  538. package/dist/types/profiles.d.ts.map +1 -0
  539. package/dist/types/selection.d.ts +31 -3
  540. package/dist/types/selection.d.ts.map +1 -0
  541. package/dist/types/selection.js +4 -2
  542. package/dist/types/selection.js.map +1 -1
  543. package/dist/types/shared.d.ts +1 -0
  544. package/dist/types/shared.d.ts.map +1 -0
  545. package/dist/types/streaming.d.ts +8 -0
  546. package/dist/types/streaming.d.ts.map +1 -0
  547. package/dist/upgrade/commands.context.d.ts +1 -0
  548. package/dist/upgrade/commands.context.d.ts.map +1 -0
  549. package/dist/upgrade/commands.context.js +14 -10
  550. package/dist/upgrade/commands.context.js.map +1 -1
  551. package/dist/upgrade/commands.d.ts +8 -15
  552. package/dist/upgrade/commands.d.ts.map +1 -0
  553. package/dist/upgrade/commands.js +27 -28
  554. package/dist/upgrade/commands.js.map +1 -1
  555. package/dist/upgrade/detection.context.d.ts +1 -0
  556. package/dist/upgrade/detection.context.d.ts.map +1 -0
  557. package/dist/upgrade/detection.context.js +4 -1
  558. package/dist/upgrade/detection.context.js.map +1 -1
  559. package/dist/upgrade/detection.d.ts +9 -7
  560. package/dist/upgrade/detection.d.ts.map +1 -0
  561. package/dist/upgrade/detection.js +23 -54
  562. package/dist/upgrade/detection.js.map +1 -1
  563. package/dist/upgrade/index.d.ts +2 -0
  564. package/dist/upgrade/index.d.ts.map +1 -0
  565. package/dist/upgrade/index.js +1 -0
  566. package/dist/upgrade/index.js.map +1 -1
  567. package/dist/upgrade/lifecycle.context.d.ts +20 -0
  568. package/dist/upgrade/lifecycle.context.d.ts.map +1 -0
  569. package/dist/upgrade/lifecycle.context.js +47 -0
  570. package/dist/upgrade/lifecycle.context.js.map +1 -0
  571. package/dist/upgrade/lifecycle.d.ts +72 -0
  572. package/dist/upgrade/lifecycle.d.ts.map +1 -0
  573. package/dist/upgrade/lifecycle.js +175 -0
  574. package/dist/upgrade/lifecycle.js.map +1 -0
  575. package/dist/upgrade/pathHandle.d.ts +30 -0
  576. package/dist/upgrade/pathHandle.d.ts.map +1 -0
  577. package/dist/upgrade/pathHandle.js +102 -0
  578. package/dist/upgrade/pathHandle.js.map +1 -0
  579. package/dist/utils/bootSession.context.d.ts +16 -0
  580. package/dist/utils/bootSession.context.d.ts.map +1 -0
  581. package/dist/utils/bootSession.context.js +60 -0
  582. package/dist/utils/bootSession.context.js.map +1 -0
  583. package/dist/utils/bootSession.d.ts +17 -0
  584. package/dist/utils/bootSession.d.ts.map +1 -0
  585. package/dist/utils/bootSession.js +20 -0
  586. package/dist/utils/bootSession.js.map +1 -0
  587. package/dist/utils/chromeFetch.d.ts +1 -0
  588. package/dist/utils/chromeFetch.d.ts.map +1 -0
  589. package/dist/utils/cliOutput.d.ts +1 -0
  590. package/dist/utils/cliOutput.d.ts.map +1 -0
  591. package/dist/utils/clock.d.ts +5 -4
  592. package/dist/utils/clock.d.ts.map +1 -0
  593. package/dist/utils/clock.js +19 -16
  594. package/dist/utils/clock.js.map +1 -1
  595. package/dist/utils/debugFilter.d.ts +9 -1
  596. package/dist/utils/debugFilter.d.ts.map +1 -0
  597. package/dist/utils/debugFilter.js +60 -33
  598. package/dist/utils/debugFilter.js.map +1 -1
  599. package/dist/utils/delay.d.ts +48 -15
  600. package/dist/utils/delay.d.ts.map +1 -0
  601. package/dist/utils/delay.js +73 -20
  602. package/dist/utils/delay.js.map +1 -1
  603. package/dist/utils/errors.d.ts +32 -0
  604. package/dist/utils/errors.d.ts.map +1 -0
  605. package/dist/utils/errors.js +45 -4
  606. package/dist/utils/errors.js.map +1 -1
  607. package/dist/utils/evaluate.d.ts +1 -0
  608. package/dist/utils/evaluate.d.ts.map +1 -0
  609. package/dist/utils/evaluate.js +29 -23
  610. package/dist/utils/evaluate.js.map +1 -1
  611. package/dist/utils/ffmpeg.context.d.ts +1 -0
  612. package/dist/utils/ffmpeg.context.d.ts.map +1 -0
  613. package/dist/utils/ffmpeg.context.js.map +1 -1
  614. package/dist/utils/ffmpeg.d.ts +29 -7
  615. package/dist/utils/ffmpeg.d.ts.map +1 -0
  616. package/dist/utils/ffmpeg.js +32 -14
  617. package/dist/utils/ffmpeg.js.map +1 -1
  618. package/dist/utils/fileLogger.d.ts +3 -1
  619. package/dist/utils/fileLogger.d.ts.map +1 -0
  620. package/dist/utils/fileLogger.js +64 -29
  621. package/dist/utils/fileLogger.js.map +1 -1
  622. package/dist/utils/format.d.ts +14 -1
  623. package/dist/utils/format.d.ts.map +1 -0
  624. package/dist/utils/format.js +19 -5
  625. package/dist/utils/format.js.map +1 -1
  626. package/dist/utils/index.d.ts +4 -0
  627. package/dist/utils/index.d.ts.map +1 -0
  628. package/dist/utils/index.js +3 -0
  629. package/dist/utils/index.js.map +1 -1
  630. package/dist/utils/logEmitter.d.ts +1 -0
  631. package/dist/utils/logEmitter.d.ts.map +1 -0
  632. package/dist/utils/logger.d.ts +1 -0
  633. package/dist/utils/logger.d.ts.map +1 -0
  634. package/dist/utils/logger.js +10 -6
  635. package/dist/utils/logger.js.map +1 -1
  636. package/dist/utils/m3u.d.ts +3 -2
  637. package/dist/utils/m3u.d.ts.map +1 -0
  638. package/dist/utils/m3u.js +4 -3
  639. package/dist/utils/m3u.js.map +1 -1
  640. package/dist/utils/markup.d.ts +13 -1
  641. package/dist/utils/markup.d.ts.map +1 -0
  642. package/dist/utils/markup.js +28 -4
  643. package/dist/utils/markup.js.map +1 -1
  644. package/dist/utils/memo.d.ts +3 -2
  645. package/dist/utils/memo.d.ts.map +1 -0
  646. package/dist/utils/memo.js +3 -3
  647. package/dist/utils/morganStream.d.ts +1 -0
  648. package/dist/utils/morganStream.d.ts.map +1 -0
  649. package/dist/utils/network.d.ts +1 -0
  650. package/dist/utils/network.d.ts.map +1 -0
  651. package/dist/utils/network.js +2 -2
  652. package/dist/utils/pid.d.ts +3 -25
  653. package/dist/utils/pid.d.ts.map +1 -0
  654. package/dist/utils/pid.js +10 -49
  655. package/dist/utils/pid.js.map +1 -1
  656. package/dist/utils/platform.d.ts +3 -1
  657. package/dist/utils/platform.d.ts.map +1 -0
  658. package/dist/utils/platform.js +2 -1
  659. package/dist/utils/platform.js.map +1 -1
  660. package/dist/utils/processInspector.context.d.ts +8 -0
  661. package/dist/utils/processInspector.context.d.ts.map +1 -0
  662. package/dist/utils/processInspector.context.js +106 -0
  663. package/dist/utils/processInspector.context.js.map +1 -0
  664. package/dist/utils/processInspector.d.ts +55 -0
  665. package/dist/utils/processInspector.d.ts.map +1 -0
  666. package/dist/utils/processInspector.js +127 -0
  667. package/dist/utils/processInspector.js.map +1 -0
  668. package/dist/utils/retry.d.ts +25 -2
  669. package/dist/utils/retry.d.ts.map +1 -0
  670. package/dist/utils/retry.js +33 -6
  671. package/dist/utils/retry.js.map +1 -1
  672. package/dist/utils/runtimeIdentity.context.d.ts +7 -0
  673. package/dist/utils/runtimeIdentity.context.d.ts.map +1 -0
  674. package/dist/utils/runtimeIdentity.context.js +43 -0
  675. package/dist/utils/runtimeIdentity.context.js.map +1 -0
  676. package/dist/utils/runtimeIdentity.d.ts +98 -0
  677. package/dist/utils/runtimeIdentity.d.ts.map +1 -0
  678. package/dist/utils/runtimeIdentity.js +181 -0
  679. package/dist/utils/runtimeIdentity.js.map +1 -0
  680. package/dist/utils/sanitize.d.ts +1 -0
  681. package/dist/utils/sanitize.d.ts.map +1 -0
  682. package/dist/utils/streamContext.d.ts +2 -1
  683. package/dist/utils/streamContext.d.ts.map +1 -0
  684. package/dist/utils/streamContext.js +1 -1
  685. package/dist/utils/timing.d.ts +2 -1
  686. package/dist/utils/timing.d.ts.map +1 -0
  687. package/dist/utils/timing.js +0 -5
  688. package/dist/utils/timing.js.map +1 -1
  689. package/dist/utils/version.d.ts +1 -0
  690. package/dist/utils/version.d.ts.map +1 -0
  691. package/dist/utils/version.js +47 -13
  692. package/dist/utils/version.js.map +1 -1
  693. package/package.json +26 -20
@@ -1,10 +1,11 @@
1
- import { getPackageVersion, normalizeClientAddress } from "../utils/index.js";
1
+ import { HDHR_FIRMWARE_NAME, HDHR_MANUFACTURER, HDHR_MODEL_NUMBER } from "./identity.js";
2
+ import { escapeXml, getPackageVersion } from "../utils/index.js";
2
3
  import { CONFIG } from "../config/index.js";
3
4
  import { buildChannelMap } from "./channelMap.js";
4
- import { getAllStreams } from "../streaming/registry.js";
5
+ import { getTunerStates } from "./tunerState.js";
5
6
  /**
6
- * Resolves the hostname from an incoming request for use in generated URLs. We extract the hostname from the request (which Plex already connected to) and
7
- * combine it with the appropriate port. This ensures URLs work from Plex's network perspective.
7
+ * Resolves the hostname from an incoming request for use in generated URLs. We extract the hostname from the request (which the client already connected
8
+ * to) and combine it with the appropriate port. This ensures URLs work from the client's network perspective.
8
9
  * @param req - The Express request object.
9
10
  * @returns The hostname (without port) that the client used to connect.
10
11
  */
@@ -30,12 +31,18 @@ function resolveHostname(req) {
30
31
  * @param app - The Express application for the HDHR server.
31
32
  */
32
33
  export function setupHdhrEndpoints(app) {
33
- // GET /device.xml - UPnP device description. Plex fetches this during tuner discovery before querying discover.json. Without a valid device.xml response,
34
- // Plex may silently abort the discovery process.
34
+ // GET /device.xml - UPnP device description. HDHR-aware clients (Plex in particular) fetch this during tuner discovery before querying discover.json.
35
+ // Without a valid device.xml response the discovery process may abort silently on stricter clients.
35
36
  app.get("/device.xml", (req, res) => {
36
37
  const hostname = resolveHostname(req);
37
38
  const baseUrl = "http://" + hostname + ":" + String(CONFIG.hdhr.port);
38
39
  const deviceId = CONFIG.hdhr.deviceId.toUpperCase();
40
+ /* Every value interpolated below is escaped, the compile-time constants included, which is the convention the launchd plist generator follows: escaping at
41
+ * each interpolation point rather than trusting the shape of any particular value. The values outside our control are the ones somebody else supplies:
42
+ * friendlyName is free text the operator types, and baseUrl derives from the client-supplied Host or X-Forwarded-Host header that resolveHostname reads
43
+ * without sanitizing, so an unescaped ampersand or angle bracket from either source yields a document a client cannot parse. Escaping the constants costs
44
+ * nothing and means changing one of them can never reintroduce that.
45
+ */
39
46
  const xml = [
40
47
  "<?xml version=\"1.0\" encoding=\"UTF-8\"?>",
41
48
  "<root xmlns=\"urn:schemas-upnp-org:device-1-0\">",
@@ -43,43 +50,43 @@ export function setupHdhrEndpoints(app) {
43
50
  " <major>1</major>",
44
51
  " <minor>0</minor>",
45
52
  " </specVersion>",
46
- " <URLBase>" + baseUrl + "</URLBase>",
53
+ " <URLBase>" + escapeXml(baseUrl) + "</URLBase>",
47
54
  " <device>",
48
55
  " <deviceType>urn:schemas-upnp-org:device:MediaServer:1</deviceType>",
49
- " <friendlyName>" + CONFIG.hdhr.friendlyName + "</friendlyName>",
50
- " <manufacturer>PrismCast</manufacturer>",
51
- " <modelName>HDTC-2US</modelName>",
52
- " <modelNumber>HDTC-2US</modelNumber>",
53
- " <serialNumber>" + deviceId + "</serialNumber>",
54
- " <UDN>uuid:" + deviceId + "</UDN>",
56
+ " <friendlyName>" + escapeXml(CONFIG.hdhr.friendlyName) + "</friendlyName>",
57
+ " <manufacturer>" + escapeXml(HDHR_MANUFACTURER) + "</manufacturer>",
58
+ " <modelName>" + escapeXml(HDHR_MODEL_NUMBER) + "</modelName>",
59
+ " <modelNumber>" + escapeXml(HDHR_MODEL_NUMBER) + "</modelNumber>",
60
+ " <serialNumber>" + escapeXml(deviceId) + "</serialNumber>",
61
+ " <UDN>uuid:" + escapeXml(deviceId) + "</UDN>",
55
62
  " </device>",
56
63
  "</root>"
57
64
  ].join("\n");
58
65
  res.set("Content-Type", "text/xml");
59
66
  res.send(xml);
60
67
  });
61
- // GET /discover.json - Device identity and capabilities. Plex uses this to identify the tuner model, determine concurrent stream capacity, and locate the
68
+ // GET /discover.json - Device identity and capabilities. Clients use this to identify the tuner model, determine concurrent stream capacity, and locate the
62
69
  // lineup endpoint.
63
70
  app.get("/discover.json", (req, res) => {
64
71
  const hostname = resolveHostname(req);
65
72
  const baseUrl = "http://" + hostname + ":" + String(CONFIG.hdhr.port);
66
- // The response follows the HDHomeRun HTTP API format that Plex expects. DeviceAuth must be non-empty; we use the DeviceID since there's no DRM context.
67
- // ModelNumber "HDTC-2US" is the HDHomeRun CONNECT DUO, a widely-supported model that Plex recognizes.
73
+ // The response follows the HDHomeRun HTTP API format that Plex expects. DeviceAuth must be non-empty; we use the DeviceID since there is no DRM context.
74
+ // Identity strings come from hdhr/identity.ts so a future model swap is a single-file edit.
68
75
  res.json({
69
76
  BaseURL: baseUrl,
70
77
  DeviceAuth: CONFIG.hdhr.deviceId.toUpperCase(),
71
78
  DeviceID: CONFIG.hdhr.deviceId.toUpperCase(),
72
- FirmwareName: "hdhomeruntc_atsc",
79
+ FirmwareName: HDHR_FIRMWARE_NAME,
73
80
  FirmwareVersion: getPackageVersion(),
74
81
  FriendlyName: CONFIG.hdhr.friendlyName,
75
82
  LineupURL: baseUrl + "/lineup.json",
76
- Manufacturer: "PrismCast",
77
- ModelNumber: "HDTC-2US",
83
+ Manufacturer: HDHR_MANUFACTURER,
84
+ ModelNumber: HDHR_MODEL_NUMBER,
78
85
  TunerCount: CONFIG.streaming.maxConcurrentStreams
79
86
  });
80
87
  });
81
- // GET /lineup.json - Channel lineup with stream URLs. Each entry maps a numeric channel number to an MPEG-TS stream URL on the main PrismCast server. Plex
82
- // requests the MPEG-TS stream directly from the main server when tuning a channel.
88
+ // GET /lineup.json - Channel lineup with stream URLs. Each entry maps a numeric channel number to an MPEG-TS stream URL on the main PrismCast server. The
89
+ // client requests the MPEG-TS stream directly from the main server when tuning a channel.
83
90
  app.get("/lineup.json", (req, res) => {
84
91
  const hostname = resolveHostname(req);
85
92
  const mainBaseUrl = "http://" + hostname + ":" + String(CONFIG.server.port);
@@ -94,7 +101,7 @@ export function setupHdhrEndpoints(app) {
94
101
  }));
95
102
  res.json(lineup);
96
103
  });
97
- // GET /lineup_status.json - Channel scan status. Plex checks this during tuner setup. We return a static response indicating scan is complete since PrismCast's
104
+ // GET /lineup_status.json - Channel scan status. Clients check this during tuner setup. We return a static response indicating scan is complete since PrismCast's
98
105
  // channels are configured, not scanned.
99
106
  app.get("/lineup_status.json", (_req, res) => {
100
107
  res.json({
@@ -104,41 +111,35 @@ export function setupHdhrEndpoints(app) {
104
111
  SourceList: ["Cable"]
105
112
  });
106
113
  });
107
- // POST /lineup.post - Channel scan control. Some clients (Plex during initial setup) POST scan=start to this endpoint. We return 200 OK since PrismCast's channels
108
- // are statically configured and scanning is not applicable.
114
+ // POST /lineup.post - Channel scan control. Some clients (Plex during initial setup is the common case) POST scan=start here. We return 200 OK since
115
+ // PrismCast's channels are statically configured and scanning is not applicable.
109
116
  app.post("/lineup.post", (_req, res) => {
110
117
  res.sendStatus(200);
111
118
  });
112
119
  // GET /status.json - Tuner status. Returns a JSON array with one entry per tuner slot. Active tuners include channel info and signal stats; idle tuners have only
113
- // Resource. Monitoring dashboards (Home Assistant, Homepage) poll this endpoint to display real-time tuner activity.
120
+ // Resource. Monitoring dashboards (Home Assistant, Homepage) poll this endpoint to display real-time tuner activity. The slot-indexed projection comes from
121
+ // getTunerStates - the same SSOT the UDP Get handlers use - so any change to channel-merge or fallback logic lands in one place.
114
122
  app.get("/status.json", (_req, res) => {
115
- const channelMap = buildChannelMap();
116
- const channelByKey = new Map(channelMap.map((entry) => [entry.key, entry]));
117
- const streams = getAllStreams().sort((a, b) => a.id - b.id);
118
- const tunerCount = CONFIG.streaming.maxConcurrentStreams;
119
- const tuners = [];
120
- // Build active tuner entries from currently running streams.
121
- for (const [i, stream] of streams.entries()) {
122
- const channelEntry = channelByKey.get(stream.info.storeKey);
123
- // Build the tuner entry. Active tuners include channel info and signal stats. Signal values are hardcoded at 100 since PrismCast streams are network-based and
124
- // either working or not - there is no analog signal quality to report. Channel info is merged conditionally: prefer the channel map for VctNumber (numeric
125
- // channel) and VctName (display name), fall back to stream.channelName for VctName if the channel was removed from the map after the stream started.
126
- const tuner = {
123
+ const tuners = getTunerStates().map((state) => {
124
+ // Idle slots carry only the resource name; active slots include signal stats hardcoded at 100 (network streams have no analog signal quality), plus
125
+ // channel and client information whenever the underlying TunerState provides it.
126
+ if (!state.active) {
127
+ return { Resource: state.resource };
128
+ }
129
+ return {
127
130
  Frequency: 0,
128
- Resource: "tuner" + String(i),
131
+ Resource: state.resource,
129
132
  SignalQualityPercent: 100,
130
133
  SignalStrengthPercent: 100,
131
134
  SymbolQualityPercent: 100,
132
- ...(channelEntry ? { VctName: channelEntry.name, VctNumber: String(channelEntry.number) } : {}),
133
- ...(!channelEntry && stream.channelName ? { VctName: stream.channelName } : {}),
134
- ...(stream.clientAddress ? { TargetIP: normalizeClientAddress(stream.clientAddress) } : {})
135
+ // The channelNumber guard checks (!== null) rather than truthiness because null is the only absent-sentinel this field carries; buildChannelMap never
136
+ // actually assigns a channelNumber of 0 today, but the explicit null check does not depend on that staying true. Name and address gate on truthiness
137
+ // instead because their absent case is naturally an empty string, so a truthy check is the right match for those two fields.
138
+ ...((state.channelNumber !== null) ? { VctNumber: String(state.channelNumber) } : {}),
139
+ ...(state.channelName ? { VctName: state.channelName } : {}),
140
+ ...(state.clientAddress ? { TargetIP: state.clientAddress } : {})
135
141
  };
136
- tuners.push(tuner);
137
- }
138
- // Fill remaining slots with idle tuner entries.
139
- for (let i = streams.length; i < tunerCount; i++) {
140
- tuners.push({ Resource: "tuner" + String(i) });
141
- }
142
+ });
142
143
  res.json(tuners);
143
144
  });
144
145
  }
@@ -1 +1 @@
1
- {"version":3,"file":"discover.js","sourceRoot":"","sources":["../../src/hdhr/discover.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"discover.js","sourceRoot":"","sources":["../../src/hdhr/discover.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ import type { TunerState } from "./tunerState.ts";
2
+ /**
3
+ * Result of resolving a Get key. The discriminated union mirrors the protocol's reply shape: a value reply carries the answered string; an error reply carries
4
+ * the rejection reason. Callers translate the result into a wire packet via buildGetReply/buildErrorReply.
5
+ */
6
+ export type GetResult = {
7
+ readonly kind: "value";
8
+ readonly value: string;
9
+ } | {
10
+ readonly kind: "error";
11
+ readonly error: string;
12
+ };
13
+ /**
14
+ * Context required to answer a Get request. Carries the slot-indexed tuner state (so per-tuner keys can look up the addressed slot) and a runtime-version
15
+ * string (so /sys/version reflects the running build). Other identity-shaped values come from hdhr/identity.ts and do not need to flow through the context.
16
+ */
17
+ export interface GetContext {
18
+ readonly runtimeVersion: string;
19
+ readonly tuners: readonly TunerState[];
20
+ }
21
+ /**
22
+ * Resolves a Get key to a reply value or an error. Single entry point the transport layer calls per request. Unknown keys produce an error result matching the
23
+ * "ERROR: unknown getset variable" prose real HDHR firmware uses.
24
+ * @param name - The slash-delimited Get key from the request.
25
+ * @param ctx - The resolution context (tuner state + runtime version).
26
+ * @returns The resolved value or an error.
27
+ */
28
+ export declare function resolveGet(name: string, ctx: GetContext): GetResult;
29
+ //# sourceMappingURL=getHandlers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getHandlers.d.ts","sourceRoot":"","sources":["../../src/hdhr/getHandlers.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAOlD;;;GAGG;AACH,MAAM,MAAM,SAAS,GACnB;IAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAClD;IAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAErD;;;GAGG;AACH,MAAM,WAAW,UAAU;IAGzB,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAGhC,QAAQ,CAAC,MAAM,EAAE,SAAS,UAAU,EAAE,CAAC;CACxC;AA4BD;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,GAAG,SAAS,CAqBnE"}
@@ -0,0 +1,196 @@
1
+ /* Copyright(C) 2024-2026, HJD (https://github.com/hjdhjd). All rights reserved.
2
+ *
3
+ * getHandlers.ts: Data-driven dispatch table for HDHomeRun UDP Get requests.
4
+ *
5
+ * HDHR-aware clients can issue UDP Get requests for a small fixed catalog of named state keys ("/sys/version", "/tuner0/channel", ...) once they have located a
6
+ * device via Discover. The transport layer parses each request and routes it through this module's resolveGet function; the resolver consults a table of
7
+ * static-system keys (those whose value is a constant sourced from hdhr/identity.ts, a fixed literal, or the runtime-version carried on GetContext) and a
8
+ * regex for per-tuner keys (those whose value depends on which slot is being addressed). Unknown keys fall through to an error reply, matching real HDHR
9
+ * firmware behavior.
10
+ *
11
+ * Two layering choices keep this module easy to extend and test:
12
+ *
13
+ * 1. Pure functions over a GetContext boundary. Tests construct a synthetic context with any tuner state and assert reply values without touching CONFIG, the
14
+ * stream registry, or any other global. The transport layer composes the production context once per request and passes it through.
15
+ *
16
+ * 2. A Record-keyed dispatch table for /sys/* keys, plus a single regex for /tuner&lt;N&gt;/*. Adding a new system key is a single row; adding a new per-tuner key
17
+ * is one additional case in resolveTunerKey. The dispatch shape stays declarative even as the catalog grows.
18
+ */
19
+ import { HDHR_COPYRIGHT, HDHR_HW_MODEL, HDHR_MODEL } from "./identity.js";
20
+ // Canonical wire-protocol error string for fall-through cases (unknown system key, unknown per-tuner sub-key). Real HDHomeRun firmware uses this exact wording;
21
+ // mirroring it keeps client error displays familiar to operators who have seen it from real devices. Hoisted to a module constant so both fall-through sites
22
+ // agree on the spelling - any future tweak (capitalization, punctuation) lands in one place.
23
+ const ERROR_UNKNOWN_GETSET = "ERROR: unknown getset variable";
24
+ /**
25
+ * Dispatch table for /sys/* keys. Each entry is a single-argument function over GetContext returning the answer string. The table is the SSOT for which system
26
+ * keys PrismCast answers; adding a new key is a single row, and the parser, error path, and test surface require no other changes.
27
+ */
28
+ const SYSTEM_HANDLERS = {
29
+ // Copyright string returned when probes call /sys/copyright. Static across runtime; sourced from the identity SSOT.
30
+ "/sys/copyright": () => HDHR_COPYRIGHT,
31
+ // Debug surface placeholder. Real HDHRs return verbose multi-line debug strings here; PrismCast returns an empty value so probes succeed without leaking
32
+ // internal state. Operators that want richer debug should consult the standard PrismCast logs instead.
33
+ "/sys/debug": () => "",
34
+ // Hardware model identifier. Constant across runtime; sourced from the identity SSOT.
35
+ "/sys/hwmodel": () => HDHR_HW_MODEL,
36
+ // Software model identifier (same as hardware model on the HDTC-2US family).
37
+ "/sys/model": () => HDHR_MODEL,
38
+ // Running version string, derived from package.json via the runtime context.
39
+ "/sys/version": (ctx) => ctx.runtimeVersion
40
+ };
41
+ // Regex matching per-tuner keys: "/tuner<N>/<sub-key>". Numeric capture group lets resolveTunerKey index into ctx.tuners; the second capture is the sub-key.
42
+ const TUNER_KEY_PATTERN = /^\/tuner(\d+)\/(.+)$/;
43
+ /**
44
+ * Resolves a Get key to a reply value or an error. Single entry point the transport layer calls per request. Unknown keys produce an error result matching the
45
+ * "ERROR: unknown getset variable" prose real HDHR firmware uses.
46
+ * @param name - The slash-delimited Get key from the request.
47
+ * @param ctx - The resolution context (tuner state + runtime version).
48
+ * @returns The resolved value or an error.
49
+ */
50
+ export function resolveGet(name, ctx) {
51
+ // System keys go through the dispatch table first because they cover the most common probes (version, model, copyright).
52
+ const systemHandler = SYSTEM_HANDLERS[name];
53
+ if (systemHandler !== undefined) {
54
+ return { kind: "value", value: systemHandler(ctx) };
55
+ }
56
+ // Per-tuner keys go through the regex extractor. A match means "/tunerN/..." but the slot index may still be out of bounds for the configured tuner count;
57
+ // resolveTunerKey enforces both that bound and the sub-key catalog.
58
+ const tunerMatch = TUNER_KEY_PATTERN.exec(name);
59
+ if (tunerMatch !== null) {
60
+ return resolveTunerKey(Number(tunerMatch[1]), tunerMatch[2] ?? "", ctx);
61
+ }
62
+ // Fall through to the canonical "unknown getset variable" error so unknown system keys produce the same wording real HDHR firmware would.
63
+ return { error: ERROR_UNKNOWN_GETSET, kind: "error" };
64
+ }
65
+ /**
66
+ * Resolves a per-tuner Get key for a specific slot. Sub-keys fall into two families: static state returning constants that do not depend on the tuner's
67
+ * current activity, and dynamic state read from the addressed TunerState. Unknown sub-keys produce an error matching real HDHR behavior.
68
+ * @param slot - Zero-based tuner slot index.
69
+ * @param subKey - The sub-key portion after the slot prefix.
70
+ * @param ctx - The resolution context.
71
+ * @returns The resolved value or an error.
72
+ */
73
+ function resolveTunerKey(slot, subKey, ctx) {
74
+ const state = ctx.tuners[slot] ?? null;
75
+ if (state === null) {
76
+ // Slot index out of range produces its own distinct error string, separate from the ERROR_UNKNOWN_GETSET fallback used for unrecognized sub-keys.
77
+ return { error: "ERROR: unknown tuner", kind: "error" };
78
+ }
79
+ switch (subKey) {
80
+ case "channel": {
81
+ return { kind: "value", value: formatChannel(state) };
82
+ }
83
+ case "channelmap": {
84
+ // Real HDHRs return the tuning band ("us-bcast", "us-cable"). PrismCast has no RF input, so we return an empty string - clients that filter on this
85
+ // value will route us to the generic IP-tuner code path.
86
+ return { kind: "value", value: "" };
87
+ }
88
+ case "debug": {
89
+ // Per-tuner debug placeholder, mirroring /sys/debug: PrismCast returns an empty value rather than the verbose per-tuner debug string real HDHRs emit.
90
+ return { kind: "value", value: "" };
91
+ }
92
+ case "filter": {
93
+ // PID filter. Default value matches a fully-open filter (every PID accepted), which is the right wire value for a tuner that has no PSI multiplexing.
94
+ return { kind: "value", value: "0x0000-0x1FFF" };
95
+ }
96
+ case "lockkey": {
97
+ // Lockkey is a write-once exclusive-tuner lock real HDHRs use. PrismCast has no exclusivity model, so we report it as unlocked.
98
+ return { kind: "value", value: "none" };
99
+ }
100
+ case "program": {
101
+ // MPEG-TS program number. We do not surface a useful value because PrismCast remuxes into a single-program MPEG-TS; clients that need it can read the
102
+ // stream itself.
103
+ return { kind: "value", value: "0" };
104
+ }
105
+ case "status": {
106
+ return { kind: "value", value: formatStatus(state) };
107
+ }
108
+ case "streaminfo": {
109
+ return { kind: "value", value: formatStreamInfo(state) };
110
+ }
111
+ case "target": {
112
+ return { kind: "value", value: formatTarget() };
113
+ }
114
+ case "vchannel": {
115
+ return { kind: "value", value: formatVchannel(state) };
116
+ }
117
+ case "vstatus": {
118
+ return { kind: "value", value: formatVstatus(state) };
119
+ }
120
+ default: {
121
+ return { error: ERROR_UNKNOWN_GETSET, kind: "error" };
122
+ }
123
+ }
124
+ }
125
+ /**
126
+ * Formats /tuner&lt;N&gt;/channel: the currently-tuned channel in HDHR notation. Active slots produce "auto:&lt;number&gt;" matching the HTTP-streaming convention; idle
127
+ * slots produce "none" as real HDHRs do.
128
+ * @param state - The slot's state.
129
+ * @returns The wire-formatted channel string.
130
+ */
131
+ function formatChannel(state) {
132
+ if (!state.active || (state.channelNumber === null)) {
133
+ return "none";
134
+ }
135
+ return "auto:" + String(state.channelNumber);
136
+ }
137
+ /**
138
+ * Formats /tuner&lt;N&gt;/status: a single-line status string. Real HDHRs report something like "ch=auto:5 lock=8vsb ...". PrismCast has no analog tuning, so the
139
+ * relevant fields are channel binding and stream state.
140
+ * @param state - The slot's state.
141
+ * @returns The wire-formatted status string.
142
+ */
143
+ function formatStatus(state) {
144
+ if (!state.active) {
145
+ return "ch=none lock=none ss=0 snq=0 seq=0 bps=0 pps=0";
146
+ }
147
+ // We report 100% on the signal metrics because the IP path either delivers bytes or it does not - there is no analog gradation. Bitrate is left at zero
148
+ // because we do not track it at this layer; clients that care can read /stream/* directly.
149
+ return "ch=" + formatChannel(state) + " lock=8vsb ss=100 snq=100 seq=100 bps=0 pps=0";
150
+ }
151
+ /**
152
+ * Formats /tuner&lt;N&gt;/streaminfo: a brief description of the program PrismCast is delivering. We surface the channel name when available so probe tools have a
153
+ * human-readable identifier.
154
+ * @param state - The slot's state.
155
+ * @returns The wire-formatted streaminfo string.
156
+ */
157
+ function formatStreamInfo(state) {
158
+ if (!state.active || !state.channelName) {
159
+ return "none";
160
+ }
161
+ return state.channelName;
162
+ }
163
+ /**
164
+ * Formats /tuner&lt;N&gt;/target: the destination URL of any RTP forwarding the tuner is doing. PrismCast does not forward (clients fetch over HTTP), so the value
165
+ * is always "none" regardless of slot state. Real HDHRs use this key on legacy RTP-streaming devices; HTTP-streaming devices like the HDTC-2US that PrismCast
166
+ * emulates also return "none" here.
167
+ * @returns The wire-formatted target string.
168
+ */
169
+ function formatTarget() {
170
+ return "none";
171
+ }
172
+ /**
173
+ * Formats /tuner&lt;N&gt;/vchannel: the virtual channel number (display number) the tuner is bound to. Real HDHRs differ between physical and virtual channels for
174
+ * over-the-air ATSC; PrismCast has only virtual numbers from the lineup.
175
+ * @param state - The slot's state.
176
+ * @returns The wire-formatted vchannel string.
177
+ */
178
+ function formatVchannel(state) {
179
+ if (!state.active || (state.channelNumber === null)) {
180
+ return "none";
181
+ }
182
+ return String(state.channelNumber);
183
+ }
184
+ /**
185
+ * Formats /tuner&lt;N&gt;/vstatus: a parallel of /tuner&lt;N&gt;/status but reporting the virtual-channel lock state. We mirror /status because PrismCast has only the
186
+ * one channel concept.
187
+ * @param state - The slot's state.
188
+ * @returns The wire-formatted vstatus string.
189
+ */
190
+ function formatVstatus(state) {
191
+ if (!state.active) {
192
+ return "vch=none auth=unknown cci=none cgms=none";
193
+ }
194
+ return "vch=" + formatVchannel(state) + " auth=success cci=none cgms=none";
195
+ }
196
+ //# sourceMappingURL=getHandlers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getHandlers.js","sourceRoot":"","sources":["../../src/hdhr/getHandlers.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Display name shown in client tuner pickers when probing PrismCast's HTTP discovery. Identifies the *manufacturer* of the emulated device, separate from
3
+ * PrismCast's product identity used in CONFIG.hdhr.friendlyName (which the operator can customize).
4
+ */
5
+ export declare const HDHR_MANUFACTURER = "PrismCast";
6
+ /**
7
+ * Hardware model string returned by the UDP control plane for /sys/hwmodel queries. Matches the real HDTC-2US value so clients that filter device lists by
8
+ * hwmodel ("show only ATSC tuners", "show only Connect-family devices") accept PrismCast.
9
+ */
10
+ export declare const HDHR_HW_MODEL = "hdhomerun3_atsc";
11
+ /**
12
+ * Software model string returned by the UDP control plane for /sys/model queries. Identical to the hardware model for the HDTC-2US generation; real Connect
13
+ * devices report the same string for both keys.
14
+ */
15
+ export declare const HDHR_MODEL = "hdhomerun3_atsc";
16
+ /**
17
+ * HDHomeRun CONNECT model identifier returned in /discover.json's ModelNumber field. The CONNECT is an HTTP-streaming model - clients that see this
18
+ * model expect to tune by HTTP fetching the lineup URL's stream entries, which is exactly how PrismCast serves video.
19
+ */
20
+ export declare const HDHR_MODEL_NUMBER = "HDTC-2US";
21
+ /**
22
+ * Firmware family identifier returned in /discover.json's FirmwareName field. The "atsc" suffix matches the hwmodel/model strings; the version is reported
23
+ * separately as PrismCast's package version so operators can correlate the running PrismCast build with HDHR-aware client tuner pages.
24
+ */
25
+ export declare const HDHR_FIRMWARE_NAME = "hdhomeruntc_atsc";
26
+ /**
27
+ * Copyright string returned by the UDP control plane for /sys/copyright queries and matching the prose tools like hdhomerun_config print when probing a
28
+ * device. Sentence form so the value reads cleanly when surfaced in a status display.
29
+ */
30
+ export declare const HDHR_COPYRIGHT = "Copyright(C) HJD - PrismCast HDHomeRun emulation.";
31
+ /**
32
+ * UDP discovery protocol uses a 4-byte device-type tag to classify the device. The single tuner-class value is 0x00000001; PrismCast advertises itself as a
33
+ * tuner so HDHR-aware clients route to their tuner-handling code paths rather than to repeater or storage paths used by other SiliconDust products.
34
+ */
35
+ export declare const HDHR_DEVICE_TYPE_TUNER = 1;
36
+ //# sourceMappingURL=identity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"identity.d.ts","sourceRoot":"","sources":["../../src/hdhr/identity.ts"],"names":[],"mappings":"AAgBA;;;GAGG;AACH,eAAO,MAAM,iBAAiB,cAAc,CAAC;AAE7C;;;GAGG;AACH,eAAO,MAAM,aAAa,oBAAoB,CAAC;AAE/C;;;GAGG;AACH,eAAO,MAAM,UAAU,oBAAgB,CAAC;AAExC;;;GAGG;AACH,eAAO,MAAM,iBAAiB,aAAa,CAAC;AAE5C;;;GAGG;AACH,eAAO,MAAM,kBAAkB,qBAAqB,CAAC;AAErD;;;GAGG;AACH,eAAO,MAAM,cAAc,sDAAsD,CAAC;AAElF;;;GAGG;AACH,eAAO,MAAM,sBAAsB,IAAa,CAAC"}
@@ -0,0 +1,51 @@
1
+ /* Copyright(C) 2024-2026, HJD (https://github.com/hjdhjd). All rights reserved.
2
+ *
3
+ * identity.ts: HDHomeRun device-identity constants for PrismCast.
4
+ *
5
+ * Real HDHomeRun devices identify themselves via a small set of model strings that clients use to gate behavior - "ModelNumber" appears in /discover.json,
6
+ * "/sys/model" and "/sys/hwmodel" come back over the UDP control plane on port 65001, and "/sys/copyright" is what hdhomerun_config and similar tools print
7
+ * when probing a device. PrismCast emulates the HDHomeRun CONNECT (an HTTP-streaming model) because the HTTP-streaming family is what every modern HDHR-
8
+ * aware client expects, and because that model has no DRM context to fake. Two call sites consume these strings: the HTTP discovery endpoints (device.xml,
9
+ * discover.json) and the UDP Get-request responder (/sys/* keys). This module is the single source of truth so a future model change is a
10
+ * one-line edit, not a sweep across every consumer.
11
+ *
12
+ * The hwmodel/model strings ("hdhomerun3_atsc") assert "ATSC tuner" which PrismCast manifestly is not - but every HDTC-2US in the wild returns this same value
13
+ * and many clients filter on it. Cohesion with the existing ModelNumber wins over literal accuracy. If a future client gains a "browser tuner" device type the
14
+ * strings here are the only place that needs to change.
15
+ */
16
+ /**
17
+ * Display name shown in client tuner pickers when probing PrismCast's HTTP discovery. Identifies the *manufacturer* of the emulated device, separate from
18
+ * PrismCast's product identity used in CONFIG.hdhr.friendlyName (which the operator can customize).
19
+ */
20
+ export const HDHR_MANUFACTURER = "PrismCast";
21
+ /**
22
+ * Hardware model string returned by the UDP control plane for /sys/hwmodel queries. Matches the real HDTC-2US value so clients that filter device lists by
23
+ * hwmodel ("show only ATSC tuners", "show only Connect-family devices") accept PrismCast.
24
+ */
25
+ export const HDHR_HW_MODEL = "hdhomerun3_atsc";
26
+ /**
27
+ * Software model string returned by the UDP control plane for /sys/model queries. Identical to the hardware model for the HDTC-2US generation; real Connect
28
+ * devices report the same string for both keys.
29
+ */
30
+ export const HDHR_MODEL = HDHR_HW_MODEL;
31
+ /**
32
+ * HDHomeRun CONNECT model identifier returned in /discover.json's ModelNumber field. The CONNECT is an HTTP-streaming model - clients that see this
33
+ * model expect to tune by HTTP fetching the lineup URL's stream entries, which is exactly how PrismCast serves video.
34
+ */
35
+ export const HDHR_MODEL_NUMBER = "HDTC-2US";
36
+ /**
37
+ * Firmware family identifier returned in /discover.json's FirmwareName field. The "atsc" suffix matches the hwmodel/model strings; the version is reported
38
+ * separately as PrismCast's package version so operators can correlate the running PrismCast build with HDHR-aware client tuner pages.
39
+ */
40
+ export const HDHR_FIRMWARE_NAME = "hdhomeruntc_atsc";
41
+ /**
42
+ * Copyright string returned by the UDP control plane for /sys/copyright queries and matching the prose tools like hdhomerun_config print when probing a
43
+ * device. Sentence form so the value reads cleanly when surfaced in a status display.
44
+ */
45
+ export const HDHR_COPYRIGHT = "Copyright(C) HJD - PrismCast HDHomeRun emulation.";
46
+ /**
47
+ * UDP discovery protocol uses a 4-byte device-type tag to classify the device. The single tuner-class value is 0x00000001; PrismCast advertises itself as a
48
+ * tuner so HDHR-aware clients route to their tuner-handling code paths rather than to repeater or storage paths used by other SiliconDust products.
49
+ */
50
+ export const HDHR_DEVICE_TYPE_TUNER = 0x00000001;
51
+ //# sourceMappingURL=identity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"identity.js","sourceRoot":"","sources":["../../src/hdhr/identity.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH;;;GAGG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,WAAW,CAAC;AAE7C;;;GAGG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,iBAAiB,CAAC;AAE/C;;;GAGG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,aAAa,CAAC;AAExC;;;GAGG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,UAAU,CAAC;AAE5C;;;GAGG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,kBAAkB,CAAC;AAErD;;;GAGG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,mDAAmD,CAAC;AAElF;;;GAGG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,UAAU,CAAC"}
@@ -1,9 +1,27 @@
1
+ import type { ChangeOutcome, ConfigChange } from "../config/reactivity.ts";
1
2
  /**
2
- * Starts the HDHomeRun emulation server if enabled in configuration. This includes generating a DeviceID on first run and starting the HTTP server for discovery
3
- * endpoints. If the configured port is unavailable, HDHR emulation is disabled gracefully.
3
+ * Brings the HDHomeRun emulation surfaces (HTTP + optional UDP discovery) into line with CONFIG.hdhr. Thin delegator to the controller's reconcile so the boot
4
+ * path and the live-apply path share one code path. Failures are reported through the reconcile result and logged at the surface layer; boot treats them as
5
+ * graceful degradation and does not propagate them.
4
6
  */
5
7
  export declare function startHdhrServer(): Promise<void>;
6
8
  /**
7
- * Stops the HDHomeRun emulation server. Called during graceful shutdown.
9
+ * Stops the HDHomeRun emulation surfaces and waits for the underlying sockets to fully release. Awaiting close completion matters when the caller intends to
10
+ * immediately rebind on the same port - skipping the await races the still in-flight async close, since the old listening socket may not yet have released
11
+ * the port, risking EADDRINUSE on the fresh bind. Safe to call more than once: a second call when nothing is running succeeds as a no-op, and a later
12
+ * startHdhrServer rebinds cleanly.
8
13
  */
9
- export declare function stopHdhrServer(): void;
14
+ export declare function stopHdhrServer(): Promise<void>;
15
+ /**
16
+ * Live-applies the subset of a config diff that lives under the "hdhr." prefix. Reconciles the HTTP + UDP surfaces to the new CONFIG.hdhr once (whole desired
17
+ * state, no per-change ordering to get wrong) and then maps each input change to an outcome from the reconciliation result: surface-driving fields (enabled,
18
+ * port) report rejected when their surface failed to bind; deviceId and friendlyName are read live by their consumers and always apply; discoveryEnabled reports
19
+ * rejected only when discovery was requested but failed to bind; an unknown hdhr.* field defers so a future field cannot silently no-op.
20
+ *
21
+ * Exported so tests can invoke the dispatch directly with a synthetic diff. Registered with the reactivity primitive at module load (side effect at the bottom
22
+ * of this file) so production settings saves route here automatically.
23
+ * @param changes - The subset of the diff whose path begins with "hdhr.".
24
+ * @returns Per-change outcomes.
25
+ */
26
+ export declare function applyHdhrConfigChanges(changes: readonly ConfigChange[]): Promise<readonly ChangeOutcome[]>;
27
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/hdhr/index.ts"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AA0S3E;;;;GAIG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC,CAGrD;AAED;;;;;GAKG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC,CAGpD;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,sBAAsB,CAAC,OAAO,EAAE,SAAS,YAAY,EAAE,GAAG,OAAO,CAAC,SAAS,aAAa,EAAE,CAAC,CAyChH"}