shaka-player 3.1.4 → 3.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (214) hide show
  1. package/.github/ISSUE_TEMPLATE/bug_report.md +1 -1
  2. package/.github/ISSUE_TEMPLATE/feature_request.md +1 -1
  3. package/.github/ISSUE_TEMPLATE/question.md +1 -1
  4. package/AUTHORS +6 -5
  5. package/CHANGELOG.md +363 -0
  6. package/CONTRIBUTORS +4 -2
  7. package/README.md +4 -4
  8. package/build/types/core +3 -0
  9. package/build/types/offline +1 -0
  10. package/build/types/polyfill +2 -0
  11. package/build/types/ui +2 -0
  12. package/demo/common/asset.js +9 -7
  13. package/demo/common/assets.js +28 -1
  14. package/demo/common/message_ids.js +15 -2
  15. package/demo/config.js +35 -2
  16. package/demo/index.html +1 -1
  17. package/demo/locales/en.json +14 -1
  18. package/demo/locales/source.json +56 -4
  19. package/demo/main.js +2 -1
  20. package/dist/controls.css +26 -2
  21. package/dist/controls.css.map +1 -1
  22. package/dist/demo.compiled.debug.js +24 -21
  23. package/dist/demo.compiled.debug.map +3 -3
  24. package/dist/demo.compiled.js +24 -21
  25. package/dist/demo.compiled.map +3 -3
  26. package/dist/deps.js +33 -25
  27. package/dist/locales.js +31 -29
  28. package/dist/receiver.compiled.debug.js +14 -12
  29. package/dist/receiver.compiled.debug.map +3 -3
  30. package/dist/receiver.compiled.js +14 -12
  31. package/dist/receiver.compiled.map +3 -3
  32. package/dist/shaka-player.compiled.d.ts +258 -20
  33. package/dist/shaka-player.compiled.debug.d.ts +258 -20
  34. package/dist/shaka-player.compiled.debug.externs.js +1005 -695
  35. package/dist/shaka-player.compiled.debug.js +720 -640
  36. package/dist/shaka-player.compiled.debug.map +4 -4
  37. package/dist/shaka-player.compiled.externs.js +1005 -695
  38. package/dist/shaka-player.compiled.js +850 -817
  39. package/dist/shaka-player.compiled.map +4 -4
  40. package/dist/shaka-player.ui.d.ts +274 -21
  41. package/dist/shaka-player.ui.debug.d.ts +274 -21
  42. package/dist/shaka-player.ui.debug.externs.js +766 -429
  43. package/dist/shaka-player.ui.debug.js +863 -765
  44. package/dist/shaka-player.ui.debug.map +4 -4
  45. package/dist/shaka-player.ui.externs.js +766 -429
  46. package/dist/shaka-player.ui.js +1042 -996
  47. package/dist/shaka-player.ui.map +4 -4
  48. package/docs/design/bg-fetch-after.gv +29 -0
  49. package/docs/design/bg-fetch-after.gv.png +0 -0
  50. package/docs/design/bg-fetch-before.gv +18 -0
  51. package/docs/design/bg-fetch-before.gv.png +0 -0
  52. package/docs/design/bg-fetch.md +134 -0
  53. package/docs/tutorials/blob-url.md +15 -0
  54. package/docs/tutorials/index.json +1 -0
  55. package/docs/tutorials/ui-customization.md +66 -0
  56. package/docs/tutorials/ui.md +5 -5
  57. package/externs/aria.js +6 -0
  58. package/externs/ima.js +3 -0
  59. package/externs/shaka/ads.js +29 -1
  60. package/externs/shaka/manifest.js +18 -2
  61. package/externs/shaka/manifest_parser.js +10 -1
  62. package/externs/shaka/net.js +20 -4
  63. package/externs/shaka/offline.js +36 -2
  64. package/externs/shaka/player.js +182 -13
  65. package/externs/shaka/text.js +24 -10
  66. package/externs/texttrack.js +3 -0
  67. package/externs/webcrypto.js +18 -0
  68. package/lib/abr/ewma.js +14 -0
  69. package/lib/abr/ewma_bandwidth_estimator.js +16 -2
  70. package/lib/abr/simple_abr_manager.js +6 -0
  71. package/lib/ads/ad_manager.js +16 -15
  72. package/lib/ads/client_side_ad.js +8 -0
  73. package/lib/ads/client_side_ad_manager.js +14 -6
  74. package/lib/ads/server_side_ad.js +7 -0
  75. package/lib/ads/server_side_ad_manager.js +19 -2
  76. package/lib/cast/cast_proxy.js +8 -0
  77. package/lib/cast/cast_utils.js +7 -1
  78. package/lib/cea/cea608_data_channel.js +56 -56
  79. package/lib/cea/cea608_memory.js +33 -33
  80. package/lib/cea/cea708_service.js +43 -43
  81. package/lib/cea/cea708_window.js +38 -38
  82. package/lib/cea/cea_decoder.js +13 -14
  83. package/lib/cea/cea_utils.js +23 -23
  84. package/lib/cea/dtvcc_packet_builder.js +7 -7
  85. package/lib/cea/i_caption_decoder.js +2 -3
  86. package/lib/cea/i_cea_parser.js +2 -2
  87. package/lib/cea/mp4_cea_parser.js +6 -6
  88. package/lib/dash/dash_parser.js +53 -14
  89. package/lib/dash/segment_base.js +25 -1
  90. package/lib/dash/segment_list.js +18 -9
  91. package/lib/dash/segment_template.js +23 -10
  92. package/lib/hls/hls_parser.js +210 -30
  93. package/lib/media/closed_caption_parser.js +1 -2
  94. package/lib/media/drm_engine.js +162 -192
  95. package/lib/media/quality_observer.js +291 -0
  96. package/lib/media/segment_index.js +9 -1
  97. package/lib/media/segment_reference.js +37 -5
  98. package/lib/media/streaming_engine.js +48 -10
  99. package/lib/net/http_fetch_plugin.js +31 -11
  100. package/lib/net/http_plugin_utils.js +1 -0
  101. package/lib/net/http_xhr_plugin.js +40 -14
  102. package/lib/net/networking_engine.js +82 -18
  103. package/lib/offline/download_info.js +68 -0
  104. package/lib/offline/download_manager.js +14 -7
  105. package/lib/offline/indexeddb/base_storage_cell.js +35 -0
  106. package/lib/offline/indexeddb/storage_mechanism.js +1 -1
  107. package/lib/offline/indexeddb/v1_storage_cell.js +1 -0
  108. package/lib/offline/indexeddb/v2_storage_cell.js +1 -0
  109. package/lib/offline/indexeddb/v5_storage_cell.js +5 -0
  110. package/lib/offline/manifest_converter.js +3 -1
  111. package/lib/offline/storage.js +404 -297
  112. package/lib/offline/stored_content_utils.js +2 -0
  113. package/lib/player.js +622 -153
  114. package/lib/polyfill/aria.js +82 -0
  115. package/lib/polyfill/random_uuid.js +52 -0
  116. package/lib/routing/walker.js +2 -3
  117. package/lib/text/cue.js +12 -0
  118. package/lib/text/srt_text_parser.js +4 -4
  119. package/lib/text/text_engine.js +2 -2
  120. package/lib/text/ttml_text_parser.js +25 -2
  121. package/lib/text/ui_text_displayer.js +2 -2
  122. package/lib/text/vtt_text_parser.js +2 -2
  123. package/lib/text/web_vtt_generator.js +55 -12
  124. package/lib/util/cmcd_manager.js +826 -0
  125. package/lib/util/error.js +12 -0
  126. package/lib/util/language_utils.js +12 -0
  127. package/lib/util/manifest_parser_utils.js +1 -0
  128. package/lib/util/mp4_box_parsers.js +20 -20
  129. package/lib/util/multi_map.js +8 -0
  130. package/lib/util/mutex.js +52 -0
  131. package/lib/util/periods.js +98 -64
  132. package/lib/util/player_configuration.js +31 -1
  133. package/lib/util/stream_utils.js +140 -85
  134. package/lib/util/xml_utils.js +31 -12
  135. package/package.json +1 -1
  136. package/roadmap.md +24 -22
  137. package/shaka-player.uncompiled.js +4 -0
  138. package/test/cast/cast_utils_unit.js +1 -0
  139. package/test/cea/cea608_memory_unit.js +1 -1
  140. package/test/cea/cea708_service_unit.js +8 -8
  141. package/test/cea/cea708_window_unit.js +6 -6
  142. package/test/cea/cea_decoder_unit.js +1 -1
  143. package/test/cea/dtvcc_packet_builder_unit.js +2 -2
  144. package/test/dash/dash_parser_content_protection_unit.js +2 -0
  145. package/test/dash/dash_parser_live_unit.js +101 -1
  146. package/test/dash/dash_parser_manifest_unit.js +78 -2
  147. package/test/dash/dash_parser_segment_base_unit.js +2 -0
  148. package/test/dash/dash_parser_segment_list_unit.js +2 -1
  149. package/test/dash/dash_parser_segment_template_unit.js +2 -1
  150. package/test/hls/hls_live_unit.js +2 -0
  151. package/test/hls/hls_parser_unit.js +252 -0
  152. package/test/media/drm_engine_integration.js +86 -12
  153. package/test/media/drm_engine_unit.js +310 -450
  154. package/test/media/quality_observer_unit.js +139 -0
  155. package/test/media/segment_reference_unit.js +16 -1
  156. package/test/media/streaming_engine_integration.js +2 -1
  157. package/test/media/streaming_engine_unit.js +2 -0
  158. package/test/net/http_plugin_unit.js +20 -15
  159. package/test/offline/manifest_convert_unit.js +2 -0
  160. package/test/offline/storage_integration.js +117 -23
  161. package/test/player_integration.js +151 -0
  162. package/test/player_src_equals_integration.js +52 -0
  163. package/test/player_unit.js +11 -33
  164. package/test/test/assets/chapters.srt +11 -0
  165. package/test/test/assets/chapters.vtt +10 -0
  166. package/test/test/util/cea_utils.js +12 -12
  167. package/test/test/util/dash_parser_util.js +4 -0
  168. package/test/test/util/fake_ad.js +7 -0
  169. package/test/test/util/fake_ad_manager.js +7 -0
  170. package/test/test/util/fake_drm_engine.js +9 -2
  171. package/test/test/util/manifest_generator.js +5 -2
  172. package/test/test/util/manifest_parser_util.js +3 -1
  173. package/test/test/util/test_scheme.js +14 -1
  174. package/test/text/ttml_text_parser_unit.js +47 -0
  175. package/test/text/web_vtt_generator_unit.js +81 -7
  176. package/test/ui/ui_unit.js +250 -0
  177. package/test/util/cmcd_manager_unit.js +277 -0
  178. package/test/util/stream_utils_unit.js +118 -10
  179. package/ui/airplay_button.js +2 -1
  180. package/ui/audio_language_selection.js +9 -5
  181. package/ui/cast_button.js +5 -6
  182. package/ui/constants.js +0 -3
  183. package/ui/context_menu.js +109 -0
  184. package/ui/controls.js +41 -7
  185. package/ui/controls.less +1 -0
  186. package/ui/enums.js +4 -0
  187. package/ui/externs/ui.js +28 -1
  188. package/ui/fast_forward_button.js +16 -8
  189. package/ui/fullscreen_button.js +2 -3
  190. package/ui/language_utils.js +1 -1
  191. package/ui/less/buttons.less +0 -4
  192. package/ui/less/containers.less +74 -0
  193. package/ui/less/overflow_menu.less +0 -10
  194. package/ui/less/tooltip.less +97 -0
  195. package/ui/locales/en.json +1 -0
  196. package/ui/locales/source.json +4 -0
  197. package/ui/loop_button.js +6 -3
  198. package/ui/mute_button.js +3 -4
  199. package/ui/overflow_menu.js +7 -28
  200. package/ui/pip_button.js +10 -7
  201. package/ui/play_button.js +2 -2
  202. package/ui/playback_rate_selection.js +11 -15
  203. package/ui/presentation_time.js +1 -3
  204. package/ui/resolution_selection.js +11 -7
  205. package/ui/rewind_button.js +17 -9
  206. package/ui/seek_bar.js +6 -6
  207. package/ui/settings_menu.js +36 -4
  208. package/ui/small_play_button.js +1 -0
  209. package/ui/spacer.js +1 -1
  210. package/ui/statistics_button.js +253 -0
  211. package/ui/text_selection.js +19 -15
  212. package/ui/ui.js +30 -0
  213. package/ui/ui_utils.js +1 -1
  214. package/ui/volume_bar.js +2 -4
