shaka-player 3.2.1 → 3.3.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 (213) 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 +9 -5
  5. package/CHANGELOG.md +358 -0
  6. package/CONTRIBUTORS +7 -2
  7. package/build/conformance.textproto +183 -169
  8. package/build/generateExterns.js +1 -1
  9. package/build/types/core +3 -0
  10. package/build/types/offline +1 -0
  11. package/build/types/polyfill +1 -0
  12. package/build/types/ui +2 -0
  13. package/demo/common/assets.js +19 -1
  14. package/demo/common/message_ids.js +13 -1
  15. package/demo/config.js +31 -1
  16. package/demo/index.html +1 -1
  17. package/demo/locales/en.json +12 -0
  18. package/demo/locales/source.json +48 -0
  19. package/dist/controls.css +26 -2
  20. package/dist/controls.css.map +1 -1
  21. package/dist/demo.compiled.debug.js +20 -17
  22. package/dist/demo.compiled.debug.map +3 -3
  23. package/dist/demo.compiled.js +20 -17
  24. package/dist/demo.compiled.map +3 -3
  25. package/dist/deps.js +19 -12
  26. package/dist/locales.js +39 -37
  27. package/dist/receiver.compiled.debug.js +12 -10
  28. package/dist/receiver.compiled.debug.map +3 -3
  29. package/dist/receiver.compiled.js +12 -10
  30. package/dist/receiver.compiled.map +3 -3
  31. package/dist/shaka-player.compiled.d.ts +231 -18
  32. package/dist/shaka-player.compiled.debug.d.ts +231 -18
  33. package/dist/shaka-player.compiled.debug.externs.js +279 -8
  34. package/dist/shaka-player.compiled.debug.js +512 -449
  35. package/dist/shaka-player.compiled.debug.map +4 -4
  36. package/dist/shaka-player.compiled.externs.js +279 -8
  37. package/dist/shaka-player.compiled.js +854 -821
  38. package/dist/shaka-player.compiled.map +4 -4
  39. package/dist/shaka-player.ui.d.ts +247 -19
  40. package/dist/shaka-player.ui.debug.d.ts +247 -19
  41. package/dist/shaka-player.ui.debug.externs.js +307 -9
  42. package/dist/shaka-player.ui.debug.js +662 -580
  43. package/dist/shaka-player.ui.debug.map +4 -4
  44. package/dist/shaka-player.ui.externs.js +307 -9
  45. package/dist/shaka-player.ui.js +1047 -1000
  46. package/dist/shaka-player.ui.map +4 -4
  47. package/docs/design/bg-fetch-after.gv +29 -0
  48. package/docs/design/bg-fetch-after.gv.png +0 -0
  49. package/docs/design/bg-fetch-before.gv +18 -0
  50. package/docs/design/bg-fetch-before.gv.png +0 -0
  51. package/docs/design/bg-fetch.md +134 -0
  52. package/docs/tutorials/blob-url.md +15 -0
  53. package/docs/tutorials/fairplay.md +1 -1
  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/cmcd.js +186 -0
  58. package/externs/ima.js +3 -0
  59. package/externs/shaka/ads.js +5 -0
  60. package/externs/shaka/manifest.js +12 -1
  61. package/externs/shaka/manifest_parser.js +10 -1
  62. package/externs/shaka/net.js +20 -4
  63. package/externs/shaka/offline.js +31 -2
  64. package/externs/shaka/player.js +138 -5
  65. package/externs/shaka/text.js +24 -0
  66. package/externs/webcrypto.js +18 -0
  67. package/karma.conf.js +1 -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/client_side_ad.js +8 -0
  72. package/lib/ads/client_side_ad_manager.js +54 -90
  73. package/lib/ads/server_side_ad.js +7 -0
  74. package/lib/ads/server_side_ad_manager.js +7 -10
  75. package/lib/cast/cast_proxy.js +3 -2
  76. package/lib/cast/cast_receiver.js +2 -1
  77. package/lib/cast/cast_sender.js +2 -2
  78. package/lib/cast/cast_utils.js +1 -0
  79. package/lib/dash/dash_parser.js +141 -16
  80. package/lib/dash/segment_base.js +25 -1
  81. package/lib/dash/segment_list.js +19 -10
  82. package/lib/dash/segment_template.js +24 -11
  83. package/lib/hls/hls_parser.js +146 -40
  84. package/lib/media/drm_engine.js +7 -0
  85. package/lib/media/gap_jumping_controller.js +4 -2
  86. package/lib/media/media_source_engine.js +1 -2
  87. package/lib/media/quality_observer.js +291 -0
  88. package/lib/media/segment_index.js +8 -1
  89. package/lib/media/segment_reference.js +37 -4
  90. package/lib/media/streaming_engine.js +49 -7
  91. package/lib/net/http_fetch_plugin.js +31 -11
  92. package/lib/net/http_plugin_utils.js +1 -0
  93. package/lib/net/http_xhr_plugin.js +40 -14
  94. package/lib/net/networking_engine.js +83 -19
  95. package/lib/offline/download_info.js +68 -0
  96. package/lib/offline/download_manager.js +13 -5
  97. package/lib/offline/indexeddb/base_storage_cell.js +35 -0
  98. package/lib/offline/indexeddb/storage_mechanism.js +1 -1
  99. package/lib/offline/indexeddb/v5_storage_cell.js +5 -0
  100. package/lib/offline/storage.js +393 -284
  101. package/lib/offline/stored_content_utils.js +2 -0
  102. package/lib/player.js +249 -43
  103. package/lib/polyfill/media_capabilities.js +36 -15
  104. package/lib/polyfill/mediasource.js +6 -0
  105. package/lib/polyfill/orientation.js +1 -1
  106. package/lib/polyfill/patchedmediakeys_apple.js +4 -4
  107. package/lib/polyfill/patchedmediakeys_ms.js +4 -4
  108. package/lib/polyfill/patchedmediakeys_webkit.js +4 -4
  109. package/lib/polyfill/random_uuid.js +52 -0
  110. package/lib/text/cue.js +18 -0
  111. package/lib/text/mp4_ttml_parser.js +3 -0
  112. package/lib/text/text_engine.js +14 -2
  113. package/lib/text/ttml_text_parser.js +114 -60
  114. package/lib/text/ui_text_displayer.js +95 -41
  115. package/lib/util/cmcd_manager.js +672 -0
  116. package/lib/util/error.js +6 -0
  117. package/lib/util/fake_event.js +53 -7
  118. package/lib/util/language_utils.js +12 -0
  119. package/lib/util/mutex.js +52 -0
  120. package/lib/util/periods.js +102 -65
  121. package/lib/util/platform.js +13 -1
  122. package/lib/util/player_configuration.js +18 -0
  123. package/lib/util/stream_utils.js +99 -10
  124. package/lib/util/xml_utils.js +19 -0
  125. package/package.json +2 -2
  126. package/shaka-player.uncompiled.js +3 -0
  127. package/test/cast/cast_proxy_unit.js +12 -6
  128. package/test/cast/cast_utils_unit.js +1 -1
  129. package/test/dash/dash_parser_content_protection_unit.js +2 -0
  130. package/test/dash/dash_parser_live_unit.js +101 -1
  131. package/test/dash/dash_parser_manifest_unit.js +222 -2
  132. package/test/dash/dash_parser_segment_base_unit.js +2 -0
  133. package/test/dash/dash_parser_segment_list_unit.js +2 -1
  134. package/test/dash/dash_parser_segment_template_unit.js +2 -1
  135. package/test/hls/hls_live_unit.js +2 -0
  136. package/test/hls/hls_parser_unit.js +7 -1
  137. package/test/media/closed_caption_parser_unit.js +6 -1
  138. package/test/media/drm_engine_unit.js +47 -3
  139. package/test/media/quality_observer_unit.js +139 -0
  140. package/test/media/segment_reference_unit.js +16 -1
  141. package/test/media/streaming_engine_integration.js +4 -2
  142. package/test/media/streaming_engine_unit.js +147 -0
  143. package/test/net/http_plugin_unit.js +20 -15
  144. package/test/offline/storage_integration.js +108 -4
  145. package/test/player_integration.js +178 -8
  146. package/test/player_src_equals_integration.js +41 -8
  147. package/test/player_unit.js +19 -9
  148. package/test/test/assets/3675/chunk-stream0-00001.m4s +0 -0
  149. package/test/test/assets/3675/chunk-stream0-00002.m4s +0 -0
  150. package/test/test/assets/3675/chunk-stream0-00003.m4s +0 -0
  151. package/test/test/assets/3675/chunk-stream0-00004.m4s +0 -0
  152. package/test/test/assets/3675/chunk-stream0-00005.m4s +0 -0
  153. package/test/test/assets/3675/chunk-stream0-00006.m4s +0 -0
  154. package/test/test/assets/3675/chunk-stream0-00007.m4s +0 -0
  155. package/test/test/assets/3675/dash_0.mpd +30 -0
  156. package/test/test/assets/3675/dash_1.mpd +30 -0
  157. package/test/test/assets/3675/dash_2.mpd +30 -0
  158. package/test/test/assets/3675/dash_3.mpd +30 -0
  159. package/test/test/assets/3675/dash_4.mpd +30 -0
  160. package/test/test/assets/3675/dash_5.mpd +26 -0
  161. package/test/test/assets/3675/init-stream0.m4s +0 -0
  162. package/test/test/assets/chapters.vtt +2 -2
  163. package/test/test/assets/chapters2.vtt +10 -0
  164. package/test/test/util/dash_parser_util.js +4 -0
  165. package/test/test/util/fake_ad.js +7 -0
  166. package/test/test/util/fake_ad_manager.js +1 -1
  167. package/test/test/util/fake_drm_engine.js +9 -2
  168. package/test/test/util/manifest_generator.js +3 -2
  169. package/test/test/util/test_scheme.js +14 -1
  170. package/test/test/util/ttml_utils.js +81 -0
  171. package/test/text/mp4_ttml_parser_unit.js +11 -18
  172. package/test/text/ttml_text_parser_unit.js +552 -227
  173. package/test/text/ui_text_displayer_unit.js +29 -17
  174. package/test/ui/localization_unit.js +15 -14
  175. package/test/ui/text_displayer_layout_unit.js +13 -1
  176. package/test/ui/ui_unit.js +250 -0
  177. package/test/util/cmcd_manager_unit.js +291 -0
  178. package/test/util/stream_utils_unit.js +45 -4
  179. package/third_party/closure-uri/uri.js +21 -0
  180. package/ui/airplay_button.js +1 -0
  181. package/ui/audio_language_selection.js +7 -0
  182. package/ui/cast_button.js +3 -3
  183. package/ui/context_menu.js +109 -0
  184. package/ui/controls.js +45 -13
  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 +14 -5
  189. package/ui/fullscreen_button.js +1 -0
  190. package/ui/less/buttons.less +0 -4
  191. package/ui/less/containers.less +77 -7
  192. package/ui/less/overflow_menu.less +0 -10
  193. package/ui/less/tooltip.less +97 -0
  194. package/ui/locales/en.json +1 -0
  195. package/ui/locales/ru.json +6 -6
  196. package/ui/locales/source.json +4 -0
  197. package/ui/localization.js +28 -51
  198. package/ui/loop_button.js +5 -0
  199. package/ui/mute_button.js +2 -1
  200. package/ui/overflow_menu.js +5 -25
  201. package/ui/pip_button.js +7 -3
  202. package/ui/play_button.js +2 -2
  203. package/ui/playback_rate_selection.js +8 -9
  204. package/ui/resolution_selection.js +7 -0
  205. package/ui/rewind_button.js +15 -6
  206. package/ui/seek_bar.js +4 -2
  207. package/ui/settings_menu.js +36 -4
  208. package/ui/small_play_button.js +1 -0
  209. package/ui/statistics_button.js +253 -0
  210. package/ui/text_selection.js +12 -4
  211. package/ui/ui.js +30 -0
  212. package/ui/volume_bar.js +1 -1
  213. package/externs/media_capabilities.js +0 -16
