shaka-player 4.6.5 → 4.7.1

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 (598) 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 +9 -5
  5. package/dist/locales.js +30 -30
  6. package/dist/shaka-player.compiled.d.ts +46 -3
  7. package/dist/shaka-player.compiled.debug.d.ts +46 -3
  8. package/dist/shaka-player.compiled.debug.externs.js +45 -0
  9. package/dist/shaka-player.compiled.debug.js +382 -351
  10. package/dist/shaka-player.compiled.debug.map +4 -4
  11. package/dist/shaka-player.compiled.externs.js +45 -0
  12. package/dist/shaka-player.compiled.js +1127 -1113
  13. package/dist/shaka-player.compiled.map +4 -4
  14. package/dist/shaka-player.ui.d.ts +68 -4
  15. package/dist/shaka-player.ui.debug.d.ts +68 -4
  16. package/dist/shaka-player.ui.debug.externs.js +77 -0
  17. package/dist/shaka-player.ui.debug.js +428 -392
  18. package/dist/shaka-player.ui.debug.map +4 -4
  19. package/dist/shaka-player.ui.externs.js +77 -0
  20. package/dist/shaka-player.ui.js +1304 -1290
  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/cea/cea708_service.js +1 -1
  28. package/lib/cea/cea708_window.js +95 -7
  29. package/lib/dash/dash_parser.js +55 -11
  30. package/lib/media/adaptation_set_criteria.js +76 -10
  31. package/lib/media/media_source_engine.js +42 -18
  32. package/lib/media/segment_reference.js +12 -0
  33. package/lib/media/streaming_engine.js +55 -3
  34. package/lib/player.js +92 -6
  35. package/lib/util/cmsd_manager.js +269 -0
  36. package/lib/util/content_steering_manager.js +5 -1
  37. package/lib/util/mime_utils.js +6 -2
  38. package/lib/util/periods.js +108 -39
  39. package/lib/util/player_configuration.js +19 -5
  40. package/lib/util/stream_utils.js +82 -13
  41. package/package.json +1 -1
  42. package/ui/audio_language_selection.js +3 -0
  43. package/ui/controls.js +60 -0
  44. package/ui/externs/ui.js +12 -1
  45. package/ui/hidden_fast_forward_button.js +32 -0
  46. package/ui/hidden_rewind_button.js +32 -0
  47. package/ui/hidden_seek_button.js +121 -0
  48. package/ui/less/buttons.less +50 -0
  49. package/ui/less/containers.less +18 -0
  50. package/ui/resolution_selection.js +2 -0
  51. package/ui/ui.js +2 -0
  52. package/.github/ISSUE_TEMPLATE/bug_report.md +0 -75
  53. package/.github/ISSUE_TEMPLATE/feature_request.md +0 -26
  54. package/.github/ISSUE_TEMPLATE/question.md +0 -26
  55. package/.github/config.yml +0 -1
  56. package/.github/workflows/appspot.yaml +0 -39
  57. package/.github/workflows/build-and-test.yaml +0 -222
  58. package/.github/workflows/compute-incremental-coverage.py +0 -265
  59. package/.github/workflows/custom-actions/prep-for-appspot/action.yaml +0 -56
  60. package/.github/workflows/custom-actions/set-commit-status/action.yaml +0 -37
  61. package/.github/workflows/deflake.yaml +0 -31
  62. package/.github/workflows/demo-version-index.yaml +0 -43
  63. package/.github/workflows/nightly-demo.yaml +0 -42
  64. package/.github/workflows/release-please.yaml +0 -193
  65. package/.github/workflows/report-incremental-coverage.yaml +0 -39
  66. package/.github/workflows/safari-homedir-launcher.sh +0 -18
  67. package/.github/workflows/selenium-lab-tests.yaml +0 -370
  68. package/.github/workflows/shaka-bot-commands/command-help.sh +0 -27
  69. package/.github/workflows/shaka-bot-commands/command-test.sh +0 -56
  70. package/.github/workflows/shaka-bot-commands/lib.sh +0 -83
  71. package/.github/workflows/shaka-bot-commands/main.sh +0 -51
  72. package/.github/workflows/sync-labels.yaml +0 -33
  73. package/.github/workflows/talk-to-shaka-bot.yaml +0 -29
  74. package/.github/workflows/update-issues.yaml +0 -31
  75. package/.github/workflows/update-screenshots.yaml +0 -142
  76. package/.github/workflows/validate-pr-title.yaml +0 -27
  77. package/CHANGELOG.md +0 -5785
  78. package/CODE_OF_CONDUCT.md +0 -93
  79. package/CONTRIBUTING.md +0 -76
  80. package/demo/TengwarTelcontar.woff2 +0 -0
  81. package/demo/app_logo_144.png +0 -0
  82. package/demo/app_logo_192.png +0 -0
  83. package/demo/app_logo_256.png +0 -0
  84. package/demo/app_logo_384.png +0 -0
  85. package/demo/app_logo_512.png +0 -0
  86. package/demo/app_manifest.json +0 -29
  87. package/demo/asset_card.js +0 -410
  88. package/demo/autoTemplate.txt +0 -61
  89. package/demo/cast_receiver/idle1.jpg +0 -0
  90. package/demo/cast_receiver/idle2.jpg +0 -0
  91. package/demo/cast_receiver/idle3.jpg +0 -0
  92. package/demo/cast_receiver/index.html +0 -75
  93. package/demo/cast_receiver/receiver_app.css +0 -111
  94. package/demo/cast_receiver/receiver_app.js +0 -158
  95. package/demo/close_button.js +0 -60
  96. package/demo/common/asset.js +0 -510
  97. package/demo/common/assets.js +0 -1634
  98. package/demo/config.js +0 -859
  99. package/demo/custom.js +0 -907
  100. package/demo/customWarning.txt +0 -8
  101. package/demo/demo.less +0 -591
  102. package/demo/demo_uncompiled.js +0 -11
  103. package/demo/demo_utils.js +0 -113
  104. package/demo/favicon.ico +0 -0
  105. package/demo/front.js +0 -156
  106. package/demo/icons/README.md +0 -4
  107. package/demo/icons/baseline-audiotrack-24px.svg +0 -1
  108. package/demo/icons/baseline-closed_caption-24px.svg +0 -1
  109. package/demo/icons/baseline-fast_forward-24px.svg +0 -1
  110. package/demo/icons/baseline-language-24px.svg +0 -1
  111. package/demo/icons/baseline-live_tv-24px.svg +0 -1
  112. package/demo/icons/baseline-subtitles-24px.svg +0 -1
  113. package/demo/icons/baseline-surround_sound-24px.svg +0 -1
  114. package/demo/icons/custom_ad.svg +0 -1
  115. package/demo/icons/custom_box_with_text.svg +0 -1
  116. package/demo/icons/custom_clear_key.svg +0 -1
  117. package/demo/icons/custom_high_definition.svg +0 -1
  118. package/demo/icons/custom_playready.svg +0 -1
  119. package/demo/icons/custom_ultra_high_definition.svg +0 -1
  120. package/demo/icons/custom_widevine.svg +0 -1
  121. package/demo/index.html +0 -173
  122. package/demo/input.js +0 -270
  123. package/demo/input_container.js +0 -218
  124. package/demo/load.js +0 -156
  125. package/demo/main.js +0 -1854
  126. package/demo/search.js +0 -452
  127. package/demo/service_worker.js +0 -355
  128. package/demo/shaka_logo_trans.png +0 -0
  129. package/demo/tooltip.js +0 -29
  130. package/demo/visualizer.js +0 -335
  131. package/demo/visualizer_button.js +0 -84
  132. package/dist/demo.compiled.debug.js +0 -340
  133. package/dist/demo.compiled.debug.map +0 -8
  134. package/dist/demo.compiled.js +0 -340
  135. package/dist/demo.compiled.map +0 -8
  136. package/dist/demo.css +0 -6
  137. package/dist/demo.css.map +0 -1
  138. package/dist/receiver.compiled.debug.js +0 -187
  139. package/dist/receiver.compiled.debug.map +0 -8
  140. package/dist/receiver.compiled.js +0 -187
  141. package/dist/receiver.compiled.map +0 -8
  142. package/docs/announcement-list-join-group.png +0 -0
  143. package/docs/api-mainpage.md +0 -28
  144. package/docs/design/REDESIGN.md +0 -283
  145. package/docs/design/architecture.md +0 -13
  146. package/docs/design/bg-fetch-after.gv +0 -29
  147. package/docs/design/bg-fetch-after.gv.png +0 -0
  148. package/docs/design/bg-fetch-before.gv +0 -18
  149. package/docs/design/bg-fetch-before.gv.png +0 -0
  150. package/docs/design/bg-fetch.md +0 -134
  151. package/docs/design/cast.gv +0 -35
  152. package/docs/design/cast.gv.png +0 -0
  153. package/docs/design/chromecast.md +0 -151
  154. package/docs/design/codec_preferences.md +0 -158
  155. package/docs/design/dash-audio-channels.md +0 -123
  156. package/docs/design/dash-manifests.md +0 -248
  157. package/docs/design/dash-timeline.svg +0 -4
  158. package/docs/design/dataflow.gv +0 -66
  159. package/docs/design/dataflow.gv.png +0 -0
  160. package/docs/design/export.md +0 -70
  161. package/docs/design/fuzzy-locale-matching.md +0 -40
  162. package/docs/design/gap-jumping.md +0 -151
  163. package/docs/design/lcevc-architecture.png +0 -0
  164. package/docs/design/lcevc-demo.png +0 -0
  165. package/docs/design/lcevc-integration.md +0 -72
  166. package/docs/design/locale_compatibility.svg +0 -1
  167. package/docs/design/locales_tree.svg +0 -1
  168. package/docs/design/localization-design-principles.md +0 -158
  169. package/docs/design/newdemo.gv +0 -83
  170. package/docs/design/newdemo.gv.png +0 -0
  171. package/docs/design/offline.gv +0 -43
  172. package/docs/design/offline.gv.png +0 -0
  173. package/docs/design/offline.md +0 -153
  174. package/docs/design/ownership.gv +0 -76
  175. package/docs/design/ownership.gv.png +0 -0
  176. package/docs/design/preload.md +0 -299
  177. package/docs/design/preload.png +0 -0
  178. package/docs/design/talking-about-languages.md +0 -46
  179. package/docs/design/timeline.svg +0 -152
  180. package/docs/design/ui.md +0 -31
  181. package/docs/design/ui_player_relationships.svg +0 -1
  182. package/docs/jsdoc-plugin.js +0 -74
  183. package/docs/jsdoc-template/README.md +0 -1
  184. package/docs/jsdoc-template/publish.js +0 -879
  185. package/docs/jsdoc-template/static/fonts/OpenSans-Bold-webfont.eot +0 -0
  186. package/docs/jsdoc-template/static/fonts/OpenSans-Bold-webfont.svg +0 -1830
  187. package/docs/jsdoc-template/static/fonts/OpenSans-Bold-webfont.woff +0 -0
  188. package/docs/jsdoc-template/static/fonts/OpenSans-BoldItalic-webfont.eot +0 -0
  189. package/docs/jsdoc-template/static/fonts/OpenSans-BoldItalic-webfont.svg +0 -1830
  190. package/docs/jsdoc-template/static/fonts/OpenSans-BoldItalic-webfont.woff +0 -0
  191. package/docs/jsdoc-template/static/fonts/OpenSans-Italic-webfont.eot +0 -0
  192. package/docs/jsdoc-template/static/fonts/OpenSans-Italic-webfont.svg +0 -1830
  193. package/docs/jsdoc-template/static/fonts/OpenSans-Italic-webfont.woff +0 -0
  194. package/docs/jsdoc-template/static/fonts/OpenSans-Light-webfont.eot +0 -0
  195. package/docs/jsdoc-template/static/fonts/OpenSans-Light-webfont.svg +0 -1831
  196. package/docs/jsdoc-template/static/fonts/OpenSans-Light-webfont.woff +0 -0
  197. package/docs/jsdoc-template/static/fonts/OpenSans-LightItalic-webfont.eot +0 -0
  198. package/docs/jsdoc-template/static/fonts/OpenSans-LightItalic-webfont.svg +0 -1835
  199. package/docs/jsdoc-template/static/fonts/OpenSans-LightItalic-webfont.woff +0 -0
  200. package/docs/jsdoc-template/static/fonts/OpenSans-Regular-webfont.eot +0 -0
  201. package/docs/jsdoc-template/static/fonts/OpenSans-Regular-webfont.svg +0 -1831
  202. package/docs/jsdoc-template/static/fonts/OpenSans-Regular-webfont.woff +0 -0
  203. package/docs/jsdoc-template/static/scripts/linenumber.js +0 -44
  204. package/docs/jsdoc-template/static/scripts/show-widget.js +0 -55
  205. package/docs/jsdoc-template/static/styles/jsdoc-default.css +0 -438
  206. package/docs/jsdoc-template/tmpl/augments.tmpl +0 -10
  207. package/docs/jsdoc-template/tmpl/container.tmpl +0 -205
  208. package/docs/jsdoc-template/tmpl/details.tmpl +0 -152
  209. package/docs/jsdoc-template/tmpl/example.tmpl +0 -2
  210. package/docs/jsdoc-template/tmpl/examples.tmpl +0 -13
  211. package/docs/jsdoc-template/tmpl/exceptions.tmpl +0 -32
  212. package/docs/jsdoc-template/tmpl/layout.tmpl +0 -50
  213. package/docs/jsdoc-template/tmpl/mainpage.tmpl +0 -14
  214. package/docs/jsdoc-template/tmpl/members.tmpl +0 -47
  215. package/docs/jsdoc-template/tmpl/method.tmpl +0 -140
  216. package/docs/jsdoc-template/tmpl/modifies.tmpl +0 -14
  217. package/docs/jsdoc-template/tmpl/params.tmpl +0 -131
  218. package/docs/jsdoc-template/tmpl/properties.tmpl +0 -125
  219. package/docs/jsdoc-template/tmpl/returns.tmpl +0 -19
  220. package/docs/jsdoc-template/tmpl/source.tmpl +0 -8
  221. package/docs/jsdoc-template/tmpl/tutorial.tmpl +0 -21
  222. package/docs/jsdoc-template/tmpl/type.tmpl +0 -7
  223. package/docs/jsdoc.conf.json +0 -38
  224. package/docs/shaka-player-logo.png +0 -0
  225. package/docs/style.md +0 -174
  226. package/docs/tutorials/a11y.md +0 -64
  227. package/docs/tutorials/ad_monetization.md +0 -292
  228. package/docs/tutorials/application-level-redirects.md +0 -94
  229. package/docs/tutorials/architecture.md +0 -32
  230. package/docs/tutorials/basic-usage.md +0 -89
  231. package/docs/tutorials/blob-url.md +0 -15
  232. package/docs/tutorials/config.md +0 -148
  233. package/docs/tutorials/debugging.md +0 -189
  234. package/docs/tutorials/drm-config.md +0 -274
  235. package/docs/tutorials/errors.md +0 -95
  236. package/docs/tutorials/fairplay.md +0 -242
  237. package/docs/tutorials/faq.md +0 -252
  238. package/docs/tutorials/index.json +0 -29
  239. package/docs/tutorials/lcevc.md +0 -118
  240. package/docs/tutorials/license-server-auth.md +0 -248
  241. package/docs/tutorials/license-wrapping.md +0 -168
  242. package/docs/tutorials/manifest-parser.md +0 -365
  243. package/docs/tutorials/network-and-buffering-config.md +0 -119
  244. package/docs/tutorials/offline.md +0 -683
  245. package/docs/tutorials/plugins.md +0 -184
  246. package/docs/tutorials/selenium-grid-config.md +0 -174
  247. package/docs/tutorials/service-worker.md +0 -106
  248. package/docs/tutorials/ui-customization.md +0 -288
  249. package/docs/tutorials/ui.md +0 -232
  250. package/docs/tutorials/upgrade-manifest.md +0 -281
  251. package/docs/tutorials/upgrade.md +0 -104
  252. package/docs/tutorials/welcome.md +0 -108
  253. package/docs/tutorials/widevine-service-certs.md +0 -45
  254. package/karma.conf.js +0 -879
  255. package/maintained-branches.md +0 -15
  256. package/roadmap.md +0 -186
  257. package/test/abr/simple_abr_manager_unit.js +0 -398
  258. package/test/ads/ad_manager_unit.js +0 -260
  259. package/test/assumptions/uint8_array_unit.js +0 -22
  260. package/test/cast/cast_proxy_unit.js +0 -736
  261. package/test/cast/cast_receiver_integration.js +0 -488
  262. package/test/cast/cast_receiver_unit.js +0 -1183
  263. package/test/cast/cast_sender_unit.js +0 -973
  264. package/test/cast/cast_utils_unit.js +0 -311
  265. package/test/cea/cea608_memory_unit.js +0 -411
  266. package/test/cea/cea708_service_unit.js +0 -674
  267. package/test/cea/cea708_window_unit.js +0 -373
  268. package/test/cea/cea_decoder_unit.js +0 -615
  269. package/test/cea/dtvcc_packet_builder_unit.js +0 -158
  270. package/test/cea/dtvcc_packet_unit.js +0 -60
  271. package/test/cea/mp4_cea_parser_unit.js +0 -127
  272. package/test/codec_switching/codec_switching_integration.js +0 -182
  273. package/test/dash/dash_parser_content_protection_unit.js +0 -998
  274. package/test/dash/dash_parser_integration.js +0 -74
  275. package/test/dash/dash_parser_live_unit.js +0 -1542
  276. package/test/dash/dash_parser_manifest_unit.js +0 -3121
  277. package/test/dash/dash_parser_segment_base_unit.js +0 -421
  278. package/test/dash/dash_parser_segment_list_unit.js +0 -380
  279. package/test/dash/dash_parser_segment_template_unit.js +0 -910
  280. package/test/dash/mpd_utils_unit.js +0 -794
  281. package/test/demo/demo_unit.js +0 -108
  282. package/test/deprecate/enforcer_unit.js +0 -74
  283. package/test/deprecate/version_unit.js +0 -57
  284. package/test/hls/hls_live_unit.js +0 -1330
  285. package/test/hls/hls_parser_unit.js +0 -5276
  286. package/test/hls/manifest_text_parser_unit.js +0 -545
  287. package/test/media/adaptation_set_criteria_unit.js +0 -806
  288. package/test/media/adaptation_set_unit.js +0 -229
  289. package/test/media/buffering_observer_unit.js +0 -143
  290. package/test/media/closed_caption_parser_unit.js +0 -18
  291. package/test/media/content_workarounds_unit.js +0 -43
  292. package/test/media/drm_engine_integration.js +0 -356
  293. package/test/media/drm_engine_unit.js +0 -2805
  294. package/test/media/media_source_engine_integration.js +0 -691
  295. package/test/media/media_source_engine_unit.js +0 -1512
  296. package/test/media/mp4_segment_index_parser_unit.js +0 -80
  297. package/test/media/play_rate_controller_unit.js +0 -69
  298. package/test/media/playhead_unit.js +0 -1394
  299. package/test/media/presentation_timeline_unit.js +0 -477
  300. package/test/media/quality_observer_unit.js +0 -138
  301. package/test/media/region_observer_unit.js +0 -374
  302. package/test/media/region_timeline_unit.js +0 -139
  303. package/test/media/segment_index_unit.js +0 -1080
  304. package/test/media/segment_prefetch_unit.js +0 -243
  305. package/test/media/segment_reference_unit.js +0 -63
  306. package/test/media/stall_detector_unit.js +0 -184
  307. package/test/media/streaming_engine_integration.js +0 -632
  308. package/test/media/streaming_engine_unit.js +0 -4211
  309. package/test/media/time_ranges_utils_unit.js +0 -123
  310. package/test/media/webm_segment_index_parser_unit.js +0 -90
  311. package/test/mss/mss_parser_content_protection_unit.js +0 -49
  312. package/test/mss/mss_parser_unit.js +0 -474
  313. package/test/mss/mss_player_integration.js +0 -124
  314. package/test/net/data_uri_plugin_unit.js +0 -105
  315. package/test/net/http_plugin_unit.js +0 -439
  316. package/test/net/networking_engine_unit.js +0 -1236
  317. package/test/net/networking_utils_unit.js +0 -37
  318. package/test/offline/download_progress_estimator_unit.js +0 -90
  319. package/test/offline/indexeddb_storage_unit.js +0 -192
  320. package/test/offline/manifest_convert_unit.js +0 -622
  321. package/test/offline/offline_integration.js +0 -168
  322. package/test/offline/offline_manifest_parser_unit.js +0 -231
  323. package/test/offline/offline_scheme_unit.js +0 -154
  324. package/test/offline/offline_uri_unit.js +0 -59
  325. package/test/offline/storage_compatibility_unit.js +0 -344
  326. package/test/offline/storage_integration.js +0 -1858
  327. package/test/player_external.js +0 -237
  328. package/test/player_integration.js +0 -1371
  329. package/test/player_load_graph_integration.js +0 -865
  330. package/test/player_src_equals_external.js +0 -154
  331. package/test/player_src_equals_integration.js +0 -527
  332. package/test/player_unit.js +0 -4465
  333. package/test/polyfill/media_capabilities_unit.js +0 -277
  334. package/test/polyfill/patchedmediakeys_apple_unit.js +0 -130
  335. package/test/test/assets/3675/chunk-stream0-00001.m4s +0 -0
  336. package/test/test/assets/3675/chunk-stream0-00002.m4s +0 -0
  337. package/test/test/assets/3675/chunk-stream0-00003.m4s +0 -0
  338. package/test/test/assets/3675/chunk-stream0-00004.m4s +0 -0
  339. package/test/test/assets/3675/chunk-stream0-00005.m4s +0 -0
  340. package/test/test/assets/3675/chunk-stream0-00006.m4s +0 -0
  341. package/test/test/assets/3675/chunk-stream0-00007.m4s +0 -0
  342. package/test/test/assets/3675/dash_0.mpd +0 -30
  343. package/test/test/assets/3675/dash_1.mpd +0 -30
  344. package/test/test/assets/3675/dash_2.mpd +0 -30
  345. package/test/test/assets/3675/dash_3.mpd +0 -30
  346. package/test/test/assets/3675/dash_4.mpd +0 -30
  347. package/test/test/assets/3675/dash_5.mpd +0 -26
  348. package/test/test/assets/3675/init-stream0.m4s +0 -0
  349. package/test/test/assets/audio-xhe-aac.mp4 +0 -0
  350. package/test/test/assets/audio.ts +0 -0
  351. package/test/test/assets/captions-test.ts +0 -0
  352. package/test/test/assets/cea-init.mp4 +0 -0
  353. package/test/test/assets/cea-segment.mp4 +0 -0
  354. package/test/test/assets/chapters.srt +0 -11
  355. package/test/test/assets/chapters.vtt +0 -10
  356. package/test/test/assets/chapters2.vtt +0 -10
  357. package/test/test/assets/dash-aes-128/Fragments(video=0,format=mpd-time-csf) +0 -0
  358. package/test/test/assets/dash-aes-128/Fragments(video=20000000,format=mpd-time-csf) +0 -0
  359. package/test/test/assets/dash-aes-128/Fragments(video=40000000,format=mpd-time-csf) +0 -0
  360. package/test/test/assets/dash-aes-128/Fragments(video=60000000,format=mpd-time-csf) +0 -0
  361. package/test/test/assets/dash-aes-128/Fragments(video=i,format=mpd-time-csf) +0 -0
  362. package/test/test/assets/dash-aes-128/dash.mpd +0 -18
  363. package/test/test/assets/dash-aes-128/license +0 -1
  364. package/test/test/assets/dash-multi-codec/audio_en_2c_128k_aac.mp4 +0 -0
  365. package/test/test/assets/dash-multi-codec/audio_es_2c_64k_opus.webm +0 -0
  366. package/test/test/assets/dash-multi-codec/dash.mpd +0 -32
  367. package/test/test/assets/dash-multi-codec/video_144p_108k_h264.mp4 +0 -0
  368. package/test/test/assets/db-dump-v1.json +0 -1
  369. package/test/test/assets/db-dump-v2-broken.json +0 -1
  370. package/test/test/assets/db-dump-v2-clean.json +0 -1
  371. package/test/test/assets/db-dump-v3.json +0 -1
  372. package/test/test/assets/db-dump-v4-broken.json +0 -1
  373. package/test/test/assets/db-dump-v5.json +0 -1
  374. package/test/test/assets/empty_caption_video_init.mp4 +0 -0
  375. package/test/test/assets/empty_caption_video_segment.mp4 +0 -0
  376. package/test/test/assets/encrypted-sintel-audio-init.mp4 +0 -0
  377. package/test/test/assets/encrypted-sintel-audio-segment.mp4 +0 -0
  378. package/test/test/assets/encrypted-sintel-video-init.mp4 +0 -0
  379. package/test/test/assets/encrypted-sintel-video-segment.mp4 +0 -0
  380. package/test/test/assets/green-pixel.mp4 +0 -0
  381. package/test/test/assets/green-pixel.txt +0 -15
  382. package/test/test/assets/h265-cea-init.mp4 +0 -0
  383. package/test/test/assets/h265-cea-segment.mp4 +0 -0
  384. package/test/test/assets/hls-raw-aac/fileSequence0.aac +0 -0
  385. package/test/test/assets/hls-raw-aac/fileSequence1.aac +0 -0
  386. package/test/test/assets/hls-raw-aac/fileSequence2.aac +0 -0
  387. package/test/test/assets/hls-raw-aac/fileSequence3.aac +0 -0
  388. package/test/test/assets/hls-raw-aac/manifest.m3u8 +0 -4
  389. package/test/test/assets/hls-raw-aac/stream.m4a.m3u8 +0 -14
  390. package/test/test/assets/hls-raw-ac3/fileSequence0.ac3 +0 -0
  391. package/test/test/assets/hls-raw-ac3/fileSequence1.ac3 +0 -0
  392. package/test/test/assets/hls-raw-ac3/fileSequence2.ac3 +0 -0
  393. package/test/test/assets/hls-raw-ac3/fileSequence3.ac3 +0 -0
  394. package/test/test/assets/hls-raw-ac3/fileSequence4.ac3 +0 -0
  395. package/test/test/assets/hls-raw-ac3/fileSequence5.ac3 +0 -0
  396. package/test/test/assets/hls-raw-ac3/fileSequence6.ac3 +0 -0
  397. package/test/test/assets/hls-raw-ac3/fileSequence7.ac3 +0 -0
  398. package/test/test/assets/hls-raw-ac3/prog_index.m3u8 +0 -31
  399. package/test/test/assets/hls-raw-ec3/fileSequence0.ec3 +0 -0
  400. package/test/test/assets/hls-raw-ec3/fileSequence1.ec3 +0 -0
  401. package/test/test/assets/hls-raw-ec3/fileSequence2.ec3 +0 -0
  402. package/test/test/assets/hls-raw-ec3/fileSequence3.ec3 +0 -0
  403. package/test/test/assets/hls-raw-ec3/fileSequence4.ec3 +0 -0
  404. package/test/test/assets/hls-raw-ec3/fileSequence5.ec3 +0 -0
  405. package/test/test/assets/hls-raw-ec3/fileSequence6.ec3 +0 -0
  406. package/test/test/assets/hls-raw-ec3/fileSequence7.ec3 +0 -0
  407. package/test/test/assets/hls-raw-ec3/prog_index.m3u8 +0 -31
  408. package/test/test/assets/hls-raw-mp3/chunklist_w905519204.m3u8 +0 -13
  409. package/test/test/assets/hls-raw-mp3/media_w905519204_0.mp3 +0 -0
  410. package/test/test/assets/hls-raw-mp3/media_w905519204_1.mp3 +0 -0
  411. package/test/test/assets/hls-raw-mp3/media_w905519204_2.mp3 +0 -0
  412. package/test/test/assets/hls-raw-mp3/media_w905519204_3.mp3 +0 -0
  413. package/test/test/assets/hls-raw-mp3/playlist.m3u8 +0 -4
  414. package/test/test/assets/hls-ts-aac/playlist.m3u8 +0 -23
  415. package/test/test/assets/hls-ts-aac/segment_0.ts +0 -0
  416. package/test/test/assets/hls-ts-aac/segment_1.ts +0 -0
  417. package/test/test/assets/hls-ts-aac/segment_2.ts +0 -0
  418. package/test/test/assets/hls-ts-aac/segment_3.ts +0 -0
  419. package/test/test/assets/hls-ts-aac/segment_4.ts +0 -0
  420. package/test/test/assets/hls-ts-aac/segment_5.ts +0 -0
  421. package/test/test/assets/hls-ts-aac/segment_6.ts +0 -0
  422. package/test/test/assets/hls-ts-aac/segment_7.ts +0 -0
  423. package/test/test/assets/hls-ts-ac3/ChID_voices_6ch_640kbps_dd_sub_0000.ts +0 -0
  424. package/test/test/assets/hls-ts-ac3/ChID_voices_6ch_640kbps_dd_sub_0001.ts +0 -0
  425. package/test/test/assets/hls-ts-ac3/ChID_voices_6ch_640kbps_dd_sub_0002.ts +0 -0
  426. package/test/test/assets/hls-ts-ac3/ChID_voices_6ch_640kbps_dd_sub_0003.ts +0 -0
  427. package/test/test/assets/hls-ts-ac3/ChID_voices_6ch_640kbps_dd_sub_0004.ts +0 -0
  428. package/test/test/assets/hls-ts-ac3/ChID_voices_6ch_640kbps_dd_sub_0005.ts +0 -0
  429. package/test/test/assets/hls-ts-ac3/prog_index.m3u8 +0 -19
  430. package/test/test/assets/hls-ts-ec3/ChID_voices_6ch_256kbps_ddp_sub_0000.ts +0 -0
  431. package/test/test/assets/hls-ts-ec3/ChID_voices_6ch_256kbps_ddp_sub_0001.ts +0 -0
  432. package/test/test/assets/hls-ts-ec3/ChID_voices_6ch_256kbps_ddp_sub_0002.ts +0 -0
  433. package/test/test/assets/hls-ts-ec3/ChID_voices_6ch_256kbps_ddp_sub_0003.ts +0 -0
  434. package/test/test/assets/hls-ts-ec3/ChID_voices_6ch_256kbps_ddp_sub_0004.ts +0 -0
  435. package/test/test/assets/hls-ts-ec3/ChID_voices_6ch_256kbps_ddp_sub_0005.ts +0 -0
  436. package/test/test/assets/hls-ts-ec3/prog_index.m3u8 +0 -19
  437. package/test/test/assets/hls-ts-h264/fileSequence0.ts +0 -0
  438. package/test/test/assets/hls-ts-h264/fileSequence1.ts +0 -0
  439. package/test/test/assets/hls-ts-h264/fileSequence2.ts +0 -0
  440. package/test/test/assets/hls-ts-h264/fileSequence3.ts +0 -0
  441. package/test/test/assets/hls-ts-h264/fileSequence4.ts +0 -0
  442. package/test/test/assets/hls-ts-h264/fileSequence5.ts +0 -0
  443. package/test/test/assets/hls-ts-h264/prog_index.m3u8 +0 -25
  444. package/test/test/assets/hls-ts-h265/0.ts +0 -0
  445. package/test/test/assets/hls-ts-h265/hevc.m3u8 +0 -6
  446. package/test/test/assets/hls-ts-h265/index.m3u8 +0 -7
  447. package/test/test/assets/hls-ts-mp3/manifest.m3u8 +0 -13
  448. package/test/test/assets/hls-ts-mp3/media_w239891843_0.ts +0 -0
  449. package/test/test/assets/hls-ts-mp3/media_w239891843_1.ts +0 -0
  450. package/test/test/assets/hls-ts-mp3/media_w239891843_2.ts +0 -0
  451. package/test/test/assets/hls-ts-mp3/media_w239891843_3.ts +0 -0
  452. package/test/test/assets/hls-ts-muxed-aac-h264/chunk.m3u8 +0 -17
  453. package/test/test/assets/hls-ts-muxed-aac-h264/n_0_0_0.ts +0 -0
  454. package/test/test/assets/hls-ts-muxed-aac-h264/n_1_0_0.ts +0 -0
  455. package/test/test/assets/hls-ts-muxed-aac-h264/n_2_0_0.ts +0 -0
  456. package/test/test/assets/hls-ts-muxed-aac-h264/n_3_0_0.ts +0 -0
  457. package/test/test/assets/hls-ts-muxed-aac-h264/n_4_0_0.ts +0 -0
  458. package/test/test/assets/hls-ts-muxed-aac-h264/n_5_0_0.ts +0 -0
  459. package/test/test/assets/hls-ts-muxed-aac-h264/playlist.m3u8 +0 -4
  460. package/test/test/assets/hls-ts-muxed-aac-h265/0.ts +0 -0
  461. package/test/test/assets/hls-ts-muxed-aac-h265/1.ts +0 -0
  462. package/test/test/assets/hls-ts-muxed-aac-h265/media.m3u8 +0 -9
  463. package/test/test/assets/hls-ts-muxed-ac3-h264/media.m3u8 +0 -24
  464. package/test/test/assets/hls-ts-muxed-ac3-h264/s_00000.ts +0 -0
  465. package/test/test/assets/hls-ts-muxed-ac3-h264/s_00001.ts +0 -0
  466. package/test/test/assets/hls-ts-muxed-ac3-h264/s_00002.ts +0 -0
  467. package/test/test/assets/hls-ts-muxed-ac3-h264/s_00003.ts +0 -0
  468. package/test/test/assets/hls-ts-muxed-ac3-h264/s_00004.ts +0 -0
  469. package/test/test/assets/hls-ts-muxed-ac3-h264/s_00005.ts +0 -0
  470. package/test/test/assets/hls-ts-muxed-ec3-h264/ChID_voices_1280x720p_25fps_h264_6ch_256kbps_ddp_sub_0000.ts +0 -0
  471. package/test/test/assets/hls-ts-muxed-ec3-h264/ChID_voices_1280x720p_25fps_h264_6ch_256kbps_ddp_sub_0001.ts +0 -0
  472. package/test/test/assets/hls-ts-muxed-ec3-h264/ChID_voices_1280x720p_25fps_h264_6ch_256kbps_ddp_sub_0002.ts +0 -0
  473. package/test/test/assets/hls-ts-muxed-ec3-h264/ChID_voices_1280x720p_25fps_h264_6ch_256kbps_ddp_sub_0003.ts +0 -0
  474. package/test/test/assets/hls-ts-muxed-ec3-h264/prog_index.m3u8 +0 -14
  475. package/test/test/assets/hls-ts-muxed-mp3-h264/index.m3u8 +0 -23
  476. package/test/test/assets/hls-ts-muxed-mp3-h264/seg-1-v1-a1.ts +0 -0
  477. package/test/test/assets/hls-ts-muxed-mp3-h264/seg-2-v1-a1.ts +0 -0
  478. package/test/test/assets/hls-ts-muxed-mp3-h264/seg-3-v1-a1.ts +0 -0
  479. package/test/test/assets/hls-ts-muxed-mp3-h264/seg-4-v1-a1.ts +0 -0
  480. package/test/test/assets/hls-ts-muxed-mp3-h264/seg-5-v1-a1.ts +0 -0
  481. package/test/test/assets/hls-ts-muxed-mp3-h264/seg-6-v1-a1.ts +0 -0
  482. package/test/test/assets/hls-ts-muxed-mp3-h264/seg-7-v1-a1.ts +0 -0
  483. package/test/test/assets/hls-ts-muxed-mp3-h264/seg-8-v1-a1.ts +0 -0
  484. package/test/test/assets/id3-metadata.aac +0 -0
  485. package/test/test/assets/id3-metadata.ts +0 -0
  486. package/test/test/assets/index-segment.mp4 +0 -0
  487. package/test/test/assets/index-segment.webm +0 -0
  488. package/test/test/assets/init-segment.webm +0 -0
  489. package/test/test/assets/large_file.mpd +0 -4930
  490. package/test/test/assets/multidrm-audio-init.mp4 +0 -0
  491. package/test/test/assets/multidrm-audio-segment.mp4 +0 -0
  492. package/test/test/assets/multidrm-video-init.mp4 +0 -0
  493. package/test/test/assets/multidrm-video-segment.mp4 +0 -0
  494. package/test/test/assets/multiple-trun-init.mp4 +0 -0
  495. package/test/test/assets/multiple-trun-segment.mp4 +0 -0
  496. package/test/test/assets/sintel-audio-init.mp4 +0 -0
  497. package/test/test/assets/sintel-audio-segment.mp4 +0 -0
  498. package/test/test/assets/sintel-video-init.mp4 +0 -0
  499. package/test/test/assets/sintel-video-segment.mp4 +0 -0
  500. package/test/test/assets/small.mp4 +0 -0
  501. package/test/test/assets/text-clip-alt.vtt +0 -63
  502. package/test/test/assets/text-clip.vtt +0 -63
  503. package/test/test/assets/thumbnails-sprites.vtt +0 -10
  504. package/test/test/assets/thumbnails.vtt +0 -10
  505. package/test/test/assets/ttml-init.mp4 +0 -0
  506. package/test/test/assets/ttml-segment-multiplemdat.mp4 +0 -0
  507. package/test/test/assets/ttml-segment.mp4 +0 -0
  508. package/test/test/assets/video.ts +0 -0
  509. package/test/test/assets/vtt-init.mp4 +0 -0
  510. package/test/test/assets/vtt-segment-multi-payload.mp4 +0 -0
  511. package/test/test/assets/vtt-segment-no-duration.mp4 +0 -0
  512. package/test/test/assets/vtt-segment-settings.mp4 +0 -0
  513. package/test/test/assets/vtt-segment.mp4 +0 -0
  514. package/test/test/boot.js +0 -495
  515. package/test/test/externs/filters.js +0 -44
  516. package/test/test/externs/fontfaceonload.js +0 -29
  517. package/test/test/externs/jasmine.js +0 -670
  518. package/test/test/externs/karma.js +0 -26
  519. package/test/test/externs/require.js +0 -21
  520. package/test/test/externs/sprintf.js +0 -18
  521. package/test/test/namespace.js +0 -10
  522. package/test/test/util/canned_idb.js +0 -379
  523. package/test/test/util/cea_utils.js +0 -60
  524. package/test/test/util/dash_parser_util.js +0 -329
  525. package/test/test/util/fake_ad.js +0 -321
  526. package/test/test/util/fake_ad_manager.js +0 -122
  527. package/test/test/util/fake_demo_main.js +0 -144
  528. package/test/test/util/fake_drm_engine.js +0 -103
  529. package/test/test/util/fake_media_source_engine.js +0 -464
  530. package/test/test/util/fake_networking_engine.js +0 -381
  531. package/test/test/util/fake_segment_prefetch.js +0 -84
  532. package/test/test/util/fake_text_displayer.js +0 -60
  533. package/test/test/util/id3_generator.js +0 -100
  534. package/test/test/util/indexeddb_utils.js +0 -124
  535. package/test/test/util/jasmine_fetch.js +0 -382
  536. package/test/test/util/layout_tests.js +0 -435
  537. package/test/test/util/loader.js +0 -88
  538. package/test/test/util/manifest_generator.js +0 -705
  539. package/test/test/util/manifest_parser_util.js +0 -101
  540. package/test/test/util/mss_parser_util.js +0 -119
  541. package/test/test/util/offline_utils.js +0 -105
  542. package/test/test/util/simple_fakes.js +0 -535
  543. package/test/test/util/stream_generator.js +0 -676
  544. package/test/test/util/streaming_engine_util.js +0 -506
  545. package/test/test/util/test_scheme.js +0 -778
  546. package/test/test/util/ttml_utils.js +0 -77
  547. package/test/test/util/ui_utils.js +0 -183
  548. package/test/test/util/util.js +0 -374
  549. package/test/test/util/waiter.js +0 -406
  550. package/test/text/cue_integration.js +0 -51
  551. package/test/text/lrc_text_parser_unit.js +0 -98
  552. package/test/text/mp4_ttml_parser_unit.js +0 -171
  553. package/test/text/mp4_vtt_parser_unit.js +0 -195
  554. package/test/text/sbv_text_parser_unit.js +0 -81
  555. package/test/text/simple_text_displayer_unit.js +0 -468
  556. package/test/text/srt_text_parser_unit.js +0 -163
  557. package/test/text/ssa_text_parser_unit.js +0 -382
  558. package/test/text/text_displayer_layout_unit.js +0 -323
  559. package/test/text/text_engine_unit.js +0 -500
  560. package/test/text/text_track_integration.js +0 -186
  561. package/test/text/ttml_text_parser_unit.js +0 -2176
  562. package/test/text/ui_text_displayer_unit.js +0 -608
  563. package/test/text/vtt_text_parser_unit.js +0 -1363
  564. package/test/text/web_vtt_generator_unit.js +0 -144
  565. package/test/text/web_vtt_layout_integration.js +0 -524
  566. package/test/transmuxer/transmuxer_engine_integration.js +0 -69
  567. package/test/transmuxer/transmuxer_integration.js +0 -443
  568. package/test/ui/ad_ui_unit.js +0 -369
  569. package/test/ui/localization_unit.js +0 -508
  570. package/test/ui/ui_customization_unit.js +0 -208
  571. package/test/ui/ui_integration.js +0 -669
  572. package/test/ui/ui_unit.js +0 -902
  573. package/test/util/abortable_operation_unit.js +0 -624
  574. package/test/util/array_utils_unit.js +0 -58
  575. package/test/util/buffer_utils_unit.js +0 -185
  576. package/test/util/cmcd_manager_unit.js +0 -440
  577. package/test/util/content_steering_manager_unit.js +0 -427
  578. package/test/util/data_view_reader_unit.js +0 -254
  579. package/test/util/ebml_parser_unit.js +0 -297
  580. package/test/util/event_manager_unit.js +0 -185
  581. package/test/util/fake_event_target_unit.js +0 -123
  582. package/test/util/id3_utils_unit.js +0 -168
  583. package/test/util/iterables_unit.js +0 -68
  584. package/test/util/language_utils_unit.js +0 -240
  585. package/test/util/manifest_parser_utils_unit.js +0 -55
  586. package/test/util/mime_utils_unit.js +0 -64
  587. package/test/util/mp4_box_parsers_unit.js +0 -246
  588. package/test/util/mp4_parser_unit.js +0 -373
  589. package/test/util/multi_map_unit.js +0 -94
  590. package/test/util/object_utils_unit.js +0 -79
  591. package/test/util/periods_unit.js +0 -1623
  592. package/test/util/pssh_unit.js +0 -226
  593. package/test/util/state_history_unit.js +0 -101
  594. package/test/util/stream_utils_unit.js +0 -1068
  595. package/test/util/string_utils_unit.js +0 -166
  596. package/test/util/text_parser_unit.js +0 -165
  597. package/test/util/ts_parser_unit.js +0 -77
  598. 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
- });