@@ -7,7 +7,6 @@
7
7
 
8
8
  goog.provide('shaka.ui.FastForwardButton');
9
9
 
10
- goog.require('shaka.ui.Constants');
11
10
  goog.require('shaka.ui.Controls');
12
11
  goog.require('shaka.ui.Element');
13
12
  goog.require('shaka.ui.Enums');
@@ -33,11 +32,16 @@ shaka.ui.FastForwardButton = class extends shaka.ui.Element {
33
32
  this.button_ = shaka.util.Dom.createButton();
34
33
  this.button_.classList.add('material-icons-round');
35
34
  this.button_.classList.add('shaka-fast-forward-button');
35
+ this.button_.classList.add('shaka-tooltip-status');
36
+ this.button_.setAttribute('shaka-status', '1x');
36
37
  this.button_.textContent =
37
38
  shaka.ui.Enums.MaterialDesignIcons.FAST_FORWARD;
38
39
  this.parent.appendChild(this.button_);
39
40
  this.updateAriaLabel_();
40
41
 
42
+ /** @private {!Array.<number>} */
43
+ this.fastForwardRates_ = this.controls.getConfig().fastForwardRates;
44
+
41
45
  this.eventManager.listen(
42
46
  this.localization, shaka.ui.Localization.LOCALE_UPDATED, () => {
43
47
  this.updateAriaLabel_();
@@ -57,12 +61,12 @@ shaka.ui.FastForwardButton = class extends shaka.ui.Element {
57
61
  * @private
58
62
  */
59
63
  updateAriaLabel_() {
60
- this.button_.setAttribute(shaka.ui.Constants.ARIA_LABEL,
61
- this.localization.resolve(shaka.ui.Locales.Ids.FAST_FORWARD));
64
+ this.button_.ariaLabel =
65
+ this.localization.resolve(shaka.ui.Locales.Ids.FAST_FORWARD);
62
66
  }
63
67
 
64
68
  /**
65
- * Cycles trick play rate between 1, 2, 4, and 8.
69
+ * Cycles trick play rate between the selected fast forward rates.
66
70
  * @private
67
71
  */
68
72
  fastForward_() {
@@ -71,11 +75,15 @@ shaka.ui.FastForwardButton = class extends shaka.ui.Element {
71
75
  }
72
76
 
73
77
  const trickPlayRate = this.player.getPlaybackRate();
74
- // Every time the button is clicked, the rate is multiplied by 2,
75
- // unless the rate is at max (8), in which case it is dropped back to 1.
76
- const newRate = (trickPlayRate < 0 || trickPlayRate > 4) ?
77
- 1 : trickPlayRate * 2;
78
+ const newRateIndex = this.fastForwardRates_.indexOf(trickPlayRate) + 1;
79
+
80
+ // When the button is clicked, the next rate in this.fastForwardRates_ is
81
+ // selected. If no more rates are available, the first one is set.
82
+ const newRate = (newRateIndex != this.fastForwardRates_.length) ?
83
+ this.fastForwardRates_[newRateIndex] : this.fastForwardRates_[0];
78
84
  this.player.trickPlay(newRate);
85
+
86
+ this.button_.setAttribute('shaka-status', newRate + 'x');
79
87
  }
80
88
  };
81
89
 
@@ -7,7 +7,6 @@
7
7
 
8
8
  goog.provide('shaka.ui.FullscreenButton');
9
9
 
10
- goog.require('shaka.ui.Constants');
11
10
  goog.require('shaka.ui.Controls');
12
11
  goog.require('shaka.ui.Element');
13
12
  goog.require('shaka.ui.Enums');
@@ -33,6 +32,7 @@ shaka.ui.FullscreenButton = class extends shaka.ui.Element {
33
32
  this.button_ = shaka.util.Dom.createButton();
34
33
  this.button_.classList.add('shaka-fullscreen-button');
35
34
  this.button_.classList.add('material-icons-round');
35
+ this.button_.classList.add('shaka-tooltip');
36
36
 
37
37
  // Don't show the button if fullscreen is not supported
38
38
  if (!document.fullscreenEnabled) {
@@ -71,8 +71,7 @@ shaka.ui.FullscreenButton = class extends shaka.ui.Element {
71
71
  const label = document.fullscreenElement ?
72
72
  LocIds.EXIT_FULL_SCREEN : LocIds.FULL_SCREEN;
73
73
 
74
- this.button_.setAttribute(shaka.ui.Constants.ARIA_LABEL,
75
- this.localization.resolve(label));
74
+ this.button_.ariaLabel = this.localization.resolve(label);
76
75
  }
77
76
 
78
77
  /**
@@ -138,7 +138,7 @@ shaka.ui.LanguageUtils = class {
138
138
  if (updateChosen && (combinationName == selectedCombination)) {
139
139
  button.appendChild(shaka.ui.Utils.checkmarkIcon());
140
140
  span.classList.add('shaka-chosen-item');
141
- button.setAttribute('aria-selected', 'true');
141
+ button.ariaSelected = 'true';
142
142
  currentSelectionElement.textContent = span.textContent;
143
143
  }
144
144
  langMenu.appendChild(button);
@@ -75,10 +75,6 @@
75
75
  .shaka-current-time {
76
76
  font-size: 14px;
77
77
  color: rgb(255, 255, 255);
78
-
79
- /* Make the time element the right size for the text, instead of defaulting
80
- * to the same size as the rest of the controls. */
81
- height: auto;
82
78
  cursor: pointer;
83
79
 
84
80
  &[disabled] {
@@ -195,6 +195,80 @@
195
195
  align-items: center;
196
196
  }
197
197
 
198
+ .shaka-statistics-container {
199
+ overflow-x: hidden;
200
+ overflow-y: auto;
201
+
202
+ min-width: 300px;
203
+
204
+ color: white;
205
+ background-color: rgba(35, 35, 35, 0.9);
206
+
207
+ font-size: 14px;
208
+
209
+ padding: 5px 10px;
210
+ border-radius: 2px;
211
+
212
+ position: absolute;
213
+ z-index: 2;
214
+ left: 15px;
215
+ top: 15px;
216
+
217
+ /* Fades out with the other controls. */
218
+ .show-when-controls-shown();
219
+
220
+ div {
221
+ display: flex;
222
+ justify-content: space-between;
223
+ }
224
+
225
+ span {
226
+ color: rgb(150, 150, 150);
227
+ }
228
+ }
229
+
230
+ .shaka-context-menu {
231
+ background-color: rgba(35, 35, 35, 0.9);
232
+
233
+ border-radius: 2px;
234
+
235
+ position: absolute;
236
+ z-index: 3;
237
+
238
+ button {
239
+ padding: 5px 10px;
240
+
241
+ width: 100%;
242
+ display: flex;
243
+ align-items: center;
244
+
245
+ color: white;
246
+ background: transparent;
247
+ border: 0;
248
+ cursor: pointer;
249
+
250
+ &:hover {
251
+ background-color: rgba(50, 50, 50, 0.9);
252
+ }
253
+ }
254
+
255
+ label {
256
+ padding: 0 20px;
257
+
258
+ align-items: flex-start;
259
+
260
+ color: white;
261
+ cursor: pointer;
262
+ }
263
+
264
+ .shaka-current-selection-span {
265
+ align-items: flex-start;
266
+
267
+ color: white;
268
+ cursor: pointer;
269
+ }
270
+ }
271
+
198
272
  .shaka-scrim-container {
199
273
  margin: 0;
200
274
  .fill-container();
@@ -141,13 +141,3 @@
141
141
  /* TODO(b/116651454): eliminate hard-coded offsets */
142
142
  left: 17px;
143
143
  }
144
-
145
- /* The captions button, when captions are on. */
146
- .shaka-captions-on {
147
- color: black;
148
- }
149
-
150
- /* The captions button, when captions are off. */
151
- .shaka-captions-off {
152
- color: grey;
153
- }
@@ -0,0 +1,97 @@
1
+ /*!
2
+ * @license
3
+ * The tooltip is based on https://github.com/felipefialho/css-components/
4
+ * Local modifications have been performed.
5
+ *
6
+ * Copyright (c) 2017 Felipe Fialho
7
+ *
8
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
9
+ * of this software and associated documentation files (the "Software"), to deal
10
+ * in the Software without restriction, including without limitation the rights
11
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12
+ * copies of the Software, and to permit persons to whom the Software is
13
+ * furnished to do so, subject to the following conditions:
14
+ *
15
+ * The above copyright notice and this permission notice shall be included in
16
+ * all copies or substantial portions of the Software.
17
+ *
18
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24
+ * SOFTWARE.
25
+ */
26
+
27
+ @material-icons-width: 32px;
28
+
29
+ .translateX(@percent) {
30
+ -webkit-transform: translateX(percentage(@percent));
31
+ -moz-transform: translateX(percentage(@percent));
32
+ -ms-transform: translateX(percentage(@percent));
33
+ -o-transform: translateX(percentage(@percent));
34
+ transform: translateX(percentage(@percent));
35
+ }
36
+
37
+ /* .shaka-tooltips-on enables the tooltips and is only added to the
38
+ * control panel when the 'enableTooltips' option is set to true */
39
+ .shaka-tooltips-on {
40
+ overflow: visible;
41
+
42
+ & > [class*="shaka-tooltip"] {
43
+ position: relative;
44
+
45
+ /* The :after pseudo-element contains the tooltip */
46
+ &:hover:after, &:focus-visible:after, &:active:after {
47
+ content: attr(aria-label);
48
+
49
+ /* Override .material-icons-round text styling */
50
+ font-family: Roboto-Regular, Roboto, sans-serif;
51
+ line-height: @material-icons-width / 2;
52
+ white-space: nowrap;
53
+ font-size: 13px;
54
+
55
+ /* Styling */
56
+ background: rgba(35, 35, 35, 0.9);
57
+ color: white;
58
+ border-radius: 3px;
59
+ padding: 5px 10px;
60
+
61
+ /* Positioning */
62
+ position: absolute;
63
+ bottom: @material-icons-width + 5px;
64
+
65
+ /* Left attribute is set to half of the width of the parent button */
66
+ left: @material-icons-width / 2;
67
+
68
+ /* The tooltip is also translated 50% to appear centered */
69
+ .translateX(-0.5);
70
+ }
71
+ }
72
+
73
+ /* Adds an additional attribute for the status in .shaka-tooltip-status */
74
+ & > .shaka-tooltip-status {
75
+ &:hover:after, &:focus-visible:after, &:active:after {
76
+ content: attr(aria-label) " (" attr(shaka-status) ")";
77
+ }
78
+ }
79
+
80
+ /* The first tooltip of the panel is not centered on top of the button
81
+ * but rather aligned with the left border of the control panel */
82
+ button:first-child {
83
+ &:hover:after, &:focus-visible:after, &:active:after {
84
+ left: 0;
85
+ .translateX(0);
86
+ }
87
+ }
88
+
89
+ /* The last tooltip of the panel is not centered on top of the button
90
+ * but rather aligned with the right border of the control panel */
91
+ button:last-child {
92
+ &:hover:after, &:focus-visible:after,&:active:after {
93
+ left: @material-icons-width;
94
+ .translateX(-1);
95
+ }
96
+ }
97
+ }
@@ -33,6 +33,7 @@
33
33
  "SEEK": "Seek",
34
34
  "SKIP_AD": "Skip Ad",
35
35
  "SKIP_TO_LIVE": "Skip ahead to live",
36
+ "STATISTICS": "Statistics",
36
37
  "SUBTITLE_FORCED": "Forced",
37
38
  "UNDETERMINED_LANGUAGE": "Undetermined",
38
39
  "UNMUTE": "Unmute",
@@ -138,6 +138,10 @@
138
138
  "description": "Label for a button used to skip ahead to the live broadcast.",
139
139
  "message": "Skip ahead to live"
140
140
  },
141
+ "STATISTICS": {
142
+ "description": "Label for a button that displays statistics of the video.",
143
+ "message": "Statistics"
144
+ },
141
145
  "SUBTITLE_FORCED": {
142
146
  "description": "Label used to identify a subtitle track that is forced to be shown.",
143
147
  "message": "Forced"
package/ui/loop_button.js CHANGED
@@ -7,7 +7,7 @@
7
7
 
8
8
  goog.provide('shaka.ui.LoopButton');
9
9
 
10
- goog.require('shaka.ui.Constants');
10
+ goog.require('shaka.ui.ContextMenu');
11
11
  goog.require('shaka.ui.Controls');
12
12
  goog.require('shaka.ui.Element');
13
13
  goog.require('shaka.ui.Enums');
@@ -36,6 +36,7 @@ shaka.ui.LoopButton = class extends shaka.ui.Element {
36
36
  /** @private {!HTMLButtonElement} */
37
37
  this.button_ = shaka.util.Dom.createButton();
38
38
  this.button_.classList.add('shaka-loop-button');
39
+ this.button_.classList.add('shaka-tooltip');
39
40
 
40
41
  /** @private {!HTMLElement} */
41
42
  this.icon_ = shaka.util.Dom.createHTMLElement('i');
@@ -151,8 +152,7 @@ shaka.ui.LoopButton = class extends shaka.ui.Element {
151
152
  const ariaText = this.video.loop ?
152
153
  LocIds.EXIT_LOOP_MODE : LocIds.ENTER_LOOP_MODE;
153
154
 
154
- this.button_.setAttribute(shaka.ui.Constants.ARIA_LABEL,
155
- this.localization.resolve(ariaText));
155
+ this.button_.ariaLabel = this.localization.resolve(ariaText);
156
156
  }
157
157
  };
158
158
 
@@ -173,3 +173,6 @@ shaka.ui.OverflowMenu.registerElement(
173
173
 
174
174
  shaka.ui.Controls.registerElement(
175
175
  'loop', new shaka.ui.LoopButton.Factory());
176
+
177
+ shaka.ui.ContextMenu.registerElement(
178
+ 'loop', new shaka.ui.LoopButton.Factory());
package/ui/mute_button.js CHANGED
@@ -8,7 +8,6 @@
8
8
  goog.provide('shaka.ui.MuteButton');
9
9
 
10
10
  goog.require('shaka.ads.AdManager');
11
- goog.require('shaka.ui.Constants');
12
11
  goog.require('shaka.ui.Controls');
13
12
  goog.require('shaka.ui.Element');
14
13
  goog.require('shaka.ui.Enums');
@@ -34,6 +33,7 @@ shaka.ui.MuteButton = class extends shaka.ui.Element {
34
33
  this.button_ = shaka.util.Dom.createButton();
35
34
  this.button_.classList.add('shaka-mute-button');
36
35
  this.button_.classList.add('material-icons-round');
36
+ this.button_.classList.add('shaka-tooltip');
37
37
  this.parent.appendChild(this.button_);
38
38
  this.updateAriaLabel_();
39
39
  this.updateIcon_();
@@ -49,7 +49,7 @@ shaka.ui.MuteButton = class extends shaka.ui.Element {
49
49
  });
50
50
 
51
51
  this.eventManager.listen(this.button_, 'click', () => {
52
- if (this.ad) {
52
+ if (this.ad && this.ad.isLinear()) {
53
53
  this.ad.setMuted(!this.ad.isMuted());
54
54
  } else {
55
55
  this.video.muted = !this.video.muted;
@@ -97,8 +97,7 @@ shaka.ui.MuteButton = class extends shaka.ui.Element {
97
97
  label = this.video.muted ? LocIds.UNMUTE : LocIds.MUTE;
98
98
  }
99
99
 
100
- this.button_.setAttribute(shaka.ui.Constants.ARIA_LABEL,
101
- this.localization.resolve(label));
100
+ this.button_.ariaLabel = this.localization.resolve(label);
102
101
  }
103
102
 
104
103
  /**
@@ -10,7 +10,6 @@ goog.provide('shaka.ui.OverflowMenu');
10
10
  goog.require('goog.asserts');
11
11
  goog.require('shaka.ads.AdManager');
12
12
  goog.require('shaka.log');
13
- goog.require('shaka.ui.Constants');
14
13
  goog.require('shaka.ui.Controls');
15
14
  goog.require('shaka.ui.Element');
16
15
  goog.require('shaka.ui.Enums');
@@ -49,29 +48,6 @@ shaka.ui.OverflowMenu = class extends shaka.ui.Element {
49
48
 
50
49
  this.createChildren_();
51
50
 
52
-
53
- const backToOverflowMenuButtons =
54
- this.controls.getVideoContainer().getElementsByClassName(
55
- 'shaka-back-to-overflow-button');
56
-
57
- for (const button of backToOverflowMenuButtons) {
58
- this.eventManager.listen(button, 'click', () => {
59
- // Hide the submenus, display the overflow menu
60
- this.controls.hideSettingsMenus();
61
- shaka.ui.Utils.setDisplay(this.overflowMenu_, true);
62
-
63
- // If there are back to overflow menu buttons, there must be
64
- // overflow menu buttons, but oh well
65
- if (this.overflowMenu_.childNodes.length) {
66
- /** @type {!HTMLElement} */ (this.overflowMenu_.childNodes[0])
67
- .focus();
68
- }
69
-
70
- // Make sure controls are displayed
71
- this.controls.computeOpacity();
72
- });
73
- }
74
-
75
51
  this.eventManager.listen(
76
52
  this.localization, shaka.ui.Localization.LOCALE_UPDATED, () => {
77
53
  this.updateAriaLabel_();
@@ -84,7 +60,9 @@ shaka.ui.OverflowMenu = class extends shaka.ui.Element {
84
60
 
85
61
  this.eventManager.listen(
86
62
  this.adManager, shaka.ads.AdManager.AD_STARTED, () => {
87
- shaka.ui.Utils.setDisplay(this.overflowMenuButton_, false);
63
+ if (this.ad && this.ad.isLinear()) {
64
+ shaka.ui.Utils.setDisplay(this.overflowMenuButton_, false);
65
+ }
88
66
  });
89
67
 
90
68
  this.eventManager.listen(
@@ -113,7 +91,7 @@ shaka.ui.OverflowMenu = class extends shaka.ui.Element {
113
91
 
114
92
  this.updateAriaLabel_();
115
93
 
116
- if (this.ad) {
94
+ if (this.ad && this.ad.isLinear()) {
117
95
  // There was already an ad.
118
96
  shaka.ui.Utils.setDisplay(this.overflowMenuButton_, false);
119
97
  }
@@ -164,6 +142,7 @@ shaka.ui.OverflowMenu = class extends shaka.ui.Element {
164
142
  this.overflowMenuButton_.classList.add('shaka-overflow-menu-button');
165
143
  this.overflowMenuButton_.classList.add('shaka-no-propagation');
166
144
  this.overflowMenuButton_.classList.add('material-icons-round');
145
+ this.overflowMenuButton_.classList.add('shaka-tooltip');
167
146
  this.overflowMenuButton_.textContent =
168
147
  shaka.ui.Enums.MaterialDesignIcons.OPEN_OVERFLOW;
169
148
  this.parent.appendChild(this.overflowMenuButton_);
@@ -217,8 +196,8 @@ shaka.ui.OverflowMenu = class extends shaka.ui.Element {
217
196
  */
218
197
  updateAriaLabel_() {
219
198
  const LocIds = shaka.ui.Locales.Ids;
220
- this.overflowMenuButton_.setAttribute(shaka.ui.Constants.ARIA_LABEL,
221
- this.localization.resolve(LocIds.MORE_SETTINGS));
199
+ this.overflowMenuButton_.ariaLabel =
200
+ this.localization.resolve(LocIds.MORE_SETTINGS);
222
201
  }
223
202
  };
224
203
 
package/ui/pip_button.js CHANGED
@@ -7,7 +7,7 @@
7
7
 
8
8
  goog.provide('shaka.ui.PipButton');
9
9
 
10
- goog.require('shaka.ui.Constants');
10
+ goog.require('shaka.ui.ContextMenu');
11
11
  goog.require('shaka.ui.Controls');
12
12
  goog.require('shaka.ui.Element');
13
13
  goog.require('shaka.ui.Enums');
@@ -40,6 +40,7 @@ shaka.ui.PipButton = class extends shaka.ui.Element {
40
40
  /** @private {!HTMLButtonElement} */
41
41
  this.pipButton_ = shaka.util.Dom.createButton();
42
42
  this.pipButton_.classList.add('shaka-pip-button');
43
+ this.pipButton_.classList.add('shaka-tooltip');
43
44
 
44
45
  /** @private {!HTMLElement} */
45
46
  this.pipIcon_ = shaka.util.Dom.createHTMLElement('i');
@@ -141,8 +142,8 @@ shaka.ui.PipButton = class extends shaka.ui.Element {
141
142
  onEnterPictureInPicture_() {
142
143
  const LocIds = shaka.ui.Locales.Ids;
143
144
  this.pipIcon_.textContent = shaka.ui.Enums.MaterialDesignIcons.EXIT_PIP;
144
- this.pipButton_.setAttribute(shaka.ui.Constants.ARIA_LABEL,
145
- this.localization.resolve(LocIds.EXIT_PICTURE_IN_PICTURE));
145
+ this.pipButton_.ariaLabel =
146
+ this.localization.resolve(LocIds.EXIT_PICTURE_IN_PICTURE);
146
147
  this.currentPipState_.textContent =
147
148
  this.localization.resolve(LocIds.ON);
148
149
  }
@@ -152,8 +153,8 @@ shaka.ui.PipButton = class extends shaka.ui.Element {
152
153
  onLeavePictureInPicture_() {
153
154
  const LocIds = shaka.ui.Locales.Ids;
154
155
  this.pipIcon_.textContent = shaka.ui.Enums.MaterialDesignIcons.PIP;
155
- this.pipButton_.setAttribute(shaka.ui.Constants.ARIA_LABEL,
156
- this.localization.resolve(LocIds.ENTER_PICTURE_IN_PICTURE));
156
+ this.pipButton_.ariaLabel =
157
+ this.localization.resolve(LocIds.ENTER_PICTURE_IN_PICTURE);
157
158
  this.currentPipState_.textContent =
158
159
  this.localization.resolve(LocIds.OFF);
159
160
  }
@@ -171,8 +172,7 @@ shaka.ui.PipButton = class extends shaka.ui.Element {
171
172
  const ariaLabel = document.pictureInPictureElement ?
172
173
  LocIds.EXIT_PICTURE_IN_PICTURE :
173
174
  LocIds.ENTER_PICTURE_IN_PICTURE;
174
- this.pipButton_.setAttribute(shaka.ui.Constants.ARIA_LABEL,
175
- this.localization.resolve(ariaLabel));
175
+ this.pipButton_.ariaLabel = this.localization.resolve(ariaLabel);
176
176
 
177
177
  const currentPipState = document.pictureInPictureElement ?
178
178
  LocIds.ON : LocIds.OFF;
@@ -239,3 +239,6 @@ shaka.ui.OverflowMenu.registerElement(
239
239
 
240
240
  shaka.ui.Controls.registerElement(
241
241
  'picture_in_picture', new shaka.ui.PipButton.Factory());
242
+
243
+ shaka.ui.ContextMenu.registerElement(
244
+ 'picture_in_picture', new shaka.ui.PipButton.Factory());
package/ui/play_button.js CHANGED
@@ -73,7 +73,7 @@ shaka.ui.PlayButton = class extends shaka.ui.Element {
73
73
  });
74
74
 
75
75
  this.eventManager.listen(this.button, 'click', () => {
76
- if (this.ad) {
76
+ if (this.ad && this.ad.isLinear()) {
77
77
  this.controls.playPauseAd();
78
78
  } else {
79
79
  this.controls.playPausePresentation();
@@ -92,7 +92,7 @@ shaka.ui.PlayButton = class extends shaka.ui.Element {
92
92
  * @protected
93
93
  */
94
94
  isPaused() {
95
- if (this.ad) {
95
+ if (this.ad && this.ad.isLinear()) {
96
96
  return this.ad.isPaused();
97
97
  }
98
98
 
@@ -7,7 +7,7 @@
7
7
 
8
8
  goog.provide('shaka.ui.PlaybackRateSelection');
9
9
 
10
- goog.require('shaka.ui.Constants');
10
+ goog.require('shaka.ui.Controls');
11
11
  goog.require('shaka.ui.Enums');
12
12
  goog.require('shaka.ui.Locales');
13
13
  goog.require('shaka.ui.Localization');
@@ -32,6 +32,7 @@ shaka.ui.PlaybackRateSelection = class extends shaka.ui.SettingsMenu {
32
32
 
33
33
  this.button.classList.add('shaka-playbackrate-button');
34
34
  this.menu.classList.add('shaka-playback-rates');
35
+ this.button.classList.add('shaka-tooltip-status');
35
36
 
36
37
  this.eventManager.listen(
37
38
  this.localization, shaka.ui.Localization.LOCALE_UPDATED, () => {
@@ -48,15 +49,8 @@ shaka.ui.PlaybackRateSelection = class extends shaka.ui.SettingsMenu {
48
49
  });
49
50
 
50
51
  /** @type {!Map.<string, number>} */
51
- this.playbackRates_ = new Map([
52
- ['0.5x', 0.5],
53
- ['0.75x', 0.75],
54
- ['1x', 1],
55
- ['1.25x', 1.25],
56
- ['1.5x', 1.5],
57
- ['1.75x', 1.75],
58
- ['2x', 2],
59
- ]);
52
+ this.playbackRates_ = new Map(this.controls.getConfig().playbackRates
53
+ .map((rate) => [rate + 'x', rate]));
60
54
 
61
55
  // Set up all the strings in the user's preferred language.
62
56
  this.updateLocalizedStrings_();
@@ -70,10 +64,8 @@ shaka.ui.PlaybackRateSelection = class extends shaka.ui.SettingsMenu {
70
64
  updateLocalizedStrings_() {
71
65
  const LocIds = shaka.ui.Locales.Ids;
72
66
 
73
- this.backButton.setAttribute(shaka.ui.Constants.ARIA_LABEL,
74
- this.localization.resolve(LocIds.BACK));
75
- this.button.setAttribute(shaka.ui.Constants.ARIA_LABEL,
76
- this.localization.resolve(LocIds.PLAYBACK_RATE));
67
+ this.backButton.ariaLabel = this.localization.resolve(LocIds.BACK);
68
+ this.button.ariaLabel = this.localization.resolve(LocIds.PLAYBACK_RATE);
77
69
  this.nameSpan.textContent = this.localization.resolve(LocIds.PLAYBACK_RATE);
78
70
  this.backSpan.textContent = this.localization.resolve(LocIds.PLAYBACK_RATE);
79
71
  }
@@ -105,13 +97,14 @@ shaka.ui.PlaybackRateSelection = class extends shaka.ui.SettingsMenu {
105
97
  if (span) {
106
98
  const button = span.parentElement;
107
99
  button.appendChild(shaka.ui.Utils.checkmarkIcon());
108
- button.setAttribute('aria-selected', 'true');
100
+ button.ariaSelected = 'true';
109
101
  span.classList.add('shaka-chosen-item');
110
102
  }
111
103
 
112
104
  // Set the label to display the current playback rate in the overflow menu,
113
105
  // in the format of '1x', '1.5x', etc.
114
106
  this.currentSelection.textContent = rate + 'x';
107
+ this.button.setAttribute('shaka-status', rate + 'x');
115
108
  }
116
109
 
117
110
  /** @private */
@@ -146,3 +139,6 @@ shaka.ui.PlaybackRateSelection.Factory = class {
146
139
 
147
140
  shaka.ui.OverflowMenu.registerElement(
148
141
  'playback_rate', new shaka.ui.PlaybackRateSelection.Factory());
142
+
143
+ shaka.ui.Controls.registerElement(
144
+ 'playback_rate', new shaka.ui.PlaybackRateSelection.Factory());
@@ -7,7 +7,6 @@
7
7
 
8
8
  goog.provide('shaka.ui.PresentationTimeTracker');
9
9
 
10
- goog.require('shaka.ui.Constants');
11
10
  goog.require('shaka.ui.Controls');
12
11
  goog.require('shaka.ui.Element');
13
12
  goog.require('shaka.ui.Locales');
@@ -108,8 +107,7 @@ shaka.ui.PresentationTimeTracker = class extends shaka.ui.Element {
108
107
  onTracksChanged_() {
109
108
  if (this.player.isLive()) {
110
109
  const ariaLabel = shaka.ui.Locales.Ids.SKIP_TO_LIVE;
111
- this.currentTime_.setAttribute(shaka.ui.Constants.ARIA_LABEL,
112
- this.localization.resolve(ariaLabel));
110
+ this.currentTime_.ariaLabel = this.localization.resolve(ariaLabel);
113
111
  }
114
112
  }
115
113
  };