shaka-player 4.6.3 → 4.7.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 (608) hide show
  1. package/README.md +1 -0
  2. package/dist/controls.css +1 -1
  3. package/dist/controls.css.map +1 -1
  4. package/dist/deps.js +13 -9
  5. package/dist/locales.js +33 -33
  6. package/dist/shaka-player.compiled.d.ts +47 -4
  7. package/dist/shaka-player.compiled.debug.d.ts +47 -4
  8. package/dist/shaka-player.compiled.debug.externs.js +50 -2
  9. package/dist/shaka-player.compiled.debug.js +408 -376
  10. package/dist/shaka-player.compiled.debug.map +4 -4
  11. package/dist/shaka-player.compiled.externs.js +50 -2
  12. package/dist/shaka-player.compiled.js +1134 -1118
  13. package/dist/shaka-player.compiled.map +4 -4
  14. package/dist/shaka-player.ui.d.ts +69 -5
  15. package/dist/shaka-player.ui.debug.d.ts +69 -5
  16. package/dist/shaka-player.ui.debug.externs.js +82 -2
  17. package/dist/shaka-player.ui.debug.js +457 -420
  18. package/dist/shaka-player.ui.debug.map +4 -4
  19. package/dist/shaka-player.ui.externs.js +82 -2
  20. package/dist/shaka-player.ui.js +1305 -1289
  21. package/dist/shaka-player.ui.map +4 -4
  22. package/externs/mediasession.js +7 -0
  23. package/externs/shaka/abr_manager.js +8 -0
  24. package/externs/shaka/manifest.js +3 -3
  25. package/externs/shaka/player.js +59 -4
  26. package/lib/abr/simple_abr_manager.js +41 -15
  27. package/lib/ads/client_side_ad_manager.js +4 -0
  28. package/lib/ads/media_tailor_ad_manager.js +5 -0
  29. package/lib/ads/server_side_ad_manager.js +4 -0
  30. package/lib/cea/cea708_service.js +1 -1
  31. package/lib/cea/cea708_window.js +95 -7
  32. package/lib/dash/dash_parser.js +55 -11
  33. package/lib/hls/hls_parser.js +17 -5
  34. package/lib/media/adaptation_set_criteria.js +76 -10
  35. package/lib/media/drm_engine.js +0 -3
  36. package/lib/media/media_source_engine.js +42 -18
  37. package/lib/media/segment_reference.js +12 -0
  38. package/lib/media/streaming_engine.js +58 -5
  39. package/lib/media/video_wrapper.js +4 -3
  40. package/lib/player.js +95 -11
  41. package/lib/text/simple_text_displayer.js +8 -7
  42. package/lib/text/text_utils.js +39 -13
  43. package/lib/text/ui_text_displayer.js +20 -11
  44. package/lib/text/web_vtt_generator.js +1 -1
  45. package/lib/util/cmsd_manager.js +269 -0
  46. package/lib/util/content_steering_manager.js +5 -1
  47. package/lib/util/mime_utils.js +6 -2
  48. package/lib/util/periods.js +108 -39
  49. package/lib/util/player_configuration.js +19 -5
  50. package/lib/util/stream_utils.js +82 -13
  51. package/package.json +1 -1
  52. package/ui/audio_language_selection.js +3 -0
  53. package/ui/controls.js +60 -0
  54. package/ui/externs/ui.js +12 -1
  55. package/ui/hidden_fast_forward_button.js +32 -0
  56. package/ui/hidden_rewind_button.js +32 -0
  57. package/ui/hidden_seek_button.js +121 -0
  58. package/ui/less/buttons.less +50 -0
  59. package/ui/less/containers.less +18 -0
  60. package/ui/resolution_selection.js +2 -0
  61. package/ui/ui.js +2 -0
  62. package/.github/ISSUE_TEMPLATE/bug_report.md +0 -75
  63. package/.github/ISSUE_TEMPLATE/feature_request.md +0 -26
  64. package/.github/ISSUE_TEMPLATE/question.md +0 -26
  65. package/.github/config.yml +0 -1
  66. package/.github/workflows/appspot.yaml +0 -39
  67. package/.github/workflows/build-and-test.yaml +0 -222
  68. package/.github/workflows/compute-incremental-coverage.py +0 -265
  69. package/.github/workflows/custom-actions/prep-for-appspot/action.yaml +0 -56
  70. package/.github/workflows/custom-actions/set-commit-status/action.yaml +0 -37
  71. package/.github/workflows/deflake.yaml +0 -31
  72. package/.github/workflows/demo-version-index.yaml +0 -43
  73. package/.github/workflows/nightly-demo.yaml +0 -42
  74. package/.github/workflows/release-please.yaml +0 -193
  75. package/.github/workflows/report-incremental-coverage.yaml +0 -39
  76. package/.github/workflows/safari-homedir-launcher.sh +0 -18
  77. package/.github/workflows/selenium-lab-tests.yaml +0 -370
  78. package/.github/workflows/shaka-bot-commands/command-help.sh +0 -27
  79. package/.github/workflows/shaka-bot-commands/command-test.sh +0 -56
  80. package/.github/workflows/shaka-bot-commands/lib.sh +0 -83
  81. package/.github/workflows/shaka-bot-commands/main.sh +0 -51
  82. package/.github/workflows/sync-labels.yaml +0 -33
  83. package/.github/workflows/talk-to-shaka-bot.yaml +0 -29
  84. package/.github/workflows/update-issues.yaml +0 -31
  85. package/.github/workflows/update-screenshots.yaml +0 -142
  86. package/.github/workflows/validate-pr-title.yaml +0 -27
  87. package/CHANGELOG.md +0 -5764
  88. package/CODE_OF_CONDUCT.md +0 -93
  89. package/CONTRIBUTING.md +0 -76
  90. package/demo/TengwarTelcontar.woff2 +0 -0
  91. package/demo/app_logo_144.png +0 -0
  92. package/demo/app_logo_192.png +0 -0
  93. package/demo/app_logo_256.png +0 -0
  94. package/demo/app_logo_384.png +0 -0
  95. package/demo/app_logo_512.png +0 -0
  96. package/demo/app_manifest.json +0 -29
  97. package/demo/asset_card.js +0 -410
  98. package/demo/autoTemplate.txt +0 -61
  99. package/demo/cast_receiver/idle1.jpg +0 -0
  100. package/demo/cast_receiver/idle2.jpg +0 -0
  101. package/demo/cast_receiver/idle3.jpg +0 -0
  102. package/demo/cast_receiver/index.html +0 -75
  103. package/demo/cast_receiver/receiver_app.css +0 -111
  104. package/demo/cast_receiver/receiver_app.js +0 -158
  105. package/demo/close_button.js +0 -60
  106. package/demo/common/asset.js +0 -511
  107. package/demo/common/assets.js +0 -1635
  108. package/demo/config.js +0 -859
  109. package/demo/custom.js +0 -907
  110. package/demo/customWarning.txt +0 -8
  111. package/demo/demo.less +0 -591
  112. package/demo/demo_uncompiled.js +0 -11
  113. package/demo/demo_utils.js +0 -113
  114. package/demo/favicon.ico +0 -0
  115. package/demo/front.js +0 -156
  116. package/demo/icons/README.md +0 -4
  117. package/demo/icons/baseline-audiotrack-24px.svg +0 -1
  118. package/demo/icons/baseline-closed_caption-24px.svg +0 -1
  119. package/demo/icons/baseline-fast_forward-24px.svg +0 -1
  120. package/demo/icons/baseline-language-24px.svg +0 -1
  121. package/demo/icons/baseline-live_tv-24px.svg +0 -1
  122. package/demo/icons/baseline-subtitles-24px.svg +0 -1
  123. package/demo/icons/baseline-surround_sound-24px.svg +0 -1
  124. package/demo/icons/custom_ad.svg +0 -1
  125. package/demo/icons/custom_box_with_text.svg +0 -1
  126. package/demo/icons/custom_clear_key.svg +0 -1
  127. package/demo/icons/custom_high_definition.svg +0 -1
  128. package/demo/icons/custom_playready.svg +0 -1
  129. package/demo/icons/custom_ultra_high_definition.svg +0 -1
  130. package/demo/icons/custom_widevine.svg +0 -1
  131. package/demo/index.html +0 -173
  132. package/demo/input.js +0 -270
  133. package/demo/input_container.js +0 -218
  134. package/demo/load.js +0 -156
  135. package/demo/main.js +0 -1854
  136. package/demo/search.js +0 -452
  137. package/demo/service_worker.js +0 -355
  138. package/demo/shaka_logo_trans.png +0 -0
  139. package/demo/tooltip.js +0 -29
  140. package/demo/visualizer.js +0 -335
  141. package/demo/visualizer_button.js +0 -84
  142. package/dist/demo.compiled.debug.js +0 -340
  143. package/dist/demo.compiled.debug.map +0 -8
  144. package/dist/demo.compiled.js +0 -340
  145. package/dist/demo.compiled.map +0 -8
  146. package/dist/demo.css +0 -6
  147. package/dist/demo.css.map +0 -1
  148. package/dist/receiver.compiled.debug.js +0 -187
  149. package/dist/receiver.compiled.debug.map +0 -8
  150. package/dist/receiver.compiled.js +0 -187
  151. package/dist/receiver.compiled.map +0 -8
  152. package/docs/announcement-list-join-group.png +0 -0
  153. package/docs/api-mainpage.md +0 -28
  154. package/docs/design/REDESIGN.md +0 -283
  155. package/docs/design/architecture.md +0 -13
  156. package/docs/design/bg-fetch-after.gv +0 -29
  157. package/docs/design/bg-fetch-after.gv.png +0 -0
  158. package/docs/design/bg-fetch-before.gv +0 -18
  159. package/docs/design/bg-fetch-before.gv.png +0 -0
  160. package/docs/design/bg-fetch.md +0 -134
  161. package/docs/design/cast.gv +0 -35
  162. package/docs/design/cast.gv.png +0 -0
  163. package/docs/design/chromecast.md +0 -151
  164. package/docs/design/codec_preferences.md +0 -158
  165. package/docs/design/dash-audio-channels.md +0 -123
  166. package/docs/design/dash-manifests.md +0 -248
  167. package/docs/design/dash-timeline.svg +0 -4
  168. package/docs/design/dataflow.gv +0 -66
  169. package/docs/design/dataflow.gv.png +0 -0
  170. package/docs/design/export.md +0 -70
  171. package/docs/design/fuzzy-locale-matching.md +0 -40
  172. package/docs/design/gap-jumping.md +0 -151
  173. package/docs/design/lcevc-architecture.png +0 -0
  174. package/docs/design/lcevc-demo.png +0 -0
  175. package/docs/design/lcevc-integration.md +0 -72
  176. package/docs/design/locale_compatibility.svg +0 -1
  177. package/docs/design/locales_tree.svg +0 -1
  178. package/docs/design/localization-design-principles.md +0 -158
  179. package/docs/design/newdemo.gv +0 -83
  180. package/docs/design/newdemo.gv.png +0 -0
  181. package/docs/design/offline.gv +0 -43
  182. package/docs/design/offline.gv.png +0 -0
  183. package/docs/design/offline.md +0 -153
  184. package/docs/design/ownership.gv +0 -76
  185. package/docs/design/ownership.gv.png +0 -0
  186. package/docs/design/preload.md +0 -299
  187. package/docs/design/preload.png +0 -0
  188. package/docs/design/talking-about-languages.md +0 -46
  189. package/docs/design/timeline.svg +0 -152
  190. package/docs/design/ui.md +0 -31
  191. package/docs/design/ui_player_relationships.svg +0 -1
  192. package/docs/jsdoc-plugin.js +0 -74
  193. package/docs/jsdoc-template/README.md +0 -1
  194. package/docs/jsdoc-template/publish.js +0 -879
  195. package/docs/jsdoc-template/static/fonts/OpenSans-Bold-webfont.eot +0 -0
  196. package/docs/jsdoc-template/static/fonts/OpenSans-Bold-webfont.svg +0 -1830
  197. package/docs/jsdoc-template/static/fonts/OpenSans-Bold-webfont.woff +0 -0
  198. package/docs/jsdoc-template/static/fonts/OpenSans-BoldItalic-webfont.eot +0 -0
  199. package/docs/jsdoc-template/static/fonts/OpenSans-BoldItalic-webfont.svg +0 -1830
  200. package/docs/jsdoc-template/static/fonts/OpenSans-BoldItalic-webfont.woff +0 -0
  201. package/docs/jsdoc-template/static/fonts/OpenSans-Italic-webfont.eot +0 -0
  202. package/docs/jsdoc-template/static/fonts/OpenSans-Italic-webfont.svg +0 -1830
  203. package/docs/jsdoc-template/static/fonts/OpenSans-Italic-webfont.woff +0 -0
  204. package/docs/jsdoc-template/static/fonts/OpenSans-Light-webfont.eot +0 -0
  205. package/docs/jsdoc-template/static/fonts/OpenSans-Light-webfont.svg +0 -1831
  206. package/docs/jsdoc-template/static/fonts/OpenSans-Light-webfont.woff +0 -0
  207. package/docs/jsdoc-template/static/fonts/OpenSans-LightItalic-webfont.eot +0 -0
  208. package/docs/jsdoc-template/static/fonts/OpenSans-LightItalic-webfont.svg +0 -1835
  209. package/docs/jsdoc-template/static/fonts/OpenSans-LightItalic-webfont.woff +0 -0
  210. package/docs/jsdoc-template/static/fonts/OpenSans-Regular-webfont.eot +0 -0
  211. package/docs/jsdoc-template/static/fonts/OpenSans-Regular-webfont.svg +0 -1831
  212. package/docs/jsdoc-template/static/fonts/OpenSans-Regular-webfont.woff +0 -0
  213. package/docs/jsdoc-template/static/scripts/linenumber.js +0 -44
  214. package/docs/jsdoc-template/static/scripts/show-widget.js +0 -55
  215. package/docs/jsdoc-template/static/styles/jsdoc-default.css +0 -438
  216. package/docs/jsdoc-template/tmpl/augments.tmpl +0 -10
  217. package/docs/jsdoc-template/tmpl/container.tmpl +0 -205
  218. package/docs/jsdoc-template/tmpl/details.tmpl +0 -152
  219. package/docs/jsdoc-template/tmpl/example.tmpl +0 -2
  220. package/docs/jsdoc-template/tmpl/examples.tmpl +0 -13
  221. package/docs/jsdoc-template/tmpl/exceptions.tmpl +0 -32
  222. package/docs/jsdoc-template/tmpl/layout.tmpl +0 -50
  223. package/docs/jsdoc-template/tmpl/mainpage.tmpl +0 -14
  224. package/docs/jsdoc-template/tmpl/members.tmpl +0 -47
  225. package/docs/jsdoc-template/tmpl/method.tmpl +0 -140
  226. package/docs/jsdoc-template/tmpl/modifies.tmpl +0 -14
  227. package/docs/jsdoc-template/tmpl/params.tmpl +0 -131
  228. package/docs/jsdoc-template/tmpl/properties.tmpl +0 -125
  229. package/docs/jsdoc-template/tmpl/returns.tmpl +0 -19
  230. package/docs/jsdoc-template/tmpl/source.tmpl +0 -8
  231. package/docs/jsdoc-template/tmpl/tutorial.tmpl +0 -21
  232. package/docs/jsdoc-template/tmpl/type.tmpl +0 -7
  233. package/docs/jsdoc.conf.json +0 -38
  234. package/docs/shaka-player-logo.png +0 -0
  235. package/docs/style.md +0 -174
  236. package/docs/tutorials/a11y.md +0 -64
  237. package/docs/tutorials/ad_monetization.md +0 -292
  238. package/docs/tutorials/application-level-redirects.md +0 -94
  239. package/docs/tutorials/architecture.md +0 -32
  240. package/docs/tutorials/basic-usage.md +0 -89
  241. package/docs/tutorials/blob-url.md +0 -15
  242. package/docs/tutorials/config.md +0 -148
  243. package/docs/tutorials/debugging.md +0 -189
  244. package/docs/tutorials/drm-config.md +0 -274
  245. package/docs/tutorials/errors.md +0 -95
  246. package/docs/tutorials/fairplay.md +0 -242
  247. package/docs/tutorials/faq.md +0 -252
  248. package/docs/tutorials/index.json +0 -29
  249. package/docs/tutorials/lcevc.md +0 -118
  250. package/docs/tutorials/license-server-auth.md +0 -248
  251. package/docs/tutorials/license-wrapping.md +0 -168
  252. package/docs/tutorials/manifest-parser.md +0 -365
  253. package/docs/tutorials/network-and-buffering-config.md +0 -119
  254. package/docs/tutorials/offline.md +0 -683
  255. package/docs/tutorials/plugins.md +0 -184
  256. package/docs/tutorials/selenium-grid-config.md +0 -174
  257. package/docs/tutorials/service-worker.md +0 -106
  258. package/docs/tutorials/ui-customization.md +0 -288
  259. package/docs/tutorials/ui.md +0 -230
  260. package/docs/tutorials/upgrade-manifest.md +0 -281
  261. package/docs/tutorials/upgrade.md +0 -104
  262. package/docs/tutorials/welcome.md +0 -108
  263. package/docs/tutorials/widevine-service-certs.md +0 -45
  264. package/karma.conf.js +0 -879
  265. package/maintained-branches.md +0 -15
  266. package/roadmap.md +0 -186
  267. package/test/abr/simple_abr_manager_unit.js +0 -398
  268. package/test/ads/ad_manager_unit.js +0 -260
  269. package/test/assumptions/uint8_array_unit.js +0 -22
  270. package/test/cast/cast_proxy_unit.js +0 -736
  271. package/test/cast/cast_receiver_integration.js +0 -488
  272. package/test/cast/cast_receiver_unit.js +0 -1183
  273. package/test/cast/cast_sender_unit.js +0 -973
  274. package/test/cast/cast_utils_unit.js +0 -311
  275. package/test/cea/cea608_memory_unit.js +0 -411
  276. package/test/cea/cea708_service_unit.js +0 -674
  277. package/test/cea/cea708_window_unit.js +0 -373
  278. package/test/cea/cea_decoder_unit.js +0 -615
  279. package/test/cea/dtvcc_packet_builder_unit.js +0 -158
  280. package/test/cea/dtvcc_packet_unit.js +0 -60
  281. package/test/cea/mp4_cea_parser_unit.js +0 -127
  282. package/test/codec_switching/codec_switching_integration.js +0 -182
  283. package/test/dash/dash_parser_content_protection_unit.js +0 -998
  284. package/test/dash/dash_parser_integration.js +0 -74
  285. package/test/dash/dash_parser_live_unit.js +0 -1542
  286. package/test/dash/dash_parser_manifest_unit.js +0 -3121
  287. package/test/dash/dash_parser_segment_base_unit.js +0 -421
  288. package/test/dash/dash_parser_segment_list_unit.js +0 -380
  289. package/test/dash/dash_parser_segment_template_unit.js +0 -910
  290. package/test/dash/mpd_utils_unit.js +0 -794
  291. package/test/demo/demo_unit.js +0 -108
  292. package/test/deprecate/enforcer_unit.js +0 -74
  293. package/test/deprecate/version_unit.js +0 -57
  294. package/test/hls/hls_live_unit.js +0 -1330
  295. package/test/hls/hls_parser_unit.js +0 -5276
  296. package/test/hls/manifest_text_parser_unit.js +0 -545
  297. package/test/media/adaptation_set_criteria_unit.js +0 -806
  298. package/test/media/adaptation_set_unit.js +0 -229
  299. package/test/media/buffering_observer_unit.js +0 -143
  300. package/test/media/closed_caption_parser_unit.js +0 -18
  301. package/test/media/content_workarounds_unit.js +0 -43
  302. package/test/media/drm_engine_integration.js +0 -356
  303. package/test/media/drm_engine_unit.js +0 -2778
  304. package/test/media/media_source_engine_integration.js +0 -691
  305. package/test/media/media_source_engine_unit.js +0 -1512
  306. package/test/media/mp4_segment_index_parser_unit.js +0 -80
  307. package/test/media/play_rate_controller_unit.js +0 -69
  308. package/test/media/playhead_unit.js +0 -1394
  309. package/test/media/presentation_timeline_unit.js +0 -477
  310. package/test/media/quality_observer_unit.js +0 -138
  311. package/test/media/region_observer_unit.js +0 -374
  312. package/test/media/region_timeline_unit.js +0 -139
  313. package/test/media/segment_index_unit.js +0 -1080
  314. package/test/media/segment_prefetch_unit.js +0 -243
  315. package/test/media/segment_reference_unit.js +0 -63
  316. package/test/media/stall_detector_unit.js +0 -184
  317. package/test/media/streaming_engine_integration.js +0 -632
  318. package/test/media/streaming_engine_unit.js +0 -4211
  319. package/test/media/time_ranges_utils_unit.js +0 -123
  320. package/test/media/webm_segment_index_parser_unit.js +0 -90
  321. package/test/mss/mss_parser_content_protection_unit.js +0 -49
  322. package/test/mss/mss_parser_unit.js +0 -474
  323. package/test/mss/mss_player_integration.js +0 -124
  324. package/test/net/data_uri_plugin_unit.js +0 -105
  325. package/test/net/http_plugin_unit.js +0 -439
  326. package/test/net/networking_engine_unit.js +0 -1236
  327. package/test/net/networking_utils_unit.js +0 -37
  328. package/test/offline/download_progress_estimator_unit.js +0 -90
  329. package/test/offline/indexeddb_storage_unit.js +0 -192
  330. package/test/offline/manifest_convert_unit.js +0 -622
  331. package/test/offline/offline_integration.js +0 -168
  332. package/test/offline/offline_manifest_parser_unit.js +0 -231
  333. package/test/offline/offline_scheme_unit.js +0 -154
  334. package/test/offline/offline_uri_unit.js +0 -59
  335. package/test/offline/storage_compatibility_unit.js +0 -344
  336. package/test/offline/storage_integration.js +0 -1858
  337. package/test/player_external.js +0 -237
  338. package/test/player_integration.js +0 -1371
  339. package/test/player_load_graph_integration.js +0 -865
  340. package/test/player_src_equals_external.js +0 -154
  341. package/test/player_src_equals_integration.js +0 -527
  342. package/test/player_unit.js +0 -4434
  343. package/test/polyfill/media_capabilities_unit.js +0 -277
  344. package/test/polyfill/patchedmediakeys_apple_unit.js +0 -130
  345. package/test/test/assets/3675/chunk-stream0-00001.m4s +0 -0
  346. package/test/test/assets/3675/chunk-stream0-00002.m4s +0 -0
  347. package/test/test/assets/3675/chunk-stream0-00003.m4s +0 -0
  348. package/test/test/assets/3675/chunk-stream0-00004.m4s +0 -0
  349. package/test/test/assets/3675/chunk-stream0-00005.m4s +0 -0
  350. package/test/test/assets/3675/chunk-stream0-00006.m4s +0 -0
  351. package/test/test/assets/3675/chunk-stream0-00007.m4s +0 -0
  352. package/test/test/assets/3675/dash_0.mpd +0 -30
  353. package/test/test/assets/3675/dash_1.mpd +0 -30
  354. package/test/test/assets/3675/dash_2.mpd +0 -30
  355. package/test/test/assets/3675/dash_3.mpd +0 -30
  356. package/test/test/assets/3675/dash_4.mpd +0 -30
  357. package/test/test/assets/3675/dash_5.mpd +0 -26
  358. package/test/test/assets/3675/init-stream0.m4s +0 -0
  359. package/test/test/assets/audio-xhe-aac.mp4 +0 -0
  360. package/test/test/assets/audio.ts +0 -0
  361. package/test/test/assets/captions-test.ts +0 -0
  362. package/test/test/assets/cea-init.mp4 +0 -0
  363. package/test/test/assets/cea-segment.mp4 +0 -0
  364. package/test/test/assets/chapters.srt +0 -11
  365. package/test/test/assets/chapters.vtt +0 -10
  366. package/test/test/assets/chapters2.vtt +0 -10
  367. package/test/test/assets/dash-aes-128/Fragments(video=0,format=mpd-time-csf) +0 -0
  368. package/test/test/assets/dash-aes-128/Fragments(video=20000000,format=mpd-time-csf) +0 -0
  369. package/test/test/assets/dash-aes-128/Fragments(video=40000000,format=mpd-time-csf) +0 -0
  370. package/test/test/assets/dash-aes-128/Fragments(video=60000000,format=mpd-time-csf) +0 -0
  371. package/test/test/assets/dash-aes-128/Fragments(video=i,format=mpd-time-csf) +0 -0
  372. package/test/test/assets/dash-aes-128/dash.mpd +0 -18
  373. package/test/test/assets/dash-aes-128/license +0 -1
  374. package/test/test/assets/dash-multi-codec/audio_en_2c_128k_aac.mp4 +0 -0
  375. package/test/test/assets/dash-multi-codec/audio_es_2c_64k_opus.webm +0 -0
  376. package/test/test/assets/dash-multi-codec/dash.mpd +0 -32
  377. package/test/test/assets/dash-multi-codec/video_144p_108k_h264.mp4 +0 -0
  378. package/test/test/assets/db-dump-v1.json +0 -1
  379. package/test/test/assets/db-dump-v2-broken.json +0 -1
  380. package/test/test/assets/db-dump-v2-clean.json +0 -1
  381. package/test/test/assets/db-dump-v3.json +0 -1
  382. package/test/test/assets/db-dump-v4-broken.json +0 -1
  383. package/test/test/assets/db-dump-v5.json +0 -1
  384. package/test/test/assets/empty_caption_video_init.mp4 +0 -0
  385. package/test/test/assets/empty_caption_video_segment.mp4 +0 -0
  386. package/test/test/assets/encrypted-sintel-audio-init.mp4 +0 -0
  387. package/test/test/assets/encrypted-sintel-audio-segment.mp4 +0 -0
  388. package/test/test/assets/encrypted-sintel-video-init.mp4 +0 -0
  389. package/test/test/assets/encrypted-sintel-video-segment.mp4 +0 -0
  390. package/test/test/assets/green-pixel.mp4 +0 -0
  391. package/test/test/assets/green-pixel.txt +0 -15
  392. package/test/test/assets/h265-cea-init.mp4 +0 -0
  393. package/test/test/assets/h265-cea-segment.mp4 +0 -0
  394. package/test/test/assets/hls-raw-aac/fileSequence0.aac +0 -0
  395. package/test/test/assets/hls-raw-aac/fileSequence1.aac +0 -0
  396. package/test/test/assets/hls-raw-aac/fileSequence2.aac +0 -0
  397. package/test/test/assets/hls-raw-aac/fileSequence3.aac +0 -0
  398. package/test/test/assets/hls-raw-aac/manifest.m3u8 +0 -4
  399. package/test/test/assets/hls-raw-aac/stream.m4a.m3u8 +0 -14
  400. package/test/test/assets/hls-raw-ac3/fileSequence0.ac3 +0 -0
  401. package/test/test/assets/hls-raw-ac3/fileSequence1.ac3 +0 -0
  402. package/test/test/assets/hls-raw-ac3/fileSequence2.ac3 +0 -0
  403. package/test/test/assets/hls-raw-ac3/fileSequence3.ac3 +0 -0
  404. package/test/test/assets/hls-raw-ac3/fileSequence4.ac3 +0 -0
  405. package/test/test/assets/hls-raw-ac3/fileSequence5.ac3 +0 -0
  406. package/test/test/assets/hls-raw-ac3/fileSequence6.ac3 +0 -0
  407. package/test/test/assets/hls-raw-ac3/fileSequence7.ac3 +0 -0
  408. package/test/test/assets/hls-raw-ac3/prog_index.m3u8 +0 -31
  409. package/test/test/assets/hls-raw-ec3/fileSequence0.ec3 +0 -0
  410. package/test/test/assets/hls-raw-ec3/fileSequence1.ec3 +0 -0
  411. package/test/test/assets/hls-raw-ec3/fileSequence2.ec3 +0 -0
  412. package/test/test/assets/hls-raw-ec3/fileSequence3.ec3 +0 -0
  413. package/test/test/assets/hls-raw-ec3/fileSequence4.ec3 +0 -0
  414. package/test/test/assets/hls-raw-ec3/fileSequence5.ec3 +0 -0
  415. package/test/test/assets/hls-raw-ec3/fileSequence6.ec3 +0 -0
  416. package/test/test/assets/hls-raw-ec3/fileSequence7.ec3 +0 -0
  417. package/test/test/assets/hls-raw-ec3/prog_index.m3u8 +0 -31
  418. package/test/test/assets/hls-raw-mp3/chunklist_w905519204.m3u8 +0 -13
  419. package/test/test/assets/hls-raw-mp3/media_w905519204_0.mp3 +0 -0
  420. package/test/test/assets/hls-raw-mp3/media_w905519204_1.mp3 +0 -0
  421. package/test/test/assets/hls-raw-mp3/media_w905519204_2.mp3 +0 -0
  422. package/test/test/assets/hls-raw-mp3/media_w905519204_3.mp3 +0 -0
  423. package/test/test/assets/hls-raw-mp3/playlist.m3u8 +0 -4
  424. package/test/test/assets/hls-ts-aac/playlist.m3u8 +0 -23
  425. package/test/test/assets/hls-ts-aac/segment_0.ts +0 -0
  426. package/test/test/assets/hls-ts-aac/segment_1.ts +0 -0
  427. package/test/test/assets/hls-ts-aac/segment_2.ts +0 -0
  428. package/test/test/assets/hls-ts-aac/segment_3.ts +0 -0
  429. package/test/test/assets/hls-ts-aac/segment_4.ts +0 -0
  430. package/test/test/assets/hls-ts-aac/segment_5.ts +0 -0
  431. package/test/test/assets/hls-ts-aac/segment_6.ts +0 -0
  432. package/test/test/assets/hls-ts-aac/segment_7.ts +0 -0
  433. package/test/test/assets/hls-ts-ac3/ChID_voices_6ch_640kbps_dd_sub_0000.ts +0 -0
  434. package/test/test/assets/hls-ts-ac3/ChID_voices_6ch_640kbps_dd_sub_0001.ts +0 -0
  435. package/test/test/assets/hls-ts-ac3/ChID_voices_6ch_640kbps_dd_sub_0002.ts +0 -0
  436. package/test/test/assets/hls-ts-ac3/ChID_voices_6ch_640kbps_dd_sub_0003.ts +0 -0
  437. package/test/test/assets/hls-ts-ac3/ChID_voices_6ch_640kbps_dd_sub_0004.ts +0 -0
  438. package/test/test/assets/hls-ts-ac3/ChID_voices_6ch_640kbps_dd_sub_0005.ts +0 -0
  439. package/test/test/assets/hls-ts-ac3/prog_index.m3u8 +0 -19
  440. package/test/test/assets/hls-ts-ec3/ChID_voices_6ch_256kbps_ddp_sub_0000.ts +0 -0
  441. package/test/test/assets/hls-ts-ec3/ChID_voices_6ch_256kbps_ddp_sub_0001.ts +0 -0
  442. package/test/test/assets/hls-ts-ec3/ChID_voices_6ch_256kbps_ddp_sub_0002.ts +0 -0
  443. package/test/test/assets/hls-ts-ec3/ChID_voices_6ch_256kbps_ddp_sub_0003.ts +0 -0
  444. package/test/test/assets/hls-ts-ec3/ChID_voices_6ch_256kbps_ddp_sub_0004.ts +0 -0
  445. package/test/test/assets/hls-ts-ec3/ChID_voices_6ch_256kbps_ddp_sub_0005.ts +0 -0
  446. package/test/test/assets/hls-ts-ec3/prog_index.m3u8 +0 -19
  447. package/test/test/assets/hls-ts-h264/fileSequence0.ts +0 -0
  448. package/test/test/assets/hls-ts-h264/fileSequence1.ts +0 -0
  449. package/test/test/assets/hls-ts-h264/fileSequence2.ts +0 -0
  450. package/test/test/assets/hls-ts-h264/fileSequence3.ts +0 -0
  451. package/test/test/assets/hls-ts-h264/fileSequence4.ts +0 -0
  452. package/test/test/assets/hls-ts-h264/fileSequence5.ts +0 -0
  453. package/test/test/assets/hls-ts-h264/prog_index.m3u8 +0 -25
  454. package/test/test/assets/hls-ts-h265/0.ts +0 -0
  455. package/test/test/assets/hls-ts-h265/hevc.m3u8 +0 -6
  456. package/test/test/assets/hls-ts-h265/index.m3u8 +0 -7
  457. package/test/test/assets/hls-ts-mp3/manifest.m3u8 +0 -13
  458. package/test/test/assets/hls-ts-mp3/media_w239891843_0.ts +0 -0
  459. package/test/test/assets/hls-ts-mp3/media_w239891843_1.ts +0 -0
  460. package/test/test/assets/hls-ts-mp3/media_w239891843_2.ts +0 -0
  461. package/test/test/assets/hls-ts-mp3/media_w239891843_3.ts +0 -0
  462. package/test/test/assets/hls-ts-muxed-aac-h264/chunk.m3u8 +0 -17
  463. package/test/test/assets/hls-ts-muxed-aac-h264/n_0_0_0.ts +0 -0
  464. package/test/test/assets/hls-ts-muxed-aac-h264/n_1_0_0.ts +0 -0
  465. package/test/test/assets/hls-ts-muxed-aac-h264/n_2_0_0.ts +0 -0
  466. package/test/test/assets/hls-ts-muxed-aac-h264/n_3_0_0.ts +0 -0
  467. package/test/test/assets/hls-ts-muxed-aac-h264/n_4_0_0.ts +0 -0
  468. package/test/test/assets/hls-ts-muxed-aac-h264/n_5_0_0.ts +0 -0
  469. package/test/test/assets/hls-ts-muxed-aac-h264/playlist.m3u8 +0 -4
  470. package/test/test/assets/hls-ts-muxed-aac-h265/0.ts +0 -0
  471. package/test/test/assets/hls-ts-muxed-aac-h265/1.ts +0 -0
  472. package/test/test/assets/hls-ts-muxed-aac-h265/media.m3u8 +0 -9
  473. package/test/test/assets/hls-ts-muxed-ac3-h264/media.m3u8 +0 -24
  474. package/test/test/assets/hls-ts-muxed-ac3-h264/s_00000.ts +0 -0
  475. package/test/test/assets/hls-ts-muxed-ac3-h264/s_00001.ts +0 -0
  476. package/test/test/assets/hls-ts-muxed-ac3-h264/s_00002.ts +0 -0
  477. package/test/test/assets/hls-ts-muxed-ac3-h264/s_00003.ts +0 -0
  478. package/test/test/assets/hls-ts-muxed-ac3-h264/s_00004.ts +0 -0
  479. package/test/test/assets/hls-ts-muxed-ac3-h264/s_00005.ts +0 -0
  480. package/test/test/assets/hls-ts-muxed-ec3-h264/ChID_voices_1280x720p_25fps_h264_6ch_256kbps_ddp_sub_0000.ts +0 -0
  481. package/test/test/assets/hls-ts-muxed-ec3-h264/ChID_voices_1280x720p_25fps_h264_6ch_256kbps_ddp_sub_0001.ts +0 -0
  482. package/test/test/assets/hls-ts-muxed-ec3-h264/ChID_voices_1280x720p_25fps_h264_6ch_256kbps_ddp_sub_0002.ts +0 -0
  483. package/test/test/assets/hls-ts-muxed-ec3-h264/ChID_voices_1280x720p_25fps_h264_6ch_256kbps_ddp_sub_0003.ts +0 -0
  484. package/test/test/assets/hls-ts-muxed-ec3-h264/prog_index.m3u8 +0 -14
  485. package/test/test/assets/hls-ts-muxed-mp3-h264/index.m3u8 +0 -23
  486. package/test/test/assets/hls-ts-muxed-mp3-h264/seg-1-v1-a1.ts +0 -0
  487. package/test/test/assets/hls-ts-muxed-mp3-h264/seg-2-v1-a1.ts +0 -0
  488. package/test/test/assets/hls-ts-muxed-mp3-h264/seg-3-v1-a1.ts +0 -0
  489. package/test/test/assets/hls-ts-muxed-mp3-h264/seg-4-v1-a1.ts +0 -0
  490. package/test/test/assets/hls-ts-muxed-mp3-h264/seg-5-v1-a1.ts +0 -0
  491. package/test/test/assets/hls-ts-muxed-mp3-h264/seg-6-v1-a1.ts +0 -0
  492. package/test/test/assets/hls-ts-muxed-mp3-h264/seg-7-v1-a1.ts +0 -0
  493. package/test/test/assets/hls-ts-muxed-mp3-h264/seg-8-v1-a1.ts +0 -0
  494. package/test/test/assets/id3-metadata.aac +0 -0
  495. package/test/test/assets/id3-metadata.ts +0 -0
  496. package/test/test/assets/index-segment.mp4 +0 -0
  497. package/test/test/assets/index-segment.webm +0 -0
  498. package/test/test/assets/init-segment.webm +0 -0
  499. package/test/test/assets/large_file.mpd +0 -4930
  500. package/test/test/assets/multidrm-audio-init.mp4 +0 -0
  501. package/test/test/assets/multidrm-audio-segment.mp4 +0 -0
  502. package/test/test/assets/multidrm-video-init.mp4 +0 -0
  503. package/test/test/assets/multidrm-video-segment.mp4 +0 -0
  504. package/test/test/assets/multiple-trun-init.mp4 +0 -0
  505. package/test/test/assets/multiple-trun-segment.mp4 +0 -0
  506. package/test/test/assets/sintel-audio-init.mp4 +0 -0
  507. package/test/test/assets/sintel-audio-segment.mp4 +0 -0
  508. package/test/test/assets/sintel-video-init.mp4 +0 -0
  509. package/test/test/assets/sintel-video-segment.mp4 +0 -0
  510. package/test/test/assets/small.mp4 +0 -0
  511. package/test/test/assets/text-clip-alt.vtt +0 -63
  512. package/test/test/assets/text-clip.vtt +0 -63
  513. package/test/test/assets/thumbnails-sprites.vtt +0 -10
  514. package/test/test/assets/thumbnails.vtt +0 -10
  515. package/test/test/assets/ttml-init.mp4 +0 -0
  516. package/test/test/assets/ttml-segment-multiplemdat.mp4 +0 -0
  517. package/test/test/assets/ttml-segment.mp4 +0 -0
  518. package/test/test/assets/video.ts +0 -0
  519. package/test/test/assets/vtt-init.mp4 +0 -0
  520. package/test/test/assets/vtt-segment-multi-payload.mp4 +0 -0
  521. package/test/test/assets/vtt-segment-no-duration.mp4 +0 -0
  522. package/test/test/assets/vtt-segment-settings.mp4 +0 -0
  523. package/test/test/assets/vtt-segment.mp4 +0 -0
  524. package/test/test/boot.js +0 -495
  525. package/test/test/externs/filters.js +0 -44
  526. package/test/test/externs/fontfaceonload.js +0 -29
  527. package/test/test/externs/jasmine.js +0 -670
  528. package/test/test/externs/karma.js +0 -26
  529. package/test/test/externs/require.js +0 -21
  530. package/test/test/externs/sprintf.js +0 -18
  531. package/test/test/namespace.js +0 -10
  532. package/test/test/util/canned_idb.js +0 -379
  533. package/test/test/util/cea_utils.js +0 -60
  534. package/test/test/util/dash_parser_util.js +0 -329
  535. package/test/test/util/fake_ad.js +0 -321
  536. package/test/test/util/fake_ad_manager.js +0 -122
  537. package/test/test/util/fake_demo_main.js +0 -144
  538. package/test/test/util/fake_drm_engine.js +0 -103
  539. package/test/test/util/fake_media_source_engine.js +0 -464
  540. package/test/test/util/fake_networking_engine.js +0 -381
  541. package/test/test/util/fake_segment_prefetch.js +0 -84
  542. package/test/test/util/fake_text_displayer.js +0 -60
  543. package/test/test/util/id3_generator.js +0 -100
  544. package/test/test/util/indexeddb_utils.js +0 -124
  545. package/test/test/util/jasmine_fetch.js +0 -382
  546. package/test/test/util/layout_tests.js +0 -434
  547. package/test/test/util/loader.js +0 -88
  548. package/test/test/util/manifest_generator.js +0 -705
  549. package/test/test/util/manifest_parser_util.js +0 -101
  550. package/test/test/util/mss_parser_util.js +0 -119
  551. package/test/test/util/offline_utils.js +0 -105
  552. package/test/test/util/simple_fakes.js +0 -535
  553. package/test/test/util/stream_generator.js +0 -676
  554. package/test/test/util/streaming_engine_util.js +0 -506
  555. package/test/test/util/test_scheme.js +0 -778
  556. package/test/test/util/ttml_utils.js +0 -77
  557. package/test/test/util/ui_utils.js +0 -183
  558. package/test/test/util/util.js +0 -374
  559. package/test/test/util/waiter.js +0 -406
  560. package/test/text/cue_integration.js +0 -51
  561. package/test/text/lrc_text_parser_unit.js +0 -98
  562. package/test/text/mp4_ttml_parser_unit.js +0 -171
  563. package/test/text/mp4_vtt_parser_unit.js +0 -195
  564. package/test/text/sbv_text_parser_unit.js +0 -81
  565. package/test/text/simple_text_displayer_unit.js +0 -468
  566. package/test/text/srt_text_parser_unit.js +0 -163
  567. package/test/text/ssa_text_parser_unit.js +0 -382
  568. package/test/text/text_displayer_layout_unit.js +0 -323
  569. package/test/text/text_engine_unit.js +0 -500
  570. package/test/text/text_track_integration.js +0 -186
  571. package/test/text/ttml_text_parser_unit.js +0 -2176
  572. package/test/text/ui_text_displayer_unit.js +0 -608
  573. package/test/text/vtt_text_parser_unit.js +0 -1363
  574. package/test/text/web_vtt_generator_unit.js +0 -144
  575. package/test/text/web_vtt_layout_integration.js +0 -524
  576. package/test/transmuxer/transmuxer_engine_integration.js +0 -69
  577. package/test/transmuxer/transmuxer_integration.js +0 -443
  578. package/test/ui/ad_ui_unit.js +0 -369
  579. package/test/ui/localization_unit.js +0 -508
  580. package/test/ui/ui_customization_unit.js +0 -208
  581. package/test/ui/ui_integration.js +0 -669
  582. package/test/ui/ui_unit.js +0 -902
  583. package/test/util/abortable_operation_unit.js +0 -624
  584. package/test/util/array_utils_unit.js +0 -58
  585. package/test/util/buffer_utils_unit.js +0 -185
  586. package/test/util/cmcd_manager_unit.js +0 -440
  587. package/test/util/content_steering_manager_unit.js +0 -427
  588. package/test/util/data_view_reader_unit.js +0 -254
  589. package/test/util/ebml_parser_unit.js +0 -297
  590. package/test/util/event_manager_unit.js +0 -185
  591. package/test/util/fake_event_target_unit.js +0 -123
  592. package/test/util/id3_utils_unit.js +0 -168
  593. package/test/util/iterables_unit.js +0 -68
  594. package/test/util/language_utils_unit.js +0 -240
  595. package/test/util/manifest_parser_utils_unit.js +0 -55
  596. package/test/util/mime_utils_unit.js +0 -64
  597. package/test/util/mp4_box_parsers_unit.js +0 -246
  598. package/test/util/mp4_parser_unit.js +0 -373
  599. package/test/util/multi_map_unit.js +0 -94
  600. package/test/util/object_utils_unit.js +0 -79
  601. package/test/util/periods_unit.js +0 -1623
  602. package/test/util/pssh_unit.js +0 -226
  603. package/test/util/state_history_unit.js +0 -101
  604. package/test/util/stream_utils_unit.js +0 -1068
  605. package/test/util/string_utils_unit.js +0 -166
  606. package/test/util/text_parser_unit.js +0 -165
  607. package/test/util/ts_parser_unit.js +0 -77
  608. package/test/util/xml_utils_unit.js +0 -444