@@ -130,28 +130,20 @@ shaka.ui.Localization = class {
130
130
  (locale) => !this.localizations_.has(locale));
131
131
 
132
132
  if (missing.length) {
133
- /** @type {shaka.ui.Localization.UnknownLocalesEvent} */
134
- const eMissing = {
135
- 'locales': missing,
136
- };
137
-
138
133
  this.events_.dispatchEvent(new shaka.util.FakeEvent(
139
134
  Class.UNKNOWN_LOCALES,
140
- eMissing));
135
+ (new Map()).set('locales', missing)));
141
136
  }
142
137
 
143
138
  const found = shaka.util.Iterables.filter(
144
139
  this.currentLocales_,
145
140
  (locale) => this.localizations_.has(locale));
146
141
 
147
- /** @type {shaka.ui.Localization.LocaleChangedEvent} */
148
- const eFound = {
149
- 'locales': found.length ? found : [this.fallbackLocale_],
150
- };
151
-
142
+ const data = (new Map()).set(
143
+ 'locales', found.length ? found : [this.fallbackLocale_]);
152
144
  this.events_.dispatchEvent(new shaka.util.FakeEvent(
153
145
  Class.LOCALE_CHANGED,
154
- eFound));
146
+ data));
155
147
  }
156
148
 
157
149
  /**
@@ -253,14 +245,11 @@ shaka.ui.Localization = class {
253
245
  // number of locales. Since we don't know which ones we actually checked,
254
246
  // just tell them the preferred locale.
255
247
 
256
- /** @type {shaka.ui.Localization.UnknownLocalizationEvent} */
257
- const e = {
258
- // Make a copy to avoid leaking references.
259
- 'locales': Array.from(this.currentLocales_),
260
- 'missing': id,
261
- };
262
-
263
- this.events_.dispatchEvent(new FakeEvent(Class.UNKNOWN_LOCALIZATION, e));
248
+ const data = new Map()
249
+ // Make a copy to avoid leaking references.
250
+ .set('locales', Array.from(this.currentLocales_))
251
+ .set('missing', id);
252
+ this.events_.dispatchEvent(new FakeEvent(Class.UNKNOWN_LOCALIZATION, data));
264
253
 