package/demo/main.js DELETED
@@ -1,1854 +0,0 @@
1
- /*! @license
2
- * Shaka Player
3
- * Copyright 2016 Google LLC
4
- * SPDX-License-Identifier: Apache-2.0
5
- */
6
-
7
-
8
- goog.provide('shakaDemo.Main');
9
-
10
- goog.require('ShakaDemoAssetInfo');
11
- goog.require('goog.asserts');
12
- goog.require('shakaDemo.CloseButton');
13
- goog.require('shakaDemo.Utils');
14
- goog.require('shakaDemo.Visualizer');
15
- goog.require('shakaDemo.VisualizerButton');
16
-
17
- /**
18
- * Shaka Player demo, main section.
19
- * This controls the header and the footer, and contains all methods that should
20
- * be shared by multiple page layouts (loading assets, setting/checking
21
- * configuration, etc).
22
- */
23
- shakaDemo.Main = class {
24
- /** */
25
- constructor() {
26
- /** @private {HTMLVideoElement} */
27
- this.video_ = null;
28
-
29
- /** @private {HTMLElement} */
30
- this.container_ = null;
31
-
32
- /** @private {shaka.Player} */
33
- this.player_ = null;
34
-
35
- /** @type {?ShakaDemoAssetInfo} */
36
- this.selectedAsset = null;
37
-
38
- /** @type {shaka.ui.Localization} */
39
- this.localization_ = null;
40
-
41
- /**
42
- * The configuration asked for by the user. I.e., not from the asset.
43
- * @private {shaka.extern.PlayerConfiguration}
44
- */
45
- this.desiredConfig_;
46
-
47
- /** @private {shaka.extern.PlayerConfiguration} */
48
- this.defaultConfig_;
49
-
50
- /** @private {boolean} */
51
- this.fullyLoaded_ = false;
52
-
53
- /** @private {?shaka.ui.Controls} */
54
- this.controls_ = null;
55
-
56
- /** @private {?Array.<shaka.extern.StoredContent>} */
57
- this.initialStoredList_;
58
-
59
- /** @private {boolean} */
60
- this.trickPlayControlsEnabled_ = false;
61
-
62
- /** @private {boolean} */
63
- this.nativeControlsEnabled_ = false;
64
-
65
- /** @private {shaka.extern.SupportType} */
66
- this.support_;
67
-
68
- /** @private {string} */
69
- this.uiLocale_ = '';
70
-
71
- /** @private {boolean} */
72
- this.noInput_ = false;
73
-
74
- /** @private {!HTMLAnchorElement} */
75
- this.errorDisplayLink_ = /** @type {!HTMLAnchorElement} */(
76
- document.getElementById('error-display-link'));
77
-
78
- /** @private {?number} */
79
- this.currentErrorSeverity_ = null;
80
-
81
- // Override the icon for the MDL library's menu button.
82
- // eslint-disable-next-line no-restricted-syntax
83
- MaterialLayout.prototype.Constant_.MENU_ICON = 'settings';
84
-
85
- /** @private {?shakaDemo.Visualizer} */
86
- this.visualizer_ = null;
87
- }
88
-
89
- /**
90
- * This function contains the steps of initialization that should be followed
91
- * whether or not the demo successfully set up.
92
- * @private
93
- */
94
- initCommon_() {
95
- // Display uncaught exceptions. Note that this doesn't seem to work in IE.
96
- // See shakaDemo.Main.initWrapper for a failsafe that works for init-time
97
- // errors on IE.
98
- window.addEventListener('error', (event) => {
99
- const errorEvent = /** @type {!ErrorEvent} */(event);
100
-
101
- // Exception to the exceptions we catch: ChromeVox (screenreader) always
102
- // throws an error as of Chrome 73. Screen these out since they are
103
- // unrelated to our application and we can't control them.
104
- if (errorEvent.message.includes('cvox.Api')) {
105
- return;
106
- }
107
-
108
- this.onError_(/** @type {!shaka.util.Error} */ (errorEvent.error));
109
- });
110
-
111
- // Set up event listeners.
112
- document.getElementById('error-display-close-button').addEventListener(
113
- 'click', (event) => this.closeError_());
114
-
115
- // Set up version strings in the appropriate divs.
116
- this.setUpVersionStrings_();
117
- }
118
-
119
- /**
120
- * Set up the application with errors to show that load failed.
121
- * This does not dispatch the shaka-main-loaded event, so it will not cause
122
- * the nav bar buttons to be set up.
123
- * @param {!shaka.ui.Overlay.FailReasonCode} reasonCode
124
- */
125
- initFailed(reasonCode) {
126
- this.initCommon_();
127
-
128
- // Set up version links, so the user can switch to compiled mode if
129
- // necessary.
130
- this.makeVersionLinks_();
131
-
132
- const errorCloseButton =
133
- document.getElementById('error-display-close-button');
134
- errorCloseButton.style.display = 'none';
135
-
136
- // Update the componentHandler, to account for any new MDL elements added.
137
- componentHandler.upgradeDom();
138
-
139
- // Disable elements that should not be used.
140
- const elementsToDisable = [];
141
- const disableClass = 'should-disable-on-fail';
142
- for (const element of document.getElementsByClassName(disableClass)) {
143
- elementsToDisable.push(element);
144
- }
145
- // The hamburger menu close button is added programmatically by MDL, and
146
- // thus isn't given our 'disableonfail' class.
147
- for (const element of document.getElementsByClassName(
148
- 'mdl-layout__drawer-button')) {
149
- elementsToDisable.push(element);
150
- }
151
- for (const element of elementsToDisable) {
152
- element.tabIndex = -1;
153
- element.classList.add('disabled-by-fail');
154
- }
155
-
156
- // Process a synthetic error about lack of browser support.
157
- const severity = shaka.util.Error.Severity.CRITICAL;
158
- let href = '';
159
- let message = '';
160
- switch (reasonCode) {
161
- case shaka.ui.Overlay.FailReasonCode.NO_BROWSER_SUPPORT:
162
- message = 'Your browser is not supported!';
163
- href = 'https://github.com/shaka-project/shaka-player#' +
164
- 'platform-and-browser-support-matrix';
165
- break;
166
- case shaka.ui.Overlay.FailReasonCode.PLAYER_FAILED_TO_LOAD:
167
- message = 'Shaka Player failed to load! If you are using an adblocker' +
168
- ', try switching to compiled mode at the bottom of the page.';
169
- break;
170
- }
171
- this.handleError_(severity, message, href);
172
- }
173
-
174
- /**
175
- * Initialize the application.
176
- */
177
- async init() {
178
- this.initCommon_();
179
-
180
- this.support_ = await shaka.Player.probeSupport();
181
-
182
- this.video_ =
183
- /** @type {!HTMLVideoElement} */ (document.getElementById('video'));
184
- this.video_.poster = shakaDemo.Main.mainPoster_;
185
-
186
- this.container_ = /** @type {!HTMLElement} */(
187
- document.getElementsByClassName('video-container')[0]);
188
-
189
- if (navigator.serviceWorker) {
190
- console.debug('Registering service worker.');
191
- // NOTE: This can sometimes hang on iOS 12, so let's not wait for it to
192
- // complete before setting up the app. We don't even use the Promise
193
- // result or react to the registration failure except to log it.
194
- navigator.serviceWorker.register('service_worker.js');
195
- }
196
-
197
- // Optionally enter noinput mode. This has to happen before setting up the
198
- // player.
199
- this.noInput_ = 'noinput' in this.getParams_();
200
- this.setupPlayer_();
201
- this.readHash_();
202
- window.addEventListener('hashchange', () => this.hashChanged_());
203
-
204
- await this.setupStorage_();
205
-
206
- this.setupBugButton_();
207
-
208
- if (this.noInput_) {
209
- // Set the page to noInput mode, disabling the header and footer.
210
- const hideClass = 'should-hide-in-no-input-mode';
211
- for (const element of document.getElementsByClassName(hideClass)) {
212
- this.hideElement_(element);
213
- }
214
- const showClass = 'should-show-in-no-input-mode';
215
- for (const element of document.getElementsByClassName(showClass)) {
216
- this.showElement_(element);
217
- }
218
- // Also fullscreen the container.
219
- this.container_.classList.add('no-input-sized');
220
- document.getElementById('video-bar').classList.add('no-input-sized');
221
- } else {
222
- goog.asserts.assert(this.player_, 'Player should exist by now.');
223
-
224
- // Make the visualizer element.
225
- const vCanvas = /** @type {!HTMLCanvasElement} */ (
226
- document.getElementById('visualizer-canvas'));
227
- const vDiv = /** @type {!HTMLElement} */ (
228
- document.getElementById('visualizer-div'));
229
- const vControlsDiv = /** @type {!HTMLElement} */ (
230
- document.getElementById('visualizer-controls-div'));
231
- const vScreenshotDiv = /** @type {!HTMLElement} */ (
232
- document.getElementById('visualizer-screenshot-div'));
233
- /** @private {?shakaDemo.Visualizer} */
234
- this.visualizer_ = new shakaDemo.Visualizer(
235
- vCanvas, vDiv, vScreenshotDiv, vControlsDiv, this.video_,
236
- this.player_);
237
- }
238
-
239
- // The main page is loaded. Dispatch an event, so the various
240
- // configurations will load themselves.
241
- this.dispatchEventWithName_('shaka-main-loaded');
242
-
243
- // Wait for one interruptor cycle, so that the tabs have time to load.
244
- // This ensures that, for example, if there is an asset playing at page
245
- // load time, the video will scroll into view second, and the page won't
246
- // scroll away from the video.
247
- await Promise.resolve();
248
-
249
- // Update the componentHandler, to account for any new MDL elements added.
250
- componentHandler.upgradeDom();
251
-
252
- const asset = this.getLastAssetFromHash_();
253
-
254
- this.fullyLoaded_ = true;
255
- this.remakeHash();
256
-
257
- if (asset && !this.selectedAsset) {
258
- // If an asset has begun loading in the meantime (for example, due to
259
- // re-joining an existing cast session), don't play this.
260
- this.loadAsset(asset);
261
- }
262
- }
263
-
264
- /**
265
- * @param {string} url
266
- * @return {!Promise.<string>}
267
- * @private
268
- */
269
- async loadText_(url) {
270
- const netEngine = new shaka.net.NetworkingEngine();
271
- const retryParams = shaka.net.NetworkingEngine.defaultRetryParameters();
272
- const request = shaka.net.NetworkingEngine.makeRequest([url], retryParams);
273
- const requestType = shaka.net.NetworkingEngine.RequestType.APP;
274
- const operation = netEngine.request(requestType, request);
275
- const response = await operation.promise;
276
- const text = shaka.util.StringUtils.fromUTF8(response.data);
277
- await netEngine.destroy();
278
- return text;
279
- }
280
-
281
- /** @private */
282
- async reportBug_() {
283
- // Fetch the special bug template.
284
- let text = await this.loadText_('autoTemplate.txt');
285
-
286
- // Fill in what parts of the template we can.
287
- const fillInTemplate = (replaceString, value) => {
288
- text = text.replace(replaceString, value);
289
- };
290
- fillInTemplate('RE:player', shaka.Player.version);
291
- if (this.selectedAsset) {
292
- const uriLines = [];
293
- const addLine = (key, value) => {
294
- uriLines.push(key + '= `' + value + '`');
295
- };
296
- addLine('uri', this.selectedAsset.manifestUri);
297
- if (this.selectedAsset.adTagUri) {
298
- addLine('ad tag uri', this.selectedAsset.adTagUri);
299
- }
300
- if (this.selectedAsset.licenseServers.size) {
301
- const uri = this.selectedAsset.licenseServers.values().next().value;
302
- addLine('license server', uri);
303
- for (const drmSystem of this.selectedAsset.licenseServers.keys()) {
304
- if (!shakaDemo.Main.commonDrmSystems.includes(drmSystem)) {
305
- addLine('drm system', drmSystem);
306
- break;
307
- }
308
- }
309
- }
310
- if (this.selectedAsset.certificateUri) {
311
- addLine('certificate', this.selectedAsset.certificateUri);
312
- }
313
- fillInTemplate('RE:uris', uriLines.join('\n'));
314
- } else {
315
- fillInTemplate('RE:uris', 'No asset');
316
- }
317
- fillInTemplate('RE:browser', navigator.userAgent);
318
- if (this.selectedAsset &&
319
- this.selectedAsset.source == shakaAssets.Source.CUSTOM) {
320
- // This is a custom asset, so add a comment warning about custom assets.
321
- const warning = await this.loadText_('customWarning.txt');
322
- fillInTemplate('RE:customwarning', warning);
323
- } else {
324
- // No need for any warnings. So remove it (and the newline after it).
325
- fillInTemplate('RE:customwarning\n', '');
326
- }
327
-
328
- const urlTerms = [];
329
- urlTerms.push('labels=type%3A+bug');
330
- urlTerms.push('body=' + encodeURIComponent(text));
331
- const url = 'https://github.com/shaka-project/shaka-player/issues/new?' +
332
- urlTerms.join('&');
333
-
334
- // Navigate to the github issue opening interface, with the
335
- // partially-filled template as a preset body, opening in another tab.
336
- window.open(url, '_blank');
337
- }
338
-
339
- /** @private */
340
- setupBugButton_() {
341
- const bugButton = document.getElementById('bug-button');
342
- bugButton.addEventListener('click', () => this.reportBug_());
343
-
344
- // The button should be disabled when offline, as we can't report bugs in
345
- // that state.
346
- if (!navigator.onLine) {
347
- bugButton.setAttribute('disabled', '');
348
- }
349
- window.addEventListener('online', () => {
350
- bugButton.removeAttribute('disabled');
351
- });
352
- window.addEventListener('offline', () => {
353
- bugButton.setAttribute('disabled', '');
354
- });
355
- }
356
-
357
- /** @private */
358
- configureUI_() {
359
- const video = /** @type {!HTMLVideoElement} */ (this.video_);
360
- const ui = video['ui'];
361
-
362
- const uiConfig = ui.getConfiguration();
363
- // Remove any trick play configurations from a previous config.
364
- uiConfig.addSeekBar = true;
365
- uiConfig.controlPanelElements =
366
- uiConfig.controlPanelElements.filter((element) => {
367
- return element != 'rewind' && element != 'fast_forward';
368
- });
369
- if (this.trickPlayControlsEnabled_) {
370
- // Trick mode controls don't have a seek bar.
371
- uiConfig.addSeekBar = false;
372
- // Replace the position the play_pause button was at with a full suite of
373
- // trick play controls, including rewind and fast-forward.
374
- const index = uiConfig.controlPanelElements.indexOf('play_pause');
375
- uiConfig.controlPanelElements.splice(
376
- index, 1, 'rewind', 'play_pause', 'fast_forward');
377
- }
378
- if (!uiConfig.controlPanelElements.includes('close')) {
379
- uiConfig.controlPanelElements.push('close');
380
- }
381
- if (!uiConfig.overflowMenuButtons.includes('visualizer')) {
382
- uiConfig.overflowMenuButtons.push('visualizer');
383
- }
384
- ui.configure(uiConfig);
385
- }
386
-
387
- /** @private */
388
- setupPlayer_() {
389
- const video = /** @type {!HTMLVideoElement} */ (this.video_);
390
- const ui = video['ui'];
391
- this.player_ = ui.getControls().getPlayer();
392
-
393
- if (!this.noInput_) {
394
- // Don't add the close button if in noInput mode; it doesn't make much
395
- // sense to stop playing a video if you can't start playing other videos.
396
-
397
- // Register custom controls to the UI.
398
- const closeFactory = new shakaDemo.CloseButton.Factory();
399
- shaka.ui.Controls.registerElement('close', closeFactory);
400
- const visualizerFactory = new shakaDemo.VisualizerButton.Factory();
401
- shaka.ui.OverflowMenu.registerElement('visualizer', visualizerFactory);
402
-
403
- // Configure UI.
404
- this.configureUI_();
405
- }
406
-
407
- // Add application-level default configs here. These are not the library
408
- // defaults, but they are the application defaults. This will affect the
409
- // default values assigned to UI config elements as well as the decision
410
- // about what values to place in the URL hash.
411
- this.player_.configure(
412
- 'manifest.dash.clockSyncUri',
413
- 'https://shaka-player-demo.appspot.com/time.txt');
414
-
415
- // Get default config.
416
- this.defaultConfig_ = this.player_.getConfiguration();
417
- this.desiredConfig_ = this.player_.getConfiguration();
418
- const languages = navigator.languages || ['en-us'];
419
- this.configure('preferredAudioLanguage', languages[0]);
420
- this.configure('preferredTextLanguage', languages[0]);
421
- this.uiLocale_ = languages[0];
422
- // TODO(#1591): Support multiple language preferences
423
-
424
- const onErrorEvent = (event) => this.onErrorEvent_(event);
425
- this.player_.addEventListener('error', onErrorEvent);
426
-
427
- // Listen to events on controls.
428
- this.controls_ = ui.getControls();
429
- this.controls_.addEventListener('error', onErrorEvent);
430
- this.controls_.addEventListener('caststatuschanged', (event) => {
431
- this.onCastStatusChange_(event['newStatus']);
432
- });
433
-
434
- this.localization_ = this.controls_.getLocalization();
435
-
436
- const drawerCloseButton = document.getElementById('drawer-close-button');
437
- drawerCloseButton.addEventListener('click', () => {
438
- const layout = document.getElementById('main-layout');
439
- layout.MaterialLayout.toggleDrawer();
440
- this.dispatchEventWithName_('shaka-main-drawer-state-change');
441
- this.hideElement_(drawerCloseButton);
442
- });
443
- // Dispatch drawer state change events when the drawer button or obfuscator
444
- // are pressed also.
445
- const drawerButton = document.querySelector('.mdl-layout__drawer-button');
446
- goog.asserts.assert(drawerButton, 'There should be a drawer button.');
447
- const openDrawer = () => {
448
- this.dispatchEventWithName_('shaka-main-drawer-state-change');
449
- this.showElement_(drawerCloseButton);
450
- };
451
- // Listen to both the "click" and "keydown" events on the drawer button,
452
- // since the element is actually a div rather than a button, which means
453
- // that it doesn't fire "click" events when activated by keyboard input.
454
- drawerButton.addEventListener('click', openDrawer);
455
- drawerButton.addEventListener('keydown', (event) => {
456
- const key = (/** @type {!KeyboardEvent} */ (event)).key;
457
- // Ignore "keydown" input for keys that won't trigger the button (i.e.
458
- // anything besides spacebar or enter).
459
- if (key == ' ' || key == 'Spacebar' || key == 'Enter') {
460
- openDrawer();
461
- }
462
- });
463
- const obfuscator = document.querySelector('.mdl-layout__obfuscator');
464
- goog.asserts.assert(obfuscator, 'There should be an obfuscator.');
465
- obfuscator.addEventListener('click', () => {
466
- this.dispatchEventWithName_('shaka-main-drawer-state-change');
467
- this.hideElement_(drawerCloseButton);
468
- });
469
- this.hideElement_(drawerCloseButton);
470
- }
471
-
472
- /** @return {boolean} */
473
- getIsDrawerOpen() {
474
- const drawer = document.querySelector('.mdl-layout__drawer');
475
- goog.asserts.assert(drawer, 'There should be a drawer.');
476
- return drawer.classList.contains('is-visible');
477
- }
478
-
479
- /**
480
- * Gets a unique storage identifier for an asset.
481
- * @param {!ShakaDemoAssetInfo} asset
482
- * @return {string}
483
- * @private
484
- */
485
- getIdentifierFromAsset_(asset) {
486
- // Custom assets can't have special characters like [ or ] in their name,
487
- // and none of the default assets will have that in their name, so we can
488
- // be sure that no asset will have [CUSTOM] in its name.
489
- return asset.name +
490
- (asset.source == shakaAssets.Source.CUSTOM ? ' [CUSTOM]' : '');
491
- }
492
-
493
- /**
494
- * Creates a storage instance.
495
- * If and only if storage is not available, this will return null.
496
- * These storage instances are meant to be used once and then destroyed, using
497
- * the |Storage.destroy| method.
498
- * @return {?shaka.offline.Storage}
499
- * @private
500
- */
501
- makeStorageInstance_() {
502
- if (!shaka.offline.Storage.support()) {
503
- return null;
504
- }
505
-
506
- const storage = new shaka.offline.Storage();
507
-
508
- // Configure the storage instance.
509
- /**
510
- * @param {string} identifier
511
- * @return {?ShakaDemoAssetInfo}
512
- */
513
- const getAssetWithIdentifier = (identifier) => {
514
- for (const asset of shakaAssets.testAssets) {
515
- if (this.getIdentifierFromAsset_(asset) == identifier) {
516
- return asset;
517
- }
518
- }
519
- if (shakaDemoCustom) {
520
- for (const asset of shakaDemoCustom.assets()) {
521
- if (this.getIdentifierFromAsset_(asset) == identifier) {
522
- return asset;
523
- }
524
- }
525
- }
526
- return null;
527
- };
528
- /**
529
- * @param {shaka.extern.StoredContent} content
530
- * @param {number} progress
531
- */
532
- const progressCallback = (content, progress) => {
533
- const identifier = content.appMetadata['identifier'];
534
- const asset = getAssetWithIdentifier(identifier);
535
- if (asset) {
536
- asset.storedProgress = progress;
537
- this.dispatchEventWithName_('shaka-main-offline-progress');
538
- }
539
- };
540
- storage.configure(this.desiredConfig_);
541
- storage.configure('offline.progressCallback', progressCallback);
542
-
543
- return storage;
544
- }
545
-
546
- /**
547
- * Attaches callbacks to an asset so that it can be downloaded online.
548
- * This method does not verify whether storage is or is not possible.
549
- * Also, if an asset has an associated offline version, load it with that
550
- * info.
551
- * @param {!ShakaDemoAssetInfo} asset
552
- */
553
- setupOfflineSupport(asset) {
554
- if (!this.initialStoredList_) {
555
- // Storage failed to set up, so nothing happened.
556
- return;
557
- }
558
-
559
- // If the list of stored content does not contain this asset, then make sure
560
- // that the asset's |storedContent| value is null. Custom assets that were
561
- // once stored might have that object serialized with their other data.
562
- asset.storedContent = null;
563
- for (const storedContent of this.initialStoredList_) {
564
- const identifier = storedContent.appMetadata['identifier'];
565
- if (this.getIdentifierFromAsset_(asset) == identifier) {
566
- asset.storedContent = storedContent;
567
- }
568
- }
569
-
570
- asset.storeCallback = async () => {
571
- const storage = this.makeStorageInstance_();
572
- if (!storage) {
573
- return;
574
- }
575
- try {
576
- await this.drmConfiguration_(asset, storage);
577
- const metadata = {
578
- 'identifier': this.getIdentifierFromAsset_(asset),
579
- 'downloaded': new Date(),
580
- };
581
- asset.storedProgress = 0;
582
- this.dispatchEventWithName_('shaka-main-offline-progress');
583
- const start = Date.now();
584
- const stored = await storage.store(asset.manifestUri, metadata).promise;
585
- const end = Date.now();
586
- console.log('Download time:', end - start);
587
- asset.storedContent = stored;
588
- } catch (error) {
589
- this.onError_(/** @type {!shaka.util.Error} */ (error));
590
- asset.storedContent = null;
591
- }
592
- storage.destroy();
593
- asset.storedProgress = 1;
594
- this.dispatchEventWithName_('shaka-main-offline-progress');
595
- };
596
-
597
- asset.unstoreCallback = async () => {
598
- if (asset == this.selectedAsset) {
599
- this.unload();
600
- }
601
- if (asset.storedContent && asset.storedContent.offlineUri) {
602
- const storage = this.makeStorageInstance_();
603
- if (!storage) {
604
- return;
605
- }
606
- try {
607
- asset.storedProgress = 0;
608
- this.dispatchEventWithName_('shaka-main-offline-progress');
609
- await storage.remove(asset.storedContent.offlineUri);
610
- asset.storedContent = null;
611
- } catch (error) {
612
- this.onError_(/** @type {!shaka.util.Error} */ (error));
613
- // Presumably, if deleting the asset fails, it still exists?
614
- }
615
- storage.destroy();
616
- asset.storedProgress = 1;
617
- this.dispatchEventWithName_('shaka-main-offline-progress');
618
- }
619
- };
620
- }
621
-
622
- /**
623
- * @return {!Promise}
624
- * @private
625
- */
626
- async setupStorage_() {
627
- // Load stored asset infos.
628
- const storage = this.makeStorageInstance_();
629
- if (!storage) {
630
- return;
631
- }
632
- try {
633
- this.initialStoredList_ = await storage.list();
634
- } catch (error) {
635
- // If this operation errors, it means that storage (while supported) is
636
- // being held up by some kind of error.
637
- // Log that error, and then pretend that storage is unsupported.
638
- console.error(error);
639
- this.initialStoredList_ = null;
640
- } finally {
641
- storage.destroy();
642
- }
643
-
644
- // Setup asset callbacks for storage, for the test assets.
645
- for (const asset of shakaAssets.testAssets) {
646
- if (this.getAssetUnsupportedReason(asset, /* needOffline= */ true)) {
647
- // Don't bother setting up the callbacks.
648
- continue;
649
- }
650
-
651
- this.setupOfflineSupport(asset);
652
- }
653
- }
654
-
655
- /** @private */
656
- hashChanged_() {
657
- this.readHash_();
658
- this.dispatchEventWithName_('shaka-main-config-change');
659
- }
660
-
661
- /**
662
- * Get why the asset is unplayable, if it is unplayable.
663
- *
664
- * @param {!ShakaDemoAssetInfo} asset
665
- * @param {boolean} needOffline True if offline support is required.
666
- * @return {?string} unsupportedReason
667
- * Null if asset is supported.
668
- */
669
- getAssetUnsupportedReason(asset, needOffline) {
670
- if (needOffline &&
671
- (!shaka.offline.Storage.support() || !this.initialStoredList_)) {
672
- return 'Your browser does not support offline storage.';
673
- }
674
-
675
- if (asset.source == shakaAssets.Source.CUSTOM) {
676
- // We can't be sure if custom assets are supported or not. Just assume
677
- // they are.
678
- return null;
679
- }
680
-
681
- // Is the asset disabled?
682
- if (asset.disabled) {
683
- return 'This asset is disabled.';
684
- }
685
-
686
- if (needOffline && !asset.features.includes(shakaAssets.Feature.OFFLINE)) {
687
- return 'This asset cannot be downloaded.';
688
- }
689
-
690
- if (!asset.isClear() && !asset.isAes128()) {
691
- const hasSupportedDRM = asset.drm.some((drm) => {
692
- return this.support_.drm[shakaAssets.identifierForKeySystem(drm)];
693
- });
694
- if (!hasSupportedDRM) {
695
- return 'Your browser does not support the required key systems.';
696
- }
697
- if (needOffline) {
698
- const hasSupportedOfflineDRM = asset.drm.some((drm) => {
699
- const identifier = shakaAssets.identifierForKeySystem(drm);
700
- return this.support_.drm[identifier] &&
701
- this.support_.drm[identifier].persistentState;
702
- });
703
- if (!hasSupportedOfflineDRM) {
704
- return 'Your browser does not support offline licenses for the ' +
705
- 'required key systems.';
706
- }
707
- }
708
- }
709
-
710
- // Does the browser support the asset's manifest type?
711
- if (asset.features.includes(shakaAssets.Feature.DASH) &&
712
- !this.support_.manifest['application/dash+xml']) {
713
- return 'Your browser does not support MPEG-DASH manifests.';
714
- }
715
- if (asset.features.includes(shakaAssets.Feature.HLS) &&
716
- !this.support_.manifest['application/x-mpegurl']) {
717
- return 'Your browser does not support HLS manifests.';
718
- }
719
- if (asset.features.includes(shakaAssets.Feature.MSS) &&
720
- !this.support_.manifest['application/vnd.ms-sstr+xml']) {
721
- return 'Your browser does not support MSS manifests.';
722
- }
723
-
724
- // Does the asset contain a playable mime type?
725
- const mimeTypes = [];
726
- if (asset.features.includes(shakaAssets.Feature.WEBM)) {
727
- mimeTypes.push('video/webm');
728
- }
729
- if (asset.features.includes(shakaAssets.Feature.MP4)) {
730
- mimeTypes.push('video/mp4');
731
- }
732
- if (asset.features.includes(shakaAssets.Feature.MP2TS)) {
733
- mimeTypes.push('video/mp2t');
734
- }
735
- if (asset.features.includes(shakaAssets.Feature.CONTAINERLESS)) {
736
- mimeTypes.push('audio/aac');
737
- }
738
- if (asset.features.includes(shakaAssets.Feature.DOLBY_VISION_3D)) {
739
- mimeTypes.push('video/mp4; codecs="dvh1.20.01"');
740
- }
741
- const hasSupportedMimeType = mimeTypes.some((type) => {
742
- return this.support_.media[type];
743
- });
744
- if (!hasSupportedMimeType) {
745
- return 'Your browser does not support the required video format.';
746
- }
747
-
748
- return null;
749
- }
750
-
751
- /**
752
- * Enable or disable the UI's trick play controls.
753
- *
754
- * @param {boolean} enabled
755
- */
756
- setTrickPlayControlsEnabled(enabled) {
757
- this.trickPlayControlsEnabled_ = enabled;
758
- // Configure the UI, to add or remove the controls.
759
- this.configureUI_();
760
- this.remakeHash();
761
- }
762
-
763
- /**
764
- * Get if the trick play controls are enabled.
765
- *
766
- * @return {boolean} enabled
767
- */
768
- getTrickPlayControlsEnabled() {
769
- return this.trickPlayControlsEnabled_;
770
- }
771
-
772
- /**
773
- * Enable or disable the native controls.
774
- * Goes into effect during the next load.
775
- *
776
- * @param {boolean} enabled
777
- */
778
- setNativeControlsEnabled(enabled) {
779
- this.nativeControlsEnabled_ = enabled;
780
- this.remakeHash();
781
- }
782
-
783
- /**
784
- * Get if the native controls are enabled.
785
- *
786
- * @return {boolean} enabled
787
- */
788
- getNativeControlsEnabled() {
789
- return this.nativeControlsEnabled_;
790
- }
791
-
792
- /** @param {string} locale */
793
- setUILocale(locale) {
794
- this.uiLocale_ = locale;
795
-
796
- // Fall back to browser languages after the demo page setting.
797
- const preferredLocales = [locale].concat(navigator.languages);
798
-
799
- this.localization_.changeLocale(preferredLocales);
800
- }
801
-
802
- /** @return {string} */
803
- getUILocale() {
804
- return this.uiLocale_;
805
- }
806
-
807
- /**
808
- * @return {?ShakaDemoAssetInfo}
809
- * @private
810
- */
811
- getLastAssetFromHash_() {
812
- const params = this.getParams_();
813
-
814
- const manifest = params['asset'];
815
- const adTagUri = params['adTagUri'];
816
- if (manifest) {
817
- // See if it's a default asset.
818
- for (const asset of shakaAssets.testAssets) {
819
- if (asset.manifestUri == manifest && asset.adTagUri == adTagUri) {
820
- return asset;
821
- }
822
- }
823
-
824
- // See if it's a custom asset saved here.
825
- for (const asset of shakaDemoCustom.assets()) {
826
- if (asset.manifestUri == manifest) {
827
- return asset;
828
- }
829
- }
830
-
831
- // Construct a new asset.
832
- const asset = new ShakaDemoAssetInfo(
833
- /* name= */ 'loaded asset',
834
- /* iconUri= */ '',
835
- /* manifestUri= */ manifest,
836
- /* source= */ shakaAssets.Source.CUSTOM);
837
- if ('license' in params) {
838
- let drmSystems = shakaDemo.Main.commonDrmSystems;
839
- if ('drmSystem' in params) {
840
- drmSystems = [params['drmSystem']];
841
- }
842
- for (const drmSystem of drmSystems) {
843
- asset.addLicenseServer(drmSystem, params['license']);
844
- }
845
- }
846
- if ('certificate' in params) {
847
- asset.addCertificateUri(params['certificate']);
848
- }
849
- return asset;
850
- }
851
- return null;
852
- }
853
-
854
- /** @private */
855
- readHash_() {
856
- const params = this.getParams_();
857
-
858
- if (this.player_) {
859
- const readParam = (hashName, configName) => {
860
- if (hashName in params) {
861
- const existing = this.getCurrentConfigValue(configName);
862
-
863
- // Translate the param string into a non-string value if appropriate.
864
- // Determine what type the parsed value should be based on the current
865
- // value.
866
- let value = params[hashName];
867
- if (typeof existing == 'boolean') {
868
- value = value == 'true';
869
- } else if (typeof existing == 'number') {
870
- value = parseFloat(value);
871
- }
872
-
873
- this.configure(configName, value);
874
- }
875
- };
876
- const config = this.player_.getConfiguration();
877
- shakaDemo.Utils.runThroughHashParams(readParam, config);
878
- const advanced = this.getCurrentConfigValue('drm.advanced');
879
- if (advanced) {
880
- for (const drmSystem of shakaDemo.Main.commonDrmSystems) {
881
- if (!advanced[drmSystem]) {
882
- advanced[drmSystem] = shakaDemo.Main.defaultAdvancedDrmConfig();
883
- }
884
- if ('videoRobustness' in params) {
885
- advanced[drmSystem].videoRobustness = params['videoRobustness'];
886
- }
887
- if ('audioRobustness' in params) {
888
- advanced[drmSystem].audioRobustness = params['audioRobustness'];
889
- }
890
- }
891
- }
892
- }
893
- if ('lang' in params) {
894
- // Load the legacy 'lang' hash value.
895
- const lang = params['lang'];
896
- this.configure('preferredAudioLanguage', lang);
897
- this.configure('preferredTextLanguage', lang);
898
- this.setUILocale(lang);
899
- }
900
- if ('uilang' in params) {
901
- this.setUILocale(params['uilang']);
902
- // TODO(#1591): Support multiple language preferences
903
- }
904
- if ('noadaptation' in params) {
905
- this.configure('abr.enabled', false);
906
- }
907
-
908
- // Add compiled/uncompiled links.
909
- this.makeVersionLinks_();
910
-
911
- // Disable custom controls.
912
- this.nativeControlsEnabled_ = 'nativecontrols' in params;
913
-
914
- // Enable trick play.
915
- if ('trickplay' in params) {
916
- this.trickPlayControlsEnabled_ = true;
917
- this.configureUI_();
918
- }
919
-
920
- // Check if uncompiled mode is supported.
921
- if (!shakaDemo.Utils.browserSupportsUncompiledMode()) {
922
- const uncompiledLink = document.getElementById('uncompiled-link');
923
- goog.asserts.assert(
924
- uncompiledLink instanceof HTMLAnchorElement, 'Wrong element type!');
925
- uncompiledLink.setAttribute('disabled', '');
926
- uncompiledLink.removeAttribute('href');
927
- uncompiledLink.title = 'requires a newer browser';
928
- }
929
-
930
- if (shaka.log) {
931
- if ('vv' in params) {
932
- shaka.log.setLevel(shaka.log.Level.V2);
933
- } else if ('v' in params) {
934
- shaka.log.setLevel(shaka.log.Level.V1);
935
- } else if ('debug' in params) {
936
- shaka.log.setLevel(shaka.log.Level.DEBUG);
937
- } else if ('info' in params) {
938
- shaka.log.setLevel(shaka.log.Level.INFO);
939
- }
940
- }
941
- }
942
-
943
- /** @private */
944
- makeVersionLinks_() {
945
- const params = this.getParams_();
946
- let buildType = 'uncompiled';
947
- if ('build' in params) {
948
- buildType = params['build'];
949
- } else if ('compiled' in params) {
950
- buildType = 'compiled';
951
- }
952
- for (const type of ['compiled', 'debug_compiled', 'uncompiled']) {
953
- const elem = document.getElementById(type.split('_').join('-') + '-link');
954
- goog.asserts.assert(
955
- elem instanceof HTMLAnchorElement, 'Wrong element type!');
956
- if (buildType == type) {
957
- elem.setAttribute('disabled', '');
958
- elem.removeAttribute('href');
959
- elem.title = 'currently selected';
960
- } else {
961
- elem.removeAttribute('disabled');
962
- elem.addEventListener('click', () => {
963
- const rawParams = location.hash.substr(1).split(';');
964
- const newParams = rawParams.filter((param) => {
965
- // Remove current build type param(s).
966
- return param != 'compiled' && param.split('=')[0] != 'build';
967
- });
968
- newParams.push('build=' + type);
969
- this.setNewHashSilent_(newParams.join(';'));
970
- location.reload();
971
- return false;
972
- });
973
- }
974
- }
975
- }
976
-
977
- /**
978
- * @return {!Object.<string, string>} params
979
- * @private
980
- */
981
- getParams_() {
982
- // Read URL parameters.
983
- let fields = location.search.substr(1);
984
- fields = fields ? fields.split(';') : [];
985
- let fragments = location.hash.substr(1);
986
- fragments = fragments ? fragments.split(';') : [];
987
-
988
- // Because they are being concatenated in this order, if both an
989
- // URL fragment and an URL parameter of the same type are present
990
- // the URL fragment takes precendence.
991
- /** @type {!Array.<string>} */
992
- const combined = fields.concat(fragments);
993
- const params = {};
994
- for (const line of combined) {
995
- const kv = line.split('=');
996
- params[kv[0]] = kv.slice(1).join('=');
997
- }
998
- return params;
999
- }
1000
-
1001
- /**
1002
- * Recovers the value from the given config field, from an arbitrary config
1003
- * object.
1004
- * This uses the same syntax as setting a single configuration field.
1005
- * @param {string} valueName
1006
- * @param {?shaka.extern.PlayerConfiguration} configObject
1007
- * @return {*}
1008
- * @private
1009
- */
1010
- getValueFromGivenConfig_(valueName, configObject) {
1011
- let objOn = configObject;
1012
- let valueNameOn = valueName;
1013
- while (valueNameOn) {
1014
- // Split using a regex that only matches the first period.
1015
- const split = valueNameOn.split(/\.(.+)/);
1016
- if (split.length == 3) {
1017
- valueNameOn = split[1];
1018
- objOn = objOn[split[0]];
1019
- } else {
1020
- return objOn[split[0]];
1021
- }
1022
- }
1023
- return undefined;
1024
- }
1025
-
1026
- /**
1027
- * Recovers the value from the given config field.
1028
- * This uses the same syntax as setting a single configuration field.
1029
- * @example getCurrentConfigValue('abr.bandwidthDowngradeTarget')
1030
- * @param {string} valueName
1031
- * @return {*}
1032
- */
1033
- getCurrentConfigValue(valueName) {
1034
- const config = this.desiredConfig_;
1035
- return this.getValueFromGivenConfig_(valueName, config);
1036
- }
1037
-
1038
- /**
1039
- * @param {string} valueName
1040
- */
1041
- resetConfiguration(valueName) {
1042
- this.configure(valueName, undefined);
1043
- }
1044
-
1045
- /**
1046
- * @param {string|!Object} config
1047
- * @param {*=} value
1048
- */
1049
- configure(config, value) {
1050
- if (arguments.length == 2 && typeof(config) == 'string') {
1051
- config = shaka.util.ConfigUtils.convertToConfigObject(config, value);
1052
- }
1053
- const asObj = /** @type {!Object} */ (config);
1054
- shaka.util.PlayerConfiguration.mergeConfigObjects(
1055
- this.desiredConfig_, asObj, this.defaultConfig_);
1056
- this.player_.configure(config, value);
1057
- }
1058
-
1059
- /** @return {!shaka.extern.PlayerConfiguration} */
1060
- getConfiguration() {
1061
- return this.desiredConfig_;
1062
- }
1063
-
1064
- /**
1065
- * @param {string} uri
1066
- * @param {!shaka.net.NetworkingEngine} netEngine
1067
- * @return {!Promise.<!ArrayBuffer>}
1068
- * @private
1069
- */
1070
- async requestCertificate_(uri, netEngine) {
1071
- const requestType = shaka.net.NetworkingEngine.RequestType.APP;
1072
- const request = /** @type {shaka.extern.Request} */ ({uris: [uri]});
1073
- const response = await netEngine.request(requestType, request).promise;
1074
- return response.data;
1075
- }
1076
-
1077
- /** @return {boolean} */
1078
- getIsVisualizerActive() {
1079
- if (this.visualizer_) {
1080
- return this.visualizer_.active;
1081
- }
1082
- return false;
1083
- }
1084
-
1085
- /** @param {boolean} active */
1086
- setIsVisualizerActive(active) {
1087
- if (this.visualizer_) {
1088
- const wasActive = this.visualizer_.active;
1089
- this.visualizer_.active = active;
1090
- if (wasActive != active) {
1091
- if (active) {
1092
- this.visualizer_.start();
1093
- } else {
1094
- this.visualizer_.stop();
1095
- }
1096
- }
1097
- }
1098
- }
1099
-
1100
- /** Unload the currently-playing asset. */
1101
- unload() {
1102
- if (this.visualizer_) {
1103
- this.visualizer_.stop();
1104
- }
1105
- this.selectedAsset = null;
1106
- const videoBar = document.getElementById('video-bar');
1107
- this.hideElement_(videoBar);
1108
- this.video_.poster = shakaDemo.Main.mainPoster_;
1109
-
1110
- if (document.fullscreenElement) {
1111
- document.exitFullscreen();
1112
- }
1113
- if (this.video_.webkitDisplayingFullscreen) {
1114
- this.video_.webkitExitFullscreen();
1115
- }
1116
- if (document.pictureInPictureElement) {
1117
- document.exitPictureInPicture();
1118
- }
1119
- if (window.documentPictureInPicture &&
1120
- window.documentPictureInPicture.window) {
1121
- window.documentPictureInPicture.window.close();
1122
- }
1123
- this.player_.unload();
1124
-
1125
- // The currently-selected asset changed, so update asset cards.
1126
- this.dispatchEventWithName_('shaka-main-selected-asset-changed');
1127
-
1128
- // Unset media session title, but only if the browser supports that API.
1129
- if (navigator.mediaSession) {
1130
- navigator.mediaSession.metadata = null;
1131
- }
1132
-
1133
- // Remake hash, to change the current asset.
1134
- this.remakeHash();
1135
- }
1136
-
1137
- /**
1138
- * @param {ShakaDemoAssetInfo} asset
1139
- * @param {shaka.offline.Storage=} storage
1140
- * @return {!Promise}
1141
- * @private
1142
- */
1143
- async drmConfiguration_(asset, storage) {
1144
- const netEngine = storage ?
1145
- storage.getNetworkingEngine() :
1146
- this.player_.getNetworkingEngine();
1147
- goog.asserts.assert(netEngine, 'There should be a net engine.');
1148
- asset.applyFilters(netEngine);
1149
-
1150
- const assetConfig = asset.getConfiguration();
1151
- if (storage) {
1152
- storage.configure(assetConfig);
1153
- } else {
1154
- // Remove all not-player-applied configurations, by resetting the
1155
- // configuration then re-applying the desired configuration.
1156
- this.player_.resetConfiguration();
1157
- this.readHash_();
1158
- this.player_.configure(assetConfig);
1159
- }
1160
-
1161
- const config = storage ?
1162
- storage.getConfiguration() :
1163
- this.player_.getConfiguration();
1164
-
1165
- // Change the config's serverCertificate fields based on
1166
- // asset.certificateUri.
1167
- if (asset.certificateUri) {
1168
- // Fetch the certificate, and apply it to the configuration.
1169
- const certificate = await this.requestCertificate_(
1170
- asset.certificateUri, netEngine);
1171
- const certArray = shaka.util.BufferUtils.toUint8(certificate);
1172
- for (const drmSystem of asset.licenseServers.keys()) {
1173
- config.drm.advanced[drmSystem] = config.drm.advanced[drmSystem] || {};
1174
- config.drm.advanced[drmSystem].serverCertificate = certArray;
1175
- }
1176
- } else {
1177
- // Remove any server certificates.
1178
- for (const drmSystem of asset.licenseServers.keys()) {
1179
- if (config.drm.advanced[drmSystem]) {
1180
- delete config.drm.advanced[drmSystem].serverCertificate;
1181
- }
1182
- }
1183
- }
1184
-
1185
- if (storage) {
1186
- storage.configure(config);
1187
- } else {
1188
- this.player_.configure('drm.advanced', config.drm.advanced);
1189
- }
1190
- this.remakeHash();
1191
- }
1192
-
1193
- /**
1194
- * Performs all visual operations that should be performed when a new asset
1195
- * begins playing. The video bar is un-hidden, the screen is scrolled, and so
1196
- * on.
1197
- *
1198
- * @private
1199
- */
1200
- showPlayer_() {
1201
- const videoBar = document.getElementById('video-bar');
1202
- this.showElement_(videoBar);
1203
- this.closeError_();
1204
- this.video_.poster = shakaDemo.Main.mainPoster_;
1205
-
1206
- // Scroll to the top of the page, so that if the page is scrolled down,
1207
- // the user won't need to manually scroll up to see the video.
1208
- videoBar.scrollIntoView({behavior: 'smooth', block: 'start'});
1209
- }
1210
-
1211
- /**
1212
- * @param {ShakaDemoAssetInfo} asset
1213
- */
1214
- async loadAsset(asset) {
1215
- try {
1216
- this.selectedAsset = asset;
1217
- this.showPlayer_();
1218
-
1219
- // The currently-selected asset changed, so update asset cards.
1220
- this.dispatchEventWithName_('shaka-main-selected-asset-changed');
1221
-
1222
- // Enable the correct set of controls before loading.
1223
- // The video container influences the TextDisplayer used.
1224
- if (this.nativeControlsEnabled_) {
1225
- this.controls_.setEnabledShakaControls(false);
1226
- this.controls_.setEnabledNativeControls(true);
1227
- // This will force the player to use SimpleTextDisplayer.
1228
- this.player_.setVideoContainer(null);
1229
- } else {
1230
- this.controls_.setEnabledShakaControls(true);
1231
- this.controls_.setEnabledNativeControls(false);
1232
- // This will force the player to use UITextDisplayer.
1233
- this.player_.setVideoContainer(this.container_);
1234
- }
1235
-
1236
- await this.drmConfiguration_(asset);
1237
- this.controls_.getCastProxy().setAppData({'asset': asset});
1238
-
1239
- // Finally, the asset can be loaded.
1240
- let manifestUri = asset.manifestUri;
1241
- // If we have an offline copy, use that. If the offlineUri field is null,
1242
- // we are still downloading it.
1243
- if (asset.storedContent && asset.storedContent.offlineUri) {
1244
- manifestUri = asset.storedContent.offlineUri;
1245
- }
1246
- // If it's a server side dai asset, request ad-containing manifest
1247
- // from the ad manager.
1248
- if (asset.imaAssetKey || (asset.imaContentSrcId && asset.imaVideoId)) {
1249
- manifestUri = await this.getManifestUriFromAdManager_(asset);
1250
- }
1251
- // If it's a MediaTailor asset, request ad-containing manifest
1252
- // from the ad manager.
1253
- if (asset.mediaTailorUrl) {
1254
- manifestUri = await this.getManifestUriFromMediaTailorAdManager_(asset);
1255
- }
1256
- await this.player_.load(
1257
- manifestUri,
1258
- /* startTime= */ null,
1259
- asset.mimeType || undefined);
1260
-
1261
- if (this.player_.isAudioOnly()) {
1262
- this.video_.poster = shakaDemo.Main.audioOnlyPoster_;
1263
- }
1264
-
1265
- for (const extraText of asset.extraText) {
1266
- this.player_.addTextTrackAsync(extraText.uri, extraText.language,
1267
- extraText.kind, extraText.mime, extraText.codecs);
1268
- }
1269
-
1270
- for (const extraThumbnail of asset.extraThumbnail) {
1271
- this.player_.addThumbnailsTrack(extraThumbnail);
1272
- }
1273
-
1274
- for (const extraChapter of asset.extraChapter) {
1275
- this.player_.addChaptersTrack(extraChapter.uri, extraChapter.language,
1276
- extraChapter.mime);
1277
- }
1278
-
1279
- // If the asset has an ad tag attached to it, load the ads
1280
- const adManager = this.player_.getAdManager();
1281
- if (adManager && asset.adTagUri) {
1282
- try {
1283
- // If IMA is blocked by an AdBlocker, init() will throw.
1284
- // If that happens, just proceed to load.
1285
- goog.asserts.assert(this.video_ != null, 'this.video should exist!');
1286
- adManager.initClientSide(
1287
- this.controls_.getClientSideAdContainer(), this.video_,
1288
- /** adsRenderingSettings= **/ null);
1289
- const adRequest = new google.ima.AdsRequest();
1290
- adRequest.adTagUrl = asset.adTagUri;
1291
- adManager.requestClientSideAds(adRequest);
1292
- } catch (error) {
1293
- console.log(error);
1294
- console.warn('Ads code has been prevented from running. ' +
1295
- 'Proceeding without ads.');
1296
- }
1297
- }
1298
-
1299
- // Set media session title, but only if the browser supports that API.
1300
- if (navigator.mediaSession) {
1301
- const metadata = {
1302
- title: asset.name,
1303
- artwork: [{src: asset.iconUri}],
1304
- };
1305
- metadata.artist = asset.source;
1306
- navigator.mediaSession.metadata = new MediaMetadata(metadata);
1307
- }
1308
-
1309
- if (this.visualizer_ && this.visualizer_.active) {
1310
- this.visualizer_.start();
1311
- }
1312
- } catch (reason) {
1313
- const error = /** @type {!shaka.util.Error} */ (reason);
1314
- if (error.code == shaka.util.Error.Code.LOAD_INTERRUPTED) {
1315
- // Don't use shaka.log, which is not present in compiled builds.
1316
- console.debug('load() interrupted');
1317
- } else {
1318
- this.onError_(error);
1319
- }
1320
- }
1321
-
1322
- // Remake hash, to change the current asset.
1323
- this.remakeHash();
1324
- }
1325
-
1326
- /** Remakes the location's hash. */
1327
- remakeHash() {
1328
- if (!this.fullyLoaded_) {
1329
- // Don't remake the hash until the demo page is fully loaded.
1330
- return;
1331
- }
1332
-
1333
- const params = [];
1334
-
1335
- if (this.player_) {
1336
- const setParam = (hashName, configName) => {
1337
- const currentValue = this.getCurrentConfigValue(configName);
1338
- const defaultConfig = this.defaultConfig_;
1339
- const defaultValue =
1340
- this.getValueFromGivenConfig_(configName, defaultConfig);
1341
- // NaN != NaN, so there has to be a special check for it to prevent
1342
- // false positives.
1343
- const bothAreNaN = isNaN(currentValue) && isNaN(defaultValue);
1344
- // Strings count as NaN too, so check for them specifically.
1345
- const bothAreStrings = (typeof currentValue) == 'string' &&
1346
- (typeof defaultValue) == 'string';
1347
- if (currentValue != defaultValue && (!bothAreNaN || bothAreStrings)) {
1348
- // Don't bother saving in the hash unless it's a non-default value.
1349
- params.push(hashName + '=' + currentValue);
1350
- }
1351
- };
1352
- const config = this.player_.getConfiguration();
1353
- shakaDemo.Utils.runThroughHashParams(setParam, config);
1354
- const advanced = this.getCurrentConfigValue('drm.advanced');
1355
- if (advanced) {
1356
- for (const drmSystem of shakaDemo.Main.commonDrmSystems) {
1357
- const advancedFor = advanced[drmSystem];
1358
- if (advancedFor) {
1359
- if (advancedFor.videoRobustness) {
1360
- params.push('videoRobustness=' + advancedFor.videoRobustness);
1361
- }
1362
- if (advancedFor.audioRobustness) {
1363
- params.push('audioRobustness=' + advancedFor.audioRobustness);
1364
- }
1365
- break;
1366
- }
1367
- }
1368
- }
1369
- }
1370
- if (!this.getCurrentConfigValue('abr.enabled')) {
1371
- params.push('noadaptation');
1372
- }
1373
- params.push('uilang=' + this.getUILocale());
1374
-
1375
- if (this.selectedAsset) {
1376
- const isDefault = shakaAssets.testAssets.includes(this.selectedAsset);
1377
- params.push('asset=' + this.selectedAsset.manifestUri);
1378
- if (this.selectedAsset.adTagUri) {
1379
- params.push('adTagUri=' + this.selectedAsset.adTagUri);
1380
- }
1381
- if (!isDefault && this.selectedAsset.licenseServers.size) {
1382
- const uri = this.selectedAsset.licenseServers.values().next().value;
1383
- params.push('license=' + uri);
1384
- for (const drmSystem of this.selectedAsset.licenseServers.keys()) {
1385
- if (!shakaDemo.Main.commonDrmSystems.includes(drmSystem)) {
1386
- params.push('drmSystem=' + drmSystem);
1387
- break;
1388
- }
1389
- }
1390
- }
1391
- if (!isDefault && this.selectedAsset.certificateUri) {
1392
- params.push('certificate=' + this.selectedAsset.certificateUri);
1393
- }
1394
- }
1395
-
1396
- const navButtons = document.getElementById('nav-button-container');
1397
- for (const button of navButtons.childNodes) {
1398
- if (button.nodeType == Node.ELEMENT_NODE) {
1399
- goog.asserts.assert( button instanceof HTMLElement, 'Wrong node type!');
1400
- if (button.classList.contains('mdl-button--accent')) {
1401
- params.push('panel=' + button.getAttribute('tab-identifier'));
1402
- const hashValues = button.getAttribute('tab-hash');
1403
- if (hashValues) {
1404
- params.push('panelData=' + hashValues);
1405
- }
1406
- break;
1407
- }
1408
- }
1409
- }
1410
-
1411
- for (const type of ['compiled', 'debug_compiled', 'uncompiled']) {
1412
- const elem = document.getElementById(type.split('_').join('-') + '-link');
1413
- if (elem.hasAttribute('disabled')) {
1414
- params.push('build=' + type);
1415
- }
1416
- }
1417
-
1418
- if (this.noInput_) {
1419
- params.push('noinput');
1420
- }
1421
-
1422
- if (this.nativeControlsEnabled_) {
1423
- params.push('nativecontrols');
1424
- }
1425
-
1426
- if (this.trickPlayControlsEnabled_) {
1427
- params.push('trickplay');
1428
- }
1429
-
1430
- // MAX_LOG_LEVEL is the default starting log level. Only save the log level
1431
- // if it's different from this default.
1432
- if (shaka.log && shaka.log.currentLevel != shaka.log.MAX_LOG_LEVEL) {
1433
- switch (shaka.log.currentLevel) {
1434
- case shaka.log.Level.INFO:
1435
- params.push('info');
1436
- break;
1437
- case shaka.log.Level.DEBUG:
1438
- params.push('debug');
1439
- break;
1440
- case shaka.log.Level.V2:
1441
- params.push('vv');
1442
- break;
1443
- case shaka.log.Level.V1:
1444
- params.push('v');
1445
- break;
1446
- }
1447
- }
1448
-
1449
- this.setNewHashSilent_(params.join(';'));
1450
- }
1451
-
1452
- /**
1453
- * Sets the hash to a given value WITHOUT triggering a |hashchange| event.
1454
- * @param {string} hash
1455
- * @private
1456
- */
1457
- setNewHashSilent_(hash) {
1458
- const state = null;
1459
- const title = ''; // Unused; just needed to make Closure happy.
1460
- const newURL = document.location.pathname + '#' + hash;
1461
- // Calling history.replaceState can change the URL or hash of the page
1462
- // without actually triggering any changes; it won't make the page navigate,
1463
- // or trigger a |hashchange| event.
1464
- history.replaceState(state, title, newURL);
1465
- }
1466
-
1467
- /**
1468
- * Gets the hamburger menu's content div, so that the caller to add elements
1469
- * to it.
1470
- * There is no guarantee that the caller is the only entity that has added
1471
- * contents to the hamburger menu.
1472
- * @return {!HTMLDivElement} The container for the hamburger menu.
1473
- */
1474
- getHamburgerMenu() {
1475
- const menu = document.getElementById('hamburger-menu-contents');
1476
- return /** @type {!HTMLDivElement} */ (menu);
1477
- }
1478
-
1479
- /**
1480
- * @param {Element} element
1481
- * @private
1482
- */
1483
- hideElement_(element) {
1484
- element.classList.add('hidden');
1485
- }
1486
-
1487
- /**
1488
- * @param {Element} element
1489
- * @private
1490
- */
1491
- showElement_(element) {
1492
- element.classList.remove('hidden');
1493
- }
1494
-
1495
- /**
1496
- * @param {ShakaDemoAssetInfo} asset
1497
- * @return {!Promise.<string>}
1498
- * @private
1499
- */
1500
- async getManifestUriFromAdManager_(asset) {
1501
- const adManager = this.player_.getAdManager();
1502
- const container = this.controls_.getServerSideAdContainer();
1503
- try {
1504
- // If IMA is blocked by an AdBlocker, init() will throw.
1505
- // If that happens, return our backup uri.
1506
- goog.asserts.assert(this.video_ != null, 'Video should not be null!');
1507
- adManager.initServerSide(container, this.video_);
1508
- let request;
1509
- if (asset.imaAssetKey != null) {
1510
- // LIVE stream
1511
- request = new google.ima.dai.api.LiveStreamRequest();
1512
- request.assetKey = asset.imaAssetKey;
1513
- } else {
1514
- goog.asserts.assert(asset.imaContentSrcId != null &&
1515
- asset.imaVideoId != null, 'Asset should have ima ids!');
1516
- // VOD
1517
- request = new google.ima.dai.api.VODStreamRequest();
1518
- request.contentSourceId = asset.imaContentSrcId;
1519
- request.videoId = asset.imaVideoId;
1520
- }
1521
- switch (asset.imaManifestType) {
1522
- case 'DASH':
1523
- case 'dash':
1524
- case 'MPD':
1525
- case 'mpd':
1526
- request.format = google.ima.dai.api.StreamRequest.StreamFormat.DASH;
1527
- break;
1528
- case 'HLS':
1529
- case 'hls':
1530
- case 'M3U8':
1531
- case 'm3u8':
1532
- request.format = google.ima.dai.api.StreamRequest.StreamFormat.HLS;
1533
- break;
1534
- }
1535
-
1536
- const uri = await adManager.requestServerSideStream(
1537
- request, /* backupUri= */ asset.manifestUri);
1538
- return uri;
1539
- } catch (error) {
1540
- console.log(error);
1541
- console.warn('Ads code has been prevented from running ' +
1542
- 'or returned an error. Proceeding without ads.');
1543
-
1544
- return asset.manifestUri;
1545
- }
1546
- }
1547
-
1548
- /**
1549
- * @param {ShakaDemoAssetInfo} asset
1550
- * @return {!Promise.<string>}
1551
- * @private
1552
- */
1553
- async getManifestUriFromMediaTailorAdManager_(asset) {
1554
- const adManager = this.player_.getAdManager();
1555
- const container = this.controls_.getServerSideAdContainer();
1556
- try {
1557
- goog.asserts.assert(this.video_ != null, 'Video should not be null!');
1558
- goog.asserts.assert(asset.mediaTailorUrl != null,
1559
- 'Media Tailor info not be null!');
1560
- const netEngine = this.player_.getNetworkingEngine();
1561
- goog.asserts.assert(netEngine, 'There should be a net engine.');
1562
- adManager.initMediaTailor(container, netEngine, this.video_);
1563
- const uri = await adManager.requestMediaTailorStream(
1564
- asset.mediaTailorUrl, asset.mediaTailorAdsParams,
1565
- /* backupUri= */ asset.manifestUri);
1566
- return uri;
1567
- } catch (error) {
1568
- console.log(error);
1569
- console.warn('Ads code has been prevented from running ' +
1570
- 'or returned an error. Proceeding without ads.');
1571
-
1572
- return asset.manifestUri;
1573
- }
1574
- }
1575
-
1576
- /**
1577
- * Sets up a nav button, and an associated tab.
1578
- * This method is meant to be called by the various tabs, as part of their
1579
- * setup process.
1580
- * @param {string} containerName Used to determine the id of the button this
1581
- * is looking for. Also used as the className of the container, for CSS.
1582
- * @return {{
1583
- * container: !HTMLDivElement,
1584
- * button: !HTMLButtonElement,
1585
- * }} The container for the tab, and the button element that activates it.
1586
- */
1587
- addNavButton(containerName) {
1588
- const navButtons = document.getElementById('nav-button-container');
1589
- const contents = document.getElementById('contents');
1590
- const button = document.getElementById('nav-button-' + containerName);
1591
-
1592
- // TODO: Switch to using MDL tabs.
1593
-
1594
- // Determine if the element is selected.
1595
- const params = this.getParams_();
1596
- let selected =
1597
- params['panel'] == encodeURI(button.getAttribute('tab-identifier'));
1598
- if (selected) {
1599
- // Re-apply any saved data from hash.
1600
- const hashValues = params['panelData'];
1601
- if (hashValues) {
1602
- button.setAttribute('tab-hash', hashValues);
1603
- }
1604
- } else if (!params['panel']) {
1605
- // Check if it's selected by default.
1606
- selected = button.getAttribute('defaultselected') != null;
1607
- }
1608
-
1609
- // Create the div for this nav button's container within the contents.
1610
- const container = document.createElement('div');
1611
- this.hideElement_(container);
1612
- contents.appendChild(container);
1613
-
1614
- // Add a click listener to display this container, and hide the others.
1615
- const switchPage = () => {
1616
- // This element should be the selected one.
1617
- for (const child of navButtons.childNodes) {
1618
- if (child.nodeType == Node.ELEMENT_NODE) {
1619
- goog.asserts.assert(child instanceof Element, 'Wrong node type!');
1620
- child.classList.remove('mdl-button--accent');
1621
- }
1622
- }
1623
- for (const child of contents.childNodes) {
1624
- if (child.nodeType == Node.ELEMENT_NODE) {
1625
- goog.asserts.assert(child instanceof Element, 'Wrong node type!');
1626
- this.hideElement_(child);
1627
- }
1628
- }
1629
- button.classList.add('mdl-button--accent');
1630
- this.showElement_(container);
1631
- this.remakeHash();
1632
-
1633
- // Dispatch an event so that a page can load any deferred content.
1634
- this.dispatchEventWithName_('shaka-main-page-changed');
1635
-
1636
- // Scroll so that the top of the tab is in view.
1637
- container.scrollIntoView({behavior: 'smooth', block: 'start'});
1638
- };
1639
-
1640
- button.addEventListener('click', switchPage);
1641
- if (selected) {
1642
- // Defer this call to switchPage until the container is fully set up.
1643
- Promise.resolve().then(switchPage);
1644
- }
1645
-
1646
- return {
1647
- container: /** @type {!HTMLDivElement} */ (container),
1648
- button: /** @type {!HTMLButtonElement} */ (button),
1649
- };
1650
- }
1651
-
1652
- /**
1653
- * Dispatches a custom event to document.
1654
- * @param {string} name
1655
- * @private
1656
- */
1657
- dispatchEventWithName_(name) {
1658
- const event =
1659
- /** @type {!CustomEvent} */(document.createEvent('CustomEvent'));
1660
- event.initCustomEvent(name,
1661
- /* canBubble= */ false,
1662
- /* cancelable= */ false,
1663
- /* detail= */ null);
1664
- document.dispatchEvent(event);
1665
- }
1666
-
1667
- /**
1668
- * Sets the "version-string" divs to a version string.
1669
- * For example, "v2.5.4-main (uncompiled)".
1670
- * @private
1671
- */
1672
- setUpVersionStrings_() {
1673
- const version = shaka.Player.version;
1674
- let split = version.split('-');
1675
- const inParen = [];
1676
-
1677
- // Separate out some special terms into parentheses after the rest of the
1678
- // version, to make them stand out visually.
1679
- for (const whitelisted of ['debug', 'uncompiled']) {
1680
- if (split.includes(whitelisted)) {
1681
- inParen.push(whitelisted);
1682
- split = split.filter((term) => term != whitelisted);
1683
- }
1684
- }
1685
-
1686
- // Put the version into the version string div.
1687
- const versionStringDivs = document.getElementsByClassName('version-string');
1688
- for (const div of versionStringDivs) {
1689
- div.textContent = split.join('-');
1690
- if (inParen.length > 0) {
1691
- div.textContent += ' (' + inParen.join(', ') + ')';
1692
- }
1693
- }
1694
- }
1695
-
1696
- /**
1697
- * Closes the error bar.
1698
- * @private
1699
- */
1700
- closeError_() {
1701
- document.getElementById('error-display').classList.add('hidden');
1702
- this.errorDisplayLink_.href = '';
1703
- this.errorDisplayLink_.textContent = '';
1704
- this.currentErrorSeverity_ = null;
1705
- }
1706
-
1707
- /**
1708
- * @param {!Event} event
1709
- * @private
1710
- */
1711
- onErrorEvent_(event) {
1712
- // TODO: generate externs automatically from @event types
1713
- // This event should be shaka.Player.ErrorEvent
1714
- this.onError_(event['detail']);
1715
- }
1716
-
1717
- /**
1718
- * @param {!shaka.util.Error} error
1719
- * @private
1720
- */
1721
- onError_(error) {
1722
- let severity = error.severity;
1723
- if (severity == null || error.severity == undefined) {
1724
- // It's not a shaka.util.Error. Treat it as very severe, since those
1725
- // should not be happening.
1726
- severity = shaka.util.Error.Severity.CRITICAL;
1727
- }
1728
-
1729
- const message = error.message || ('Error code ' + error.code);
1730
-
1731
- let href = '';
1732
- if (error.code) {
1733
- href = '../docs/api/shaka.util.Error.html#value:' + error.code;
1734
- }
1735
-
1736
- console.error(error);
1737
- this.handleError_(severity, message, href);
1738
- }
1739
-
1740
- /**
1741
- * @param {!shaka.util.Error.Severity} severity
1742
- * @param {string} message
1743
- * @param {string} href
1744
- * @private
1745
- */
1746
- handleError_(severity, message, href) {
1747
- // Always show the new error if:
1748
- // 1. there is no error showing currently
1749
- // 2. the new error is more severe than the old one
1750
- if (this.currentErrorSeverity_ == null ||
1751
- severity > this.currentErrorSeverity_) {
1752
- this.errorDisplayLink_.href = href;
1753
- // IE8 and other very old browsers don't have textContent.
1754
- if (this.errorDisplayLink_.textContent === undefined) {
1755
- this.errorDisplayLink_.innerText = message;
1756
- } else {
1757
- this.errorDisplayLink_.textContent = message;
1758
- }
1759
- this.currentErrorSeverity_ = severity;
1760
- if (this.errorDisplayLink_.href) {
1761
- this.errorDisplayLink_.classList.remove('input-disabled');
1762
- } else {
1763
- this.errorDisplayLink_.classList.add('input-disabled');
1764
- }
1765
- document.getElementById('error-display').classList.remove('hidden');
1766
- }
1767
- }
1768
-
1769
- /**
1770
- * @param {boolean} connected
1771
- * @private
1772
- */
1773
- onCastStatusChange_(connected) {
1774
- if (connected && !this.selectedAsset) {
1775
- // You joined an existing session.
1776
- // The exact asset playing is unknown. Just have a selectedAsset, to show
1777
- // that this is playing something.
1778
- this.selectedAsset = ShakaDemoAssetInfo.makeBlankAsset();
1779
- this.showPlayer_();
1780
- }
1781
- }
1782
-
1783
- /** @return {!shaka.extern.AdvancedDrmConfiguration} */
1784
- static defaultAdvancedDrmConfig() {
1785
- return {
1786
- distinctiveIdentifierRequired: false,
1787
- persistentStateRequired: false,
1788
- videoRobustness: '',
1789
- audioRobustness: '',
1790
- sessionType: '',
1791
- serverCertificate: new Uint8Array(0),
1792
- serverCertificateUri: '',
1793
- individualizationServer: '',
1794
- };
1795
- }
1796
- };
1797
-
1798
-
1799
- /** @type {!Array.<string>} */
1800
- shakaDemo.Main.commonDrmSystems = [
1801
- 'com.widevine.alpha',
1802
- 'com.microsoft.playready',
1803
- 'com.apple.fps',
1804
- 'com.adobe.primetime',
1805
- 'org.w3.clearkey',
1806
- ];
1807
-
1808
-
1809
- const shakaDemoMain = new shakaDemo.Main();
1810
-
1811
-
1812
- /**
1813
- * @private
1814
- * @const {string}
1815
- */
1816
- shakaDemo.Main.mainPoster_ =
1817
- 'https://shaka-player-demo.appspot.com/assets/poster.jpg';
1818
-
1819
-
1820
- /**
1821
- * @private
1822
- * @const {string}
1823
- */
1824
- shakaDemo.Main.audioOnlyPoster_ =
1825
- 'https://shaka-player-demo.appspot.com/assets/audioOnly.gif';
1826
-
1827
-
1828
- // If setup fails and the global error handler does, too, (as happened on IE
1829
- // right before the launch of this demo), at least log that error to the console
1830
- // for debugging. Wrap init functions in an async function with a try/catch to
1831
- // make sure no error goes unseen when debugging.
1832
- /**
1833
- * @param {function()} initFn
1834
- * @return {!Promise}
1835
- * @suppress {accessControls}
1836
- */
1837
- shakaDemo.Main.initWrapper = async (initFn) => {
1838
- try {
1839
- await initFn();
1840
- } catch (error) {
1841
- shakaDemoMain.onError_(error);
1842
- console.error(error);
1843
- }
1844
- };
1845
- document.addEventListener('shaka-ui-loaded', () => {
1846
- shakaDemo.Main.initWrapper(() => shakaDemoMain.init());
1847
- });
1848
- document.addEventListener('shaka-ui-load-failed', (event) => {
1849
- shakaDemo.Main.initWrapper(() => {
1850
- const reasonCode = /** @type {!shaka.ui.Overlay.FailReasonCode} */ (
1851
- event['detail']['reasonCode']);
1852
- shakaDemoMain.initFailed(reasonCode);
1853
- });
1854
- });