265
254
  return '';
266
255
  }
@@ -381,18 +370,16 @@ shaka.ui.Localization = class {
381
370
  }
382
371
 
383
372
  if (missing.size > 0) {
384
- /** @type {shaka.ui.Localization.MissingLocalizationsEvent} */
385
- const e = {
386
- // Make a copy of the preferred locales to avoid leaking references.
387
- 'locales': Array.from(preferredLocales),
388
- // Because most people like arrays more than sets, convert the set to
389
- // an array.
390
- 'missing': Array.from(missing),
391
- };
373
+ const data = new Map()
374
+ // Make a copy of the preferred locales to avoid leaking references.
375
+ .set('locales', Array.from(preferredLocales))
376
+ // Because more people like arrays more than sets, convert the set to
377
+ // an array.
378
+ .set('missing', Array.from(missing));
392
379
 
393
380
  this.events_.dispatchEvent(new shaka.util.FakeEvent(
394
381
  shaka.ui.Localization.MISSING_LOCALIZATIONS,
395
- e));
382
+ data));
396
383
  }
397
384
  }
398
385
 
@@ -478,52 +465,42 @@ shaka.ui.Localization.LOCALE_CHANGED = 'locale-changed';
478
465
  shaka.ui.Localization.LOCALE_UPDATED = 'locale-updated';
479
466
 
480
467
  /**
481
- * @typedef {{
482
- * 'locales': !Array.<string>
483
- * }}
484
- *
468
+ * @event shaka.ui.Localization.UnknownLocalesEvent
469
+ * @property {string} type
470
+ * 'unknown-locales'
485
471
  * @property {!Array.<string>} locales
486
472
  * The locales that the user wanted but could not be found.
487
473
  * @exportDoc
488
474
  */
489
- shaka.ui.Localization.UnknownLocalesEvent;
490
475
 
491
476
  /**
492
- * @typedef {{
493
- * 'locales': !Array.<string>,
494
- * 'missing': string
495
- * }}
496
- *
477
+ * @event shaka.ui.Localization.MissingLocalizationsEvent
478
+ * @property {string} type
479
+ * 'unknown-localization'
497
480
  * @property {!Array.<string>} locales
498
481
  * The locales that the user wanted.
499
482
  * @property {string} missing
500
483
  * The id of the unknown entry.
501
484
  * @exportDoc
502
485
  */
503
- shaka.ui.Localization.UnknownLocalizationEvent;
504
486
 
505
487
  /**
506
- * @typedef {{
507
- * 'locales': !Array.<string>,
508
- * 'missing': !Array.<string>
509
- * }}
510
- *
488
+ * @event shaka.ui.Localization.MissingLocalizationsEvent
489
+ * @property {string} type
490
+ * 'missing-localizations'
511
491
  * @property {string} locale
512
492
  * The locale that the user wanted.
513
493
  * @property {!Array.<string>} missing
514
494
  * The ids of the missing entries.
515
495
  * @exportDoc
516
496
  */
517
- shaka.ui.Localization.MissingLocalizationsEvent;
518
497
 
519
498
  /**
520
- * @typedef {{
521
- * 'locales': !Array.<string>
522
- * }}
523
- *
499
+ * @event shaka.ui.Localization.LocaleChangedEvent
500
+ * @property {string} type
501
+ * 'locale-changed'
524
502
  * @property {!Array.<string>} locales
525
503
  * The new set of locales that user wanted,
526
504
  * and that were successfully found.
527
505
  * @exportDoc
528
506
  */
529
- shaka.ui.Localization.LocaleChangedEvent;
package/ui/loop_button.js CHANGED
@@ -7,6 +7,7 @@
7
7
 
8
8
  goog.provide('shaka.ui.LoopButton');
9
9
 
10
+ goog.require('shaka.ui.ContextMenu');
10
11
  goog.require('shaka.ui.Controls');
11
12
  goog.require('shaka.ui.Element');
12
13
  goog.require('shaka.ui.Enums');
@@ -35,6 +36,7 @@ shaka.ui.LoopButton = class extends shaka.ui.Element {
35
36
  /** @private {!HTMLButtonElement} */
36
37
  this.button_ = shaka.util.Dom.createButton();
37
38
  this.button_.classList.add('shaka-loop-button');
39
+ this.button_.classList.add('shaka-tooltip');
38
40
 
39
41
  /** @private {!HTMLElement} */
40
42
  this.icon_ = shaka.util.Dom.createHTMLElement('i');
@@ -171,3 +173,6 @@ shaka.ui.OverflowMenu.registerElement(
171
173
 
172
174
  shaka.ui.Controls.registerElement(
173
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
@@ -33,6 +33,7 @@ shaka.ui.MuteButton = class extends shaka.ui.Element {
33
33
  this.button_ = shaka.util.Dom.createButton();
34
34
  this.button_.classList.add('shaka-mute-button');
35
35
  this.button_.classList.add('material-icons-round');
36
+ this.button_.classList.add('shaka-tooltip');
36
37
  this.parent.appendChild(this.button_);
37
38
  this.updateAriaLabel_();
38
39
  this.updateIcon_();
@@ -48,7 +49,7 @@ shaka.ui.MuteButton = class extends shaka.ui.Element {
48
49
  });
49
50
 
50
51
  this.eventManager.listen(this.button_, 'click', () => {
51
- if (this.ad) {
52
+ if (this.ad && this.ad.isLinear()) {
52
53
  this.ad.setMuted(!this.ad.isMuted());
53
54
  } else {
54
55
  this.video.muted = !this.video.muted;
@@ -48,29 +48,6 @@ shaka.ui.OverflowMenu = class extends shaka.ui.Element {
48
48
 
49
49
  this.createChildren_();
50
50
 
51
-
52
- const backToOverflowMenuButtons =
53
- this.controls.getVideoContainer().getElementsByClassName(
54
- 'shaka-back-to-overflow-button');
55
-
56
- for (const button of backToOverflowMenuButtons) {
57
- this.eventManager.listen(button, 'click', () => {
58
- // Hide the submenus, display the overflow menu
59
- this.controls.hideSettingsMenus();
60
- shaka.ui.Utils.setDisplay(this.overflowMenu_, true);
61
-
62
- // If there are back to overflow menu buttons, there must be
63
- // overflow menu buttons, but oh well
64
- if (this.overflowMenu_.childNodes.length) {
65
- /** @type {!HTMLElement} */ (this.overflowMenu_.childNodes[0])
66
- .focus();
67
- }
68
-
69
- // Make sure controls are displayed
70
- this.controls.computeOpacity();
71
- });
72
- }
73
-
74
51
  this.eventManager.listen(
75
52
  this.localization, shaka.ui.Localization.LOCALE_UPDATED, () => {
76
53
  this.updateAriaLabel_();
@@ -83,7 +60,9 @@ shaka.ui.OverflowMenu = class extends shaka.ui.Element {
83
60
 
84
61
  this.eventManager.listen(
85
62
  this.adManager, shaka.ads.AdManager.AD_STARTED, () => {
86
- shaka.ui.Utils.setDisplay(this.overflowMenuButton_, false);
63
+ if (this.ad && this.ad.isLinear()) {
64
+ shaka.ui.Utils.setDisplay(this.overflowMenuButton_, false);
65
+ }
87
66
  });
88
67
 
89
68
  this.eventManager.listen(
@@ -112,7 +91,7 @@ shaka.ui.OverflowMenu = class extends shaka.ui.Element {
112
91
 
113
92
  this.updateAriaLabel_();
114
93
 
115
- if (this.ad) {
94
+ if (this.ad && this.ad.isLinear()) {
116
95
  // There was already an ad.
117
96
  shaka.ui.Utils.setDisplay(this.overflowMenuButton_, false);
118
97
  }
@@ -163,6 +142,7 @@ shaka.ui.OverflowMenu = class extends shaka.ui.Element {
163
142
  this.overflowMenuButton_.classList.add('shaka-overflow-menu-button');
164
143
  this.overflowMenuButton_.classList.add('shaka-no-propagation');
165
144
  this.overflowMenuButton_.classList.add('material-icons-round');
145
+ this.overflowMenuButton_.classList.add('shaka-tooltip');
166
146
  this.overflowMenuButton_.textContent =
167
147
  shaka.ui.Enums.MaterialDesignIcons.OPEN_OVERFLOW;
168
148
  this.parent.appendChild(this.overflowMenuButton_);
package/ui/pip_button.js CHANGED
@@ -7,6 +7,7 @@
7
7
 
8
8
  goog.provide('shaka.ui.PipButton');
9
9
 
10
+ goog.require('shaka.ui.ContextMenu');
10
11
  goog.require('shaka.ui.Controls');
11
12
  goog.require('shaka.ui.Element');
12
13
  goog.require('shaka.ui.Enums');
@@ -39,6 +40,7 @@ shaka.ui.PipButton = class extends shaka.ui.Element {
39
40
  /** @private {!HTMLButtonElement} */
40
41
  this.pipButton_ = shaka.util.Dom.createButton();
41
42
  this.pipButton_.classList.add('shaka-pip-button');
43
+ this.pipButton_.classList.add('shaka-tooltip');
42
44
 
43
45
  /** @private {!HTMLElement} */
44
46
  this.pipIcon_ = shaka.util.Dom.createHTMLElement('i');
@@ -130,9 +132,8 @@ shaka.ui.PipButton = class extends shaka.ui.Element {
130
132
  await document.exitPictureInPicture();
131
133
  }
132
134
  } catch (error) {
133
- this.controls.dispatchEvent(new shaka.util.FakeEvent('error', {
134
- detail: error,
135
- }));
135
+ this.controls.dispatchEvent(new shaka.util.FakeEvent(
136
+ 'error', (new Map()).set('detail', error)));
136
137
  }
137
138
  }
138
139
 
@@ -238,3 +239,6 @@ shaka.ui.OverflowMenu.registerElement(
238
239
 
239
240
  shaka.ui.Controls.registerElement(
240
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,6 +7,7 @@
7
7
 
8
8
  goog.provide('shaka.ui.PlaybackRateSelection');
9
9
 
10
+ goog.require('shaka.ui.Controls');
10
11
  goog.require('shaka.ui.Enums');
11
12
  goog.require('shaka.ui.Locales');
12
13
  goog.require('shaka.ui.Localization');
@@ -31,6 +32,7 @@ shaka.ui.PlaybackRateSelection = class extends shaka.ui.SettingsMenu {
31
32
 
32
33
  this.button.classList.add('shaka-playbackrate-button');
33
34
  this.menu.classList.add('shaka-playback-rates');
35
+ this.button.classList.add('shaka-tooltip-status');
34
36
 
35
37
  this.eventManager.listen(
36
38
  this.localization, shaka.ui.Localization.LOCALE_UPDATED, () => {
@@ -47,15 +49,8 @@ shaka.ui.PlaybackRateSelection = class extends shaka.ui.SettingsMenu {
47
49
  });
48
50
 
49
51
  /** @type {!Map.<string, number>} */
50
- this.playbackRates_ = new Map([
51
- ['0.5x', 0.5],
52
- ['0.75x', 0.75],
53
- ['1x', 1],
54
- ['1.25x', 1.25],
55
- ['1.5x', 1.5],
56
- ['1.75x', 1.75],
57
- ['2x', 2],
58
- ]);
52
+ this.playbackRates_ = new Map(this.controls.getConfig().playbackRates
53
+ .map((rate) => [rate + 'x', rate]));
59
54
 
60
55
  // Set up all the strings in the user's preferred language.
61
56
  this.updateLocalizedStrings_();
@@ -109,6 +104,7 @@ shaka.ui.PlaybackRateSelection = class extends shaka.ui.SettingsMenu {
109
104
  // Set the label to display the current playback rate in the overflow menu,
110
105
  // in the format of '1x', '1.5x', etc.
111
106
  this.currentSelection.textContent = rate + 'x';
107
+ this.button.setAttribute('shaka-status', rate + 'x');
112
108
  }
113
109
 
114
110
  /** @private */
@@ -143,3 +139,6 @@ shaka.ui.PlaybackRateSelection.Factory = class {
143
139
 
144
140
  shaka.ui.OverflowMenu.registerElement(
145
141
  'playback_rate', new shaka.ui.PlaybackRateSelection.Factory());
142
+
143
+ shaka.ui.Controls.registerElement(
144
+ 'playback_rate', new shaka.ui.PlaybackRateSelection.Factory());
@@ -8,6 +8,7 @@
8
8
  goog.provide('shaka.ui.ResolutionSelection');
9
9
 
10
10
  goog.require('goog.asserts');
11
+ goog.require('shaka.ui.Controls');
11
12
  goog.require('shaka.ui.Enums');
12
13
  goog.require('shaka.ui.Locales');
13
14
  goog.require('shaka.ui.Localization');
@@ -33,6 +34,7 @@ shaka.ui.ResolutionSelection = class extends shaka.ui.SettingsMenu {
33
34
  super(parent, controls, shaka.ui.Enums.MaterialDesignIcons.RESOLUTION);
34
35
 
35
36
  this.button.classList.add('shaka-resolution-button');
37
+ this.button.classList.add('shaka-tooltip-status');
36
38
  this.menu.classList.add('shaka-resolutions');
37
39
 
38
40
  this.eventManager.listen(
@@ -171,6 +173,8 @@ shaka.ui.ResolutionSelection = class extends shaka.ui.SettingsMenu {
171
173
  this.localization.resolve(shaka.ui.Locales.Ids.AUTO_QUALITY);
172
174
  }
173
175
 
176
+ this.button.setAttribute('shaka-status', this.currentSelection.textContent);
177
+
174
178
  this.menu.appendChild(autoButton);
175
179
  shaka.ui.Utils.focusOnTheChosenItem(this.menu);
176
180
  this.controls.dispatchEvent(
@@ -227,3 +231,6 @@ shaka.ui.ResolutionSelection.Factory = class {
227
231
 
228
232
  shaka.ui.OverflowMenu.registerElement(
229
233
  'quality', new shaka.ui.ResolutionSelection.Factory());
234
+
235
+ shaka.ui.Controls.registerElement(
236
+ 'quality', new shaka.ui.ResolutionSelection.Factory());
@@ -32,11 +32,17 @@ shaka.ui.RewindButton = class extends shaka.ui.Element {
32
32
  this.button_ = shaka.util.Dom.createButton();
33
33
  this.button_.classList.add('material-icons-round');
34
34
  this.button_.classList.add('shaka-rewind-button');
35
+ this.button_.classList.add('shaka-tooltip-status');
36
+ this.button_.setAttribute('shaka-status',
37
+ this.localization.resolve(shaka.ui.Locales.Ids.OFF));
35
38
  this.button_.textContent =
36
39
  shaka.ui.Enums.MaterialDesignIcons.REWIND;
37
40
  this.parent.appendChild(this.button_);
38
41
  this.updateAriaLabel_();
39
42
 
43
+ /** @private {!Array.<number>} */
44
+ this.rewindRates_ = this.controls.getConfig().rewindRates;
45
+
40
46
  this.eventManager.listen(
41
47
  this.localization, shaka.ui.Localization.LOCALE_UPDATED, () => {
42
48
  this.updateAriaLabel_();
@@ -61,7 +67,7 @@ shaka.ui.RewindButton = class extends shaka.ui.Element {
61
67
  }
62
68
 
63
69
  /**
64
- * Cycles trick play rate between -1, -2, -4, and -8.
70
+ * Cycles trick play rate between the selected rewind rates.
65
71
  * @private
66
72
  */
67
73
  rewind_() {
@@ -70,12 +76,15 @@ shaka.ui.RewindButton = class extends shaka.ui.Element {
70
76
  }
71
77
 
72
78
  const trickPlayRate = this.player.getPlaybackRate();
73
- // Every time the button is clicked, the rate is multiplied by 2,
74
- // unless the rate is at it's slowest (-8), in which case it is
75
- // dropped back to 1.
76
- const newRate = (trickPlayRate > 0 || trickPlayRate < -4) ?
77
- -1 : trickPlayRate * 2;
79
+ const newRateIndex = this.rewindRates_.indexOf(trickPlayRate) + 1;
80
+
81
+ // When the button is clicked, the next rate in this.rewindRates_ is
82
+ // selected. If no more rates are available, the first one is set.
83
+ const newRate = (newRateIndex != this.rewindRates_.length) ?
84
+ this.rewindRates_[newRateIndex] : this.rewindRates_[0];
78
85
  this.player.trickPlay(newRate);
86
+
87
+ this.button_.setAttribute('shaka-status', newRate + 'x');
79
88
  }
80
89
  };
81
90
 
package/ui/seek_bar.js CHANGED
@@ -95,7 +95,9 @@ shaka.ui.SeekBar = class extends shaka.ui.RangeElement {
95
95
 
96
96
  this.eventManager.listen(
97
97
  this.adManager, shaka.ads.AdManager.AD_STARTED, () => {
98
- shaka.ui.Utils.setDisplay(this.container, false);
98
+ if (!this.shouldBeDisplayed_()) {
99
+ shaka.ui.Utils.setDisplay(this.container, false);
100
+ }
99
101
  });
100
102
 
101
103
  this.eventManager.listen(
@@ -366,7 +368,7 @@ shaka.ui.SeekBar = class extends shaka.ui.RangeElement {
366
368
  return false;
367
369
  }
368
370
 
369
- return this.ad == null;
371
+ return this.ad == null || !this.ad.isLinear();
370
372
  }
371
373
 
372
374
  /** @private */
@@ -33,6 +33,8 @@ shaka.ui.SettingsMenu = class extends shaka.ui.Element {
33
33
 
34
34
  this.addMenu_();
35
35
 
36
+ this.inOverflowMenu_();
37
+
36
38
  this.eventManager.listen(this.button, 'click', () => {
37
39
  this.onButtonClick_();
38
40
  });
@@ -46,6 +48,7 @@ shaka.ui.SettingsMenu = class extends shaka.ui.Element {
46
48
  addButton_(iconText) {
47
49
  /** @protected {!HTMLButtonElement} */
48
50
  this.button = shaka.util.Dom.createButton();
51
+ this.button.classList.add('shaka-overflow-button');
49
52
 
50
53
  /** @protected {!HTMLElement}*/
51
54
  this.icon = shaka.util.Dom.createHTMLElement('i');
@@ -55,6 +58,7 @@ shaka.ui.SettingsMenu = class extends shaka.ui.Element {
55
58
 
56
59
  const label = shaka.util.Dom.createHTMLElement('label');
57
60
  label.classList.add('shaka-overflow-button-label');
61
+ label.classList.add('shaka-overflow-menu-only');
58
62
 
59
63
  /** @protected {!HTMLElement}*/
60
64
  this.nameSpan = shaka.util.Dom.createHTMLElement('span');
@@ -83,10 +87,13 @@ shaka.ui.SettingsMenu = class extends shaka.ui.Element {
83
87
  this.backButton = shaka.util.Dom.createButton();
84
88
  this.backButton.classList.add('shaka-back-to-overflow-button');
85
89
  this.menu.appendChild(this.backButton);
90
+ this.eventManager.listen(this.backButton, 'click', () => {
91
+ this.controls.hideSettingsMenus();
92
+ });
86
93
 
87
94
  const backIcon = shaka.util.Dom.createHTMLElement('i');
88
95
  backIcon.classList.add('material-icons-round');
89
- backIcon.textContent = shaka.ui.Enums.MaterialDesignIcons.BACK;
96
+ backIcon.textContent = shaka.ui.Enums.MaterialDesignIcons.CLOSE;
90
97
  this.backButton.appendChild(backIcon);
91
98
 
92
99
  /** @protected {!HTMLElement}*/
@@ -97,11 +104,36 @@ shaka.ui.SettingsMenu = class extends shaka.ui.Element {
97
104
  controlsContainer.appendChild(this.menu);
98
105
  }
99
106
 
107
+ /** @private */
108
+ inOverflowMenu_() {
109
+ // Initially, submenus are created with a "Close" option. When present
110
+ // inside of the overflow menu, that option must be replaced with a
111
+ // "Back" arrow that returns the user to the main menu.
112
+ if (this.parent.classList.contains('shaka-overflow-menu')) {
113
+ this.backButton.firstChild.textContent =
114
+ shaka.ui.Enums.MaterialDesignIcons.BACK;
115
+
116
+ this.eventManager.listen(this.backButton, 'click', () => {
117
+ shaka.ui.Utils.setDisplay(this.parent, true);
118
+
119
+ /** @type {!HTMLElement} */
120
+ (this.parent.childNodes[0]).focus();
121
+
122
+ // Make sure controls are displayed
123
+ this.controls.computeOpacity();
124
+ });
125
+ }
126
+ }
127
+
100
128
 
101
129
  /** @private */
102
130
  onButtonClick_() {
103
- this.controls.dispatchEvent(new shaka.util.FakeEvent('submenuopen'));
104
- shaka.ui.Utils.setDisplay(this.menu, true);
105
- shaka.ui.Utils.focusOnTheChosenItem(this.menu);
131
+ if (this.menu.classList.contains('shaka-hidden')) {
132
+ this.controls.dispatchEvent(new shaka.util.FakeEvent('submenuopen'));
133
+ shaka.ui.Utils.setDisplay(this.menu, true);
134
+ shaka.ui.Utils.focusOnTheChosenItem(this.menu);
135
+ } else {
136
+ shaka.ui.Utils.setDisplay(this.menu, false);
137
+ }
106
138
  }
107
139
  };
@@ -28,6 +28,7 @@ shaka.ui.SmallPlayButton = class extends shaka.ui.PlayButton {
28
28
 
29
29
  this.button.classList.add('shaka-small-play-button');
30
30
  this.button.classList.add('material-icons-round');
31
+ this.button.classList.add('shaka-tooltip');
31
32
 
32
33
  this.updateIcon();
33
34
  this.updateAriaLabel();