shaka-player 2.5.1 → 2.5.5
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.
- package/.csslintrc +13 -0
- package/AUTHORS +3 -0
- package/CHANGELOG.md +156 -0
- package/CONTRIBUTORS +3 -0
- package/README.md +3 -0
- package/build/README.md +5 -5
- package/build/apps.py +3 -1
- package/build/build.py +5 -2
- package/build/check.py +17 -0
- package/build/compiler.py +49 -0
- package/build/conformance.textproto +1 -0
- package/build/docs.py +0 -6
- package/build/generateExterns.js +72 -20
- package/build/install-linux-prereqs.sh +4 -4
- package/build/shakaBuildHelpers.py +7 -8
- package/build/test.py +21 -9
- package/build/types/core +1 -0
- package/build/types/ui +6 -1
- package/demo/asset_card.js +129 -41
- package/demo/cast_receiver/receiver_app.css +27 -13
- package/demo/close_button.js +10 -15
- package/demo/common/asset.js +6 -6
- package/demo/common/assets.js +72 -14
- package/demo/config.js +28 -25
- package/demo/custom.js +20 -16
- package/demo/demo.less +107 -16
- package/demo/demo_uncompiled.js +33 -0
- package/demo/demo_utils.js +4 -3
- package/demo/front.js +12 -8
- package/demo/index.html +14 -17
- package/demo/input.js +30 -23
- package/demo/input_container.js +15 -11
- package/demo/load.js +5 -7
- package/demo/main.js +138 -49
- package/demo/search.js +40 -36
- package/demo/service_worker.js +1 -1
- package/demo/tooltip.js +16 -24
- package/dist/.csslintstamp +0 -0
- package/dist/controls.css +1 -1
- package/dist/controls.css.map +1 -1
- package/dist/demo.compiled.debug.js +165 -152
- package/dist/demo.compiled.debug.map +4 -4
- package/dist/demo.compiled.js +165 -152
- package/dist/demo.compiled.map +4 -4
- package/dist/demo.css +1 -1
- package/dist/demo.css.map +1 -1
- package/dist/deps.js +28 -11
- package/dist/receiver.compiled.debug.js +11 -11
- package/dist/receiver.compiled.debug.map +3 -3
- package/dist/receiver.compiled.js +11 -11
- package/dist/receiver.compiled.map +3 -3
- package/dist/shaka-player.compiled.debug.externs.js +232 -102
- package/dist/shaka-player.compiled.debug.js +189 -165
- package/dist/shaka-player.compiled.debug.map +4 -4
- package/dist/shaka-player.compiled.externs.js +232 -102
- package/dist/shaka-player.compiled.js +567 -553
- package/dist/shaka-player.compiled.map +4 -4
- package/dist/shaka-player.ui.debug.externs.js +338 -113
- package/dist/shaka-player.ui.debug.js +296 -276
- package/dist/shaka-player.ui.debug.map +4 -4
- package/dist/shaka-player.ui.externs.js +338 -113
- package/dist/shaka-player.ui.js +685 -671
- package/dist/shaka-player.ui.map +4 -4
- package/docs/tutorials/drm-config.md +1 -0
- package/docs/tutorials/fairplay.md +77 -0
- package/docs/tutorials/index.json +1 -0
- package/docs/tutorials/manifest-parser.md +1 -1
- package/docs/tutorials/ui-customization.md +5 -2
- package/docs/tutorials/ui.md +10 -4
- package/docs/tutorials/welcome.md +2 -2
- package/externs/mediasession.js +16 -1
- package/externs/shaka/net.js +14 -4
- package/externs/shaka/player.js +136 -90
- package/externs/tippy.js +30 -0
- package/externs/webkitmediakeys.js +4 -0
- package/karma.conf.js +30 -24
- package/lib/cast/cast_proxy.js +94 -23
- package/lib/cast/cast_receiver.js +8 -1
- package/lib/dash/content_protection.js +33 -1
- package/lib/dash/dash_parser.js +13 -5
- package/lib/hls/hls_parser.js +20 -4
- package/lib/media/drm_engine.js +29 -2
- package/lib/media/media_source_engine.js +9 -6
- package/lib/media/play_rate_controller.js +14 -3
- package/lib/media/playhead.js +8 -3
- package/lib/media/streaming_engine.js +68 -20
- package/lib/media/transmuxer.js +2 -2
- package/lib/media/video_wrapper.js +8 -3
- package/lib/net/data_uri_plugin.js +5 -2
- package/lib/net/http_fetch_plugin.js +3 -3
- package/lib/net/http_plugin_utils.js +2 -4
- package/lib/net/http_xhr_plugin.js +2 -2
- package/lib/net/networking_engine.js +1 -0
- package/lib/offline/offline_scheme.js +7 -2
- package/lib/player.js +18 -8
- package/lib/polyfill/input_event.js +7 -11
- package/lib/polyfill/mediasource.js +1 -1
- package/lib/polyfill/patchedmediakeys_apple.js +2 -72
- package/lib/text/cue.js +1 -1
- package/lib/text/ttml_text_parser.js +1 -1
- package/lib/util/config_utils.js +1 -0
- package/lib/util/error.js +45 -11
- package/lib/util/event_manager.js +211 -100
- package/lib/util/fairplay_utils.js +122 -0
- package/lib/util/i_releasable.js +1 -0
- package/lib/util/player_configuration.js +7 -0
- package/lib/util/pssh.js +41 -0
- package/lib/util/string_utils.js +42 -6
- package/lib/util/timer.js +1 -1
- package/package.json +33 -33
- package/roadmap.md +96 -0
- package/shaka-player.uncompiled.js +5 -1
- package/test/dash/dash_parser_content_protection_unit.js +35 -1
- package/test/dash/dash_parser_manifest_unit.js +60 -0
- package/test/hls/hls_live_unit.js +7 -1
- package/test/hls/hls_parser_unit.js +50 -0
- package/test/media/drm_engine_unit.js +10 -4
- package/test/media/media_source_engine_integration.js +12 -0
- package/test/media/media_source_engine_unit.js +3 -1
- package/test/media/playhead_unit.js +7 -5
- package/test/media/streaming_engine_unit.js +46 -1
- package/test/media/transmuxer_integration.js +13 -0
- package/test/net/data_uri_plugin_unit.js +13 -2
- package/test/net/http_plugin_unit.js +17 -12
- package/test/net/networking_engine_unit.js +17 -8
- package/test/offline/offline_scheme_unit.js +18 -8
- package/test/player_external.js +3 -2
- package/test/player_integration.js +94 -3
- package/test/player_src_equals_integration.js +2 -2
- package/test/player_unit.js +21 -8
- package/test/test/boot.js +20 -5
- package/test/test/externs/jasmine.js +48 -0
- package/test/test/util/expect_async_polyfill.js +145 -0
- package/test/test/util/fake_networking_engine.js +1 -0
- package/test/test/util/manifest_generator.js +2 -1
- package/test/test/util/test_scheme.js +34 -2
- package/test/test/util/ui_utils.js +41 -0
- package/test/test/util/util.js +16 -8
- package/test/ui/ui_unit.js +130 -4
- package/ui/audio_language_selection.js +17 -96
- package/ui/big_play_button.js +61 -0
- package/ui/controls.js +226 -335
- package/ui/controls.less +3 -5
- package/ui/element.js +24 -6
- package/ui/externs/ui.js +62 -9
- package/ui/fullscreen_button.js +2 -52
- package/ui/less/buttons.less +10 -16
- package/ui/less/containers.less +75 -20
- package/ui/less/general.less +18 -2
- package/ui/less/other_elements.less +2 -1
- package/ui/less/overflow_menu.less +11 -10
- package/ui/less/range_elements.less +12 -10
- package/ui/less/spinner.less +2 -0
- package/ui/overflow_menu.js +1 -1
- package/ui/pip_button.js +1 -1
- package/ui/{play_pause_button.js → play_button.js} +17 -47
- package/ui/presentation_time.js +17 -12
- package/ui/range_element.js +176 -0
- package/ui/resolution_selection.js +43 -106
- package/ui/seek_bar.js +204 -0
- package/ui/settings_menu.js +113 -0
- package/ui/small_play_button.js +73 -0
- package/ui/text_displayer.js +17 -14
- package/ui/text_selection.js +42 -107
- package/ui/ui.js +17 -40
- package/ui/volume_bar.js +40 -68
|
@@ -18,30 +18,29 @@
|
|
|
18
18
|
|
|
19
19
|
goog.provide('shaka.ui.ResolutionSelection');
|
|
20
20
|
|
|
21
|
-
goog.require('shaka.ui.Element');
|
|
22
21
|
goog.require('shaka.ui.Enums');
|
|
23
22
|
goog.require('shaka.ui.Locales');
|
|
24
23
|
goog.require('shaka.ui.Localization');
|
|
25
24
|
goog.require('shaka.ui.OverflowMenu');
|
|
25
|
+
goog.require('shaka.ui.SettingsMenu');
|
|
26
26
|
goog.require('shaka.util.Dom');
|
|
27
27
|
|
|
28
28
|
|
|
29
29
|
/**
|
|
30
|
-
* @extends {shaka.ui.
|
|
30
|
+
* @extends {shaka.ui.SettingsMenu}
|
|
31
31
|
* @final
|
|
32
32
|
* @export
|
|
33
33
|
*/
|
|
34
|
-
shaka.ui.ResolutionSelection = class extends shaka.ui.
|
|
34
|
+
shaka.ui.ResolutionSelection = class extends shaka.ui.SettingsMenu {
|
|
35
35
|
/**
|
|
36
36
|
* @param {!HTMLElement} parent
|
|
37
37
|
* @param {!shaka.ui.Controls} controls
|
|
38
38
|
*/
|
|
39
39
|
constructor(parent, controls) {
|
|
40
|
-
super(parent, controls);
|
|
40
|
+
super(parent, controls, shaka.ui.Enums.MaterialDesignIcons.RESOLUTION);
|
|
41
41
|
|
|
42
|
-
this.
|
|
43
|
-
|
|
44
|
-
this.addResolutionMenu_();
|
|
42
|
+
this.button.classList.add('shaka-resolution-button');
|
|
43
|
+
this.menu.classList.add('shaka-resolutions');
|
|
45
44
|
|
|
46
45
|
this.eventManager.listen(
|
|
47
46
|
this.localization, shaka.ui.Localization.LOCALE_UPDATED, () => {
|
|
@@ -53,9 +52,6 @@ shaka.ui.ResolutionSelection = class extends shaka.ui.Element {
|
|
|
53
52
|
this.updateLocalizedStrings_();
|
|
54
53
|
});
|
|
55
54
|
|
|
56
|
-
this.eventManager.listen(this.resolutionButton_, 'click', () => {
|
|
57
|
-
this.onResolutionClick_();
|
|
58
|
-
});
|
|
59
55
|
|
|
60
56
|
this.eventManager.listen(this.player, 'variantchanged', () => {
|
|
61
57
|
this.updateResolutionSelection_();
|
|
@@ -76,108 +72,56 @@ shaka.ui.ResolutionSelection = class extends shaka.ui.Element {
|
|
|
76
72
|
}
|
|
77
73
|
|
|
78
74
|
|
|
79
|
-
/**
|
|
80
|
-
* @private
|
|
81
|
-
*/
|
|
82
|
-
addResolutionButton_() {
|
|
83
|
-
/** @private {!HTMLElement}*/
|
|
84
|
-
this.resolutionButton_ = shaka.util.Dom.createHTMLElement('button');
|
|
85
|
-
|
|
86
|
-
this.resolutionButton_.classList.add('shaka-resolution-button');
|
|
87
|
-
|
|
88
|
-
const icon = shaka.util.Dom.createHTMLElement('i');
|
|
89
|
-
icon.classList.add('material-icons');
|
|
90
|
-
icon.textContent = shaka.ui.Enums.MaterialDesignIcons.RESOLUTION;
|
|
91
|
-
this.resolutionButton_.appendChild(icon);
|
|
92
|
-
|
|
93
|
-
const label = shaka.util.Dom.createHTMLElement('label');
|
|
94
|
-
label.classList.add('shaka-overflow-button-label');
|
|
95
|
-
|
|
96
|
-
/** @private {!HTMLElement}*/
|
|
97
|
-
this.resolutionNameSpan_ = shaka.util.Dom.createHTMLElement('span');
|
|
98
|
-
label.appendChild(this.resolutionNameSpan_);
|
|
99
|
-
|
|
100
|
-
/** @private {!HTMLElement}*/
|
|
101
|
-
this.currentResolution_ = shaka.util.Dom.createHTMLElement('span');
|
|
102
|
-
this.currentResolution_.classList.add('shaka-current-selection-span');
|
|
103
|
-
label.appendChild(this.currentResolution_);
|
|
104
|
-
this.resolutionButton_.appendChild(label);
|
|
105
|
-
|
|
106
|
-
this.parent.appendChild(this.resolutionButton_);
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
/**
|
|
111
|
-
* @private
|
|
112
|
-
*/
|
|
113
|
-
addResolutionMenu_() {
|
|
114
|
-
/** @private {!HTMLElement}*/
|
|
115
|
-
this.resolutionMenu_ = shaka.util.Dom.createHTMLElement('div');
|
|
116
|
-
this.resolutionMenu_.classList.add('shaka-resolutions');
|
|
117
|
-
this.resolutionMenu_.classList.add('shaka-no-propagation');
|
|
118
|
-
this.resolutionMenu_.classList.add('shaka-show-controls-on-mouse-over');
|
|
119
|
-
this.resolutionMenu_.classList.add('shaka-settings-menu');
|
|
120
|
-
|
|
121
|
-
/** @private {!HTMLElement}*/
|
|
122
|
-
this.backFromResolutionButton_ =
|
|
123
|
-
shaka.util.Dom.createHTMLElement('button');
|
|
124
|
-
this.backFromResolutionButton_.classList.add(
|
|
125
|
-
'shaka-back-to-overflow-button');
|
|
126
|
-
this.resolutionMenu_.appendChild(this.backFromResolutionButton_);
|
|
127
|
-
|
|
128
|
-
const backIcon = shaka.util.Dom.createHTMLElement('i');
|
|
129
|
-
backIcon.classList.add('material-icons');
|
|
130
|
-
backIcon.textContent = shaka.ui.Enums.MaterialDesignIcons.BACK;
|
|
131
|
-
this.backFromResolutionButton_.appendChild(backIcon);
|
|
132
|
-
|
|
133
|
-
/** @private {!HTMLElement}*/
|
|
134
|
-
this.backFromResolutionSpan_ = shaka.util.Dom.createHTMLElement('span');
|
|
135
|
-
this.backFromResolutionButton_.appendChild(this.backFromResolutionSpan_);
|
|
136
|
-
|
|
137
|
-
const controlsContainer = this.controls.getControlsContainer();
|
|
138
|
-
controlsContainer.appendChild(this.resolutionMenu_);
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
|
|
142
75
|
/** @private */
|
|
143
76
|
updateResolutionSelection_() {
|
|
77
|
+
/** @type {!Array.<shaka.extern.Track>} */
|
|
144
78
|
let tracks = this.player.getVariantTracks();
|
|
145
79
|
|
|
146
80
|
// Hide resolution menu and button for audio-only content and src= content
|
|
147
81
|
// without resolution information.
|
|
82
|
+
// TODO: for audio-only content, this should be a bitrate selection menu
|
|
83
|
+
// instead.
|
|
148
84
|
if (tracks.length && !tracks[0].height) {
|
|
149
|
-
shaka.ui.Utils.setDisplay(this.
|
|
150
|
-
shaka.ui.Utils.setDisplay(this.
|
|
85
|
+
shaka.ui.Utils.setDisplay(this.menu, false);
|
|
86
|
+
shaka.ui.Utils.setDisplay(this.button, false);
|
|
151
87
|
return;
|
|
152
88
|
}
|
|
153
89
|
// Otherwise, restore it.
|
|
154
|
-
shaka.ui.Utils.setDisplay(this.
|
|
90
|
+
shaka.ui.Utils.setDisplay(this.button, true);
|
|
155
91
|
|
|
156
|
-
tracks.sort(
|
|
157
|
-
return
|
|
92
|
+
tracks.sort((t1, t2) => {
|
|
93
|
+
return t2.height - t1.height;
|
|
158
94
|
});
|
|
159
|
-
tracks.reverse();
|
|
160
95
|
|
|
161
96
|
// If there is a selected variant track, then we filter out any tracks in
|
|
162
97
|
// a different language. Then we use those remaining tracks to display the
|
|
163
98
|
// available resolutions.
|
|
164
99
|
const selectedTrack = tracks.find((track) => track.active);
|
|
165
100
|
if (selectedTrack) {
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
101
|
+
// Filter by current audio language and channel count.
|
|
102
|
+
tracks = tracks.filter(
|
|
103
|
+
(track) => track.language == selectedTrack.language &&
|
|
104
|
+
track.channelsCount == selectedTrack.channelsCount);
|
|
169
105
|
}
|
|
170
106
|
|
|
107
|
+
// Remove duplicate entries with the same height. This can happen if
|
|
108
|
+
// we have multiple resolutions of audio. Pick an arbitrary one.
|
|
109
|
+
tracks = tracks.filter((track, idx) => {
|
|
110
|
+
// Keep the first one with the same height.
|
|
111
|
+
const otherIdx = tracks.findIndex((t) => t.height == track.height);
|
|
112
|
+
return otherIdx == idx;
|
|
113
|
+
});
|
|
114
|
+
|
|
171
115
|
// Remove old shaka-resolutions
|
|
172
116
|
// 1. Save the back to menu button
|
|
173
117
|
const backButton = shaka.ui.Utils.getFirstDescendantWithClassName(
|
|
174
|
-
this.
|
|
118
|
+
this.menu, 'shaka-back-to-overflow-button');
|
|
175
119
|
|
|
176
120
|
// 2. Remove everything
|
|
177
|
-
shaka.ui.Utils.removeAllChildren(this.
|
|
121
|
+
shaka.ui.Utils.removeAllChildren(this.menu);
|
|
178
122
|
|
|
179
123
|
// 3. Add the backTo Menu button back
|
|
180
|
-
this.
|
|
124
|
+
this.menu.appendChild(backButton);
|
|
181
125
|
|
|
182
126
|
const abrEnabled = this.player.getConfiguration().abr.enabled;
|
|
183
127
|
|
|
@@ -185,7 +129,7 @@ shaka.ui.ResolutionSelection = class extends shaka.ui.Element {
|
|
|
185
129
|
tracks.forEach((track) => {
|
|
186
130
|
const button = shaka.util.Dom.createHTMLElement('button');
|
|
187
131
|
button.classList.add('explicit-resolution');
|
|
188
|
-
|
|
132
|
+
this.eventManager.listen(button, 'click',
|
|
189
133
|
this.onTrackSelected_.bind(this, track));
|
|
190
134
|
|
|
191
135
|
const span = shaka.util.Dom.createHTMLElement('span');
|
|
@@ -197,15 +141,15 @@ shaka.ui.ResolutionSelection = class extends shaka.ui.Element {
|
|
|
197
141
|
button.setAttribute('aria-selected', 'true');
|
|
198
142
|
button.appendChild(shaka.ui.Utils.checkmarkIcon());
|
|
199
143
|
span.classList.add('shaka-chosen-item');
|
|
200
|
-
this.
|
|
144
|
+
this.currentSelection.textContent = span.textContent;
|
|
201
145
|
}
|
|
202
|
-
this.
|
|
146
|
+
this.menu.appendChild(button);
|
|
203
147
|
});
|
|
204
148
|
|
|
205
149
|
// Add the Auto button
|
|
206
150
|
const autoButton = shaka.util.Dom.createHTMLElement('button');
|
|
207
151
|
autoButton.classList.add('shaka-enable-abr-button');
|
|
208
|
-
|
|
152
|
+
this.eventManager.listen(autoButton, 'click', function() {
|
|
209
153
|
const config = {abr: {enabled: true}};
|
|
210
154
|
this.player.configure(config);
|
|
211
155
|
this.updateResolutionSelection_();
|
|
@@ -225,24 +169,17 @@ shaka.ui.ResolutionSelection = class extends shaka.ui.Element {
|
|
|
225
169
|
|
|
226
170
|
this.abrOnSpan_.classList.add('shaka-chosen-item');
|
|
227
171
|
|
|
228
|
-
this.
|
|
172
|
+
this.currentSelection.textContent =
|
|
229
173
|
this.localization.resolve(shaka.ui.Locales.Ids.AUTO_QUALITY);
|
|
230
174
|
}
|
|
231
175
|
|
|
232
|
-
this.
|
|
233
|
-
shaka.ui.Utils.focusOnTheChosenItem(this.
|
|
176
|
+
this.menu.appendChild(autoButton);
|
|
177
|
+
shaka.ui.Utils.focusOnTheChosenItem(this.menu);
|
|
234
178
|
this.controls.dispatchEvent(
|
|
235
179
|
new shaka.util.FakeEvent('resolutionselectionupdated'));
|
|
236
180
|
}
|
|
237
181
|
|
|
238
182
|
|
|
239
|
-
/** @private */
|
|
240
|
-
onResolutionClick_() {
|
|
241
|
-
this.controls.dispatchEvent(new shaka.util.FakeEvent('submenuopen'));
|
|
242
|
-
shaka.ui.Utils.setDisplay(this.resolutionMenu_, true);
|
|
243
|
-
shaka.ui.Utils.focusOnTheChosenItem(this.resolutionMenu_);
|
|
244
|
-
}
|
|
245
|
-
|
|
246
183
|
/**
|
|
247
184
|
* @param {!shaka.extern.Track} track
|
|
248
185
|
* @private
|
|
@@ -251,8 +188,8 @@ shaka.ui.ResolutionSelection = class extends shaka.ui.Element {
|
|
|
251
188
|
// Disable abr manager before changing tracks.
|
|
252
189
|
let config = {abr: {enabled: false}};
|
|
253
190
|
this.player.configure(config);
|
|
254
|
-
|
|
255
|
-
this.player.selectVariantTrack(track,
|
|
191
|
+
const clearBuffer = this.controls.getConfig().clearBufferOnQualityChange;
|
|
192
|
+
this.player.selectVariantTrack(track, clearBuffer);
|
|
256
193
|
}
|
|
257
194
|
|
|
258
195
|
|
|
@@ -262,19 +199,19 @@ shaka.ui.ResolutionSelection = class extends shaka.ui.Element {
|
|
|
262
199
|
updateLocalizedStrings_() {
|
|
263
200
|
const LocIds = shaka.ui.Locales.Ids;
|
|
264
201
|
|
|
265
|
-
this.
|
|
202
|
+
this.button.setAttribute(shaka.ui.Constants.ARIA_LABEL,
|
|
266
203
|
this.localization.resolve(LocIds.RESOLUTION));
|
|
267
|
-
this.
|
|
204
|
+
this.backButton.setAttribute(shaka.ui.Constants.ARIA_LABEL,
|
|
268
205
|
this.localization.resolve(LocIds.RESOLUTION));
|
|
269
|
-
this.
|
|
206
|
+
this.backSpan.textContent =
|
|
270
207
|
this.localization.resolve(LocIds.RESOLUTION);
|
|
271
|
-
this.
|
|
208
|
+
this.nameSpan.textContent =
|
|
272
209
|
this.localization.resolve(LocIds.RESOLUTION);
|
|
273
210
|
this.abrOnSpan_.textContent =
|
|
274
211
|
this.localization.resolve(LocIds.AUTO_QUALITY);
|
|
275
212
|
|
|
276
213
|
if (this.player.getConfiguration().abr.enabled) {
|
|
277
|
-
this.
|
|
214
|
+
this.currentSelection.textContent =
|
|
278
215
|
this.localization.resolve(shaka.ui.Locales.Ids.AUTO_QUALITY);
|
|
279
216
|
}
|
|
280
217
|
}
|
package/ui/seek_bar.js
ADDED
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2016 Google Inc.
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
goog.provide('shaka.ui.SeekBar');
|
|
20
|
+
|
|
21
|
+
goog.require('shaka.ui.Constants');
|
|
22
|
+
goog.require('shaka.ui.Locales');
|
|
23
|
+
goog.require('shaka.ui.Localization');
|
|
24
|
+
goog.require('shaka.ui.RangeElement');
|
|
25
|
+
goog.require('shaka.ui.Utils');
|
|
26
|
+
goog.require('shaka.util.Timer');
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* @extends {shaka.ui.RangeElement}
|
|
31
|
+
* @final
|
|
32
|
+
* @export
|
|
33
|
+
*/
|
|
34
|
+
shaka.ui.SeekBar = class extends shaka.ui.RangeElement {
|
|
35
|
+
/**
|
|
36
|
+
* @param {!HTMLElement} parent
|
|
37
|
+
* @param {!shaka.ui.Controls} controls
|
|
38
|
+
*/
|
|
39
|
+
constructor(parent, controls) {
|
|
40
|
+
super(parent, controls,
|
|
41
|
+
['shaka-seek-bar-container'],
|
|
42
|
+
[
|
|
43
|
+
'shaka-seek-bar',
|
|
44
|
+
'shaka-no-propagation',
|
|
45
|
+
'shaka-show-controls-on-mouse-over',
|
|
46
|
+
]);
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* This timer is used to introduce a delay between the user scrubbing across
|
|
50
|
+
* the seek bar and the seek being sent to the player.
|
|
51
|
+
*
|
|
52
|
+
* @private {shaka.util.Timer}
|
|
53
|
+
*/
|
|
54
|
+
this.seekTimer_ = new shaka.util.Timer(() => {
|
|
55
|
+
this.video.currentTime = this.getValue();
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
this.eventManager.listen(this.localization,
|
|
59
|
+
shaka.ui.Localization.LOCALE_UPDATED,
|
|
60
|
+
() => this.updateAriaLabel_());
|
|
61
|
+
|
|
62
|
+
this.eventManager.listen(this.localization,
|
|
63
|
+
shaka.ui.Localization.LOCALE_CHANGED,
|
|
64
|
+
() => this.updateAriaLabel_());
|
|
65
|
+
|
|
66
|
+
// Initialize seek state and label.
|
|
67
|
+
this.setValue(this.video.currentTime);
|
|
68
|
+
this.update();
|
|
69
|
+
this.updateAriaLabel_();
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/** @override */
|
|
73
|
+
async destroy() {
|
|
74
|
+
if (this.seekTimer_) {
|
|
75
|
+
this.seekTimer_.stop();
|
|
76
|
+
this.seekTimer_ = null;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
await super.destroy();
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Called by the base class when user interaction with the input element
|
|
84
|
+
* begins.
|
|
85
|
+
*
|
|
86
|
+
* @override
|
|
87
|
+
*/
|
|
88
|
+
onChangeStart() {
|
|
89
|
+
this.controls.setSeeking(true);
|
|
90
|
+
this.video.pause();
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Update the video element's state to match the input element's state.
|
|
95
|
+
* Called by the base class when the input element changes.
|
|
96
|
+
*
|
|
97
|
+
* @override
|
|
98
|
+
*/
|
|
99
|
+
onChange() {
|
|
100
|
+
if (!this.video.duration) {
|
|
101
|
+
// Can't seek yet. Ignore.
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Update the UI right away.
|
|
106
|
+
this.update();
|
|
107
|
+
|
|
108
|
+
// We want to wait until the user has stopped moving the seek bar for a
|
|
109
|
+
// little bit to reduce the number of times we ask the player to seek.
|
|
110
|
+
//
|
|
111
|
+
// To do this, we will start a timer that will fire in a little bit, but if
|
|
112
|
+
// we see another seek bar change, we will cancel that timer and re-start
|
|
113
|
+
// it.
|
|
114
|
+
//
|
|
115
|
+
// Calling |start| on an already pending timer will cancel the old request
|
|
116
|
+
// and start the new one.
|
|
117
|
+
this.seekTimer_.tickAfter(/* seconds= */ 0.125);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Called by the base class when user interaction with the input element
|
|
122
|
+
* ends.
|
|
123
|
+
*
|
|
124
|
+
* @override
|
|
125
|
+
*/
|
|
126
|
+
onChangeEnd() {
|
|
127
|
+
// They just let go of the seek bar, so cancel the timer and manually
|
|
128
|
+
// call the event so that we can respond immediately.
|
|
129
|
+
this.seekTimer_.tickNow();
|
|
130
|
+
this.controls.setSeeking(false);
|
|
131
|
+
this.video.play();
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/** @return {boolean} */
|
|
135
|
+
isShowing() {
|
|
136
|
+
// It is showing by default, so it is hidden if shaka-hidden is in the list.
|
|
137
|
+
return !this.container.classList.contains('shaka-hidden');
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Called by Controls on a timer to update the state of the seek bar.
|
|
142
|
+
* Also called internally when the user interacts with the input element.
|
|
143
|
+
*/
|
|
144
|
+
update() {
|
|
145
|
+
const Constants = shaka.ui.Constants;
|
|
146
|
+
|
|
147
|
+
const currentTime = this.getValue();
|
|
148
|
+
const bufferedLength = this.video.buffered.length;
|
|
149
|
+
const bufferedStart = bufferedLength ? this.video.buffered.start(0) : 0;
|
|
150
|
+
const bufferedEnd =
|
|
151
|
+
bufferedLength ? this.video.buffered.end(bufferedLength - 1) : 0;
|
|
152
|
+
|
|
153
|
+
const seekRange = this.player.seekRange();
|
|
154
|
+
const seekRangeSize = seekRange.end - seekRange.start;
|
|
155
|
+
|
|
156
|
+
this.setRange(seekRange.start, seekRange.end);
|
|
157
|
+
|
|
158
|
+
// Hide seekbar if the seek window is very small.
|
|
159
|
+
if (this.player.isLive() &&
|
|
160
|
+
seekRangeSize < Constants.MIN_SEEK_WINDOW_TO_SHOW_SEEKBAR) {
|
|
161
|
+
shaka.ui.Utils.setDisplay(this.container, false);
|
|
162
|
+
} else {
|
|
163
|
+
shaka.ui.Utils.setDisplay(this.container, true);
|
|
164
|
+
|
|
165
|
+
if (bufferedLength == 0) {
|
|
166
|
+
this.container.style.background = Constants.SEEK_BAR_BASE_COLOR;
|
|
167
|
+
} else {
|
|
168
|
+
const clampedBufferStart = Math.max(bufferedStart, seekRange.start);
|
|
169
|
+
const clampedBufferEnd = Math.min(bufferedEnd, seekRange.end);
|
|
170
|
+
const clampedCurrentTime = Math.min(
|
|
171
|
+
Math.max(currentTime, seekRange.start),
|
|
172
|
+
seekRange.end);
|
|
173
|
+
|
|
174
|
+
const bufferStartDistance = clampedBufferStart - seekRange.start;
|
|
175
|
+
const bufferEndDistance = clampedBufferEnd - seekRange.start;
|
|
176
|
+
const playheadDistance = clampedCurrentTime - seekRange.start;
|
|
177
|
+
|
|
178
|
+
// NOTE: the fallback to zero eliminates NaN.
|
|
179
|
+
const bufferStartFraction = (bufferStartDistance / seekRangeSize) || 0;
|
|
180
|
+
const bufferEndFraction = (bufferEndDistance / seekRangeSize) || 0;
|
|
181
|
+
const playheadFraction = (playheadDistance / seekRangeSize) || 0;
|
|
182
|
+
|
|
183
|
+
const makeColor = (color, fract) => color + ' ' + (fract * 100) + '%';
|
|
184
|
+
const gradient = [
|
|
185
|
+
'to right',
|
|
186
|
+
makeColor(Constants.SEEK_BAR_BASE_COLOR, bufferStartFraction),
|
|
187
|
+
makeColor(Constants.SEEK_BAR_PLAYED_COLOR, bufferStartFraction),
|
|
188
|
+
makeColor(Constants.SEEK_BAR_PLAYED_COLOR, playheadFraction),
|
|
189
|
+
makeColor(Constants.SEEK_BAR_BUFFERED_COLOR, playheadFraction),
|
|
190
|
+
makeColor(Constants.SEEK_BAR_BUFFERED_COLOR, bufferEndFraction),
|
|
191
|
+
makeColor(Constants.SEEK_BAR_BASE_COLOR, bufferEndFraction),
|
|
192
|
+
];
|
|
193
|
+
this.container.style.background =
|
|
194
|
+
'linear-gradient(' + gradient.join(',') + ')';
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/** @private */
|
|
200
|
+
updateAriaLabel_() {
|
|
201
|
+
this.bar.setAttribute(shaka.ui.Constants.ARIA_LABEL,
|
|
202
|
+
this.localization.resolve(shaka.ui.Locales.Ids.SEEK));
|
|
203
|
+
}
|
|
204
|
+
};
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2016 Google Inc.
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
goog.provide('shaka.ui.SettingsMenu');
|
|
20
|
+
|
|
21
|
+
goog.require('shaka.ui.Element');
|
|
22
|
+
goog.require('shaka.ui.Enums');
|
|
23
|
+
goog.require('shaka.util.Dom');
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* @extends {shaka.ui.Element}
|
|
28
|
+
* @export
|
|
29
|
+
*/
|
|
30
|
+
shaka.ui.SettingsMenu = class extends shaka.ui.Element {
|
|
31
|
+
/**
|
|
32
|
+
* @param {!HTMLElement} parent
|
|
33
|
+
* @param {!shaka.ui.Controls} controls
|
|
34
|
+
* @param {string} iconText
|
|
35
|
+
*/
|
|
36
|
+
constructor(parent, controls, iconText) {
|
|
37
|
+
super(parent, controls);
|
|
38
|
+
|
|
39
|
+
this.addButton_(iconText);
|
|
40
|
+
|
|
41
|
+
this.addMenu_();
|
|
42
|
+
|
|
43
|
+
this.eventManager.listen(this.button, 'click', () => {
|
|
44
|
+
this.onButtonClick_();
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* @param {string} iconText
|
|
51
|
+
* @private
|
|
52
|
+
*/
|
|
53
|
+
addButton_(iconText) {
|
|
54
|
+
/** @protected {!HTMLElement}*/
|
|
55
|
+
this.button = shaka.util.Dom.createHTMLElement('button');
|
|
56
|
+
|
|
57
|
+
/** @protected {!HTMLElement}*/
|
|
58
|
+
this.icon = shaka.util.Dom.createHTMLElement('i');
|
|
59
|
+
this.icon.classList.add('material-icons');
|
|
60
|
+
this.icon.textContent = iconText;
|
|
61
|
+
this.button.appendChild(this.icon);
|
|
62
|
+
|
|
63
|
+
const label = shaka.util.Dom.createHTMLElement('label');
|
|
64
|
+
label.classList.add('shaka-overflow-button-label');
|
|
65
|
+
|
|
66
|
+
/** @protected {!HTMLElement}*/
|
|
67
|
+
this.nameSpan = shaka.util.Dom.createHTMLElement('span');
|
|
68
|
+
label.appendChild(this.nameSpan);
|
|
69
|
+
|
|
70
|
+
/** @protected {!HTMLElement}*/
|
|
71
|
+
this.currentSelection = shaka.util.Dom.createHTMLElement('span');
|
|
72
|
+
this.currentSelection.classList.add('shaka-current-selection-span');
|
|
73
|
+
label.appendChild(this.currentSelection);
|
|
74
|
+
this.button.appendChild(label);
|
|
75
|
+
|
|
76
|
+
this.parent.appendChild(this.button);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
/** @private */
|
|
81
|
+
addMenu_() {
|
|
82
|
+
/** @protected {!HTMLElement}*/
|
|
83
|
+
this.menu = shaka.util.Dom.createHTMLElement('div');
|
|
84
|
+
this.menu.classList.add('shaka-no-propagation');
|
|
85
|
+
this.menu.classList.add('shaka-show-controls-on-mouse-over');
|
|
86
|
+
this.menu.classList.add('shaka-settings-menu');
|
|
87
|
+
|
|
88
|
+
/** @protected {!HTMLElement}*/
|
|
89
|
+
this.backButton = shaka.util.Dom.createHTMLElement('button');
|
|
90
|
+
this.backButton.classList.add('shaka-back-to-overflow-button');
|
|
91
|
+
this.menu.appendChild(this.backButton);
|
|
92
|
+
|
|
93
|
+
const backIcon = shaka.util.Dom.createHTMLElement('i');
|
|
94
|
+
backIcon.classList.add('material-icons');
|
|
95
|
+
backIcon.textContent = shaka.ui.Enums.MaterialDesignIcons.BACK;
|
|
96
|
+
this.backButton.appendChild(backIcon);
|
|
97
|
+
|
|
98
|
+
/** @protected {!HTMLElement}*/
|
|
99
|
+
this.backSpan = shaka.util.Dom.createHTMLElement('span');
|
|
100
|
+
this.backButton.appendChild(this.backSpan);
|
|
101
|
+
|
|
102
|
+
const controlsContainer = this.controls.getControlsContainer();
|
|
103
|
+
controlsContainer.appendChild(this.menu);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
/** @private */
|
|
108
|
+
onButtonClick_() {
|
|
109
|
+
this.controls.dispatchEvent(new shaka.util.FakeEvent('submenuopen'));
|
|
110
|
+
shaka.ui.Utils.setDisplay(this.menu, true);
|
|
111
|
+
shaka.ui.Utils.focusOnTheChosenItem(this.menu);
|
|
112
|
+
}
|
|
113
|
+
};
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2016 Google Inc.
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
goog.provide('shaka.ui.SmallPlayButton');
|
|
20
|
+
|
|
21
|
+
goog.require('shaka.ui.PlayButton');
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* @extends {shaka.ui.PlayButton}
|
|
26
|
+
* @final
|
|
27
|
+
* @export
|
|
28
|
+
*/
|
|
29
|
+
shaka.ui.SmallPlayButton = class extends shaka.ui.PlayButton {
|
|
30
|
+
/**
|
|
31
|
+
* @param {!HTMLElement} parent
|
|
32
|
+
* @param {!shaka.ui.Controls} controls
|
|
33
|
+
*/
|
|
34
|
+
constructor(parent, controls) {
|
|
35
|
+
super(parent, controls);
|
|
36
|
+
|
|
37
|
+
this.button.classList.add('shaka-small-play-button');
|
|
38
|
+
this.button.classList.add('material-icons');
|
|
39
|
+
|
|
40
|
+
this.updateIcon_();
|
|
41
|
+
this.updateAriaLabel();
|
|
42
|
+
|
|
43
|
+
this.eventManager.listen(this.video, 'play', () => {
|
|
44
|
+
this.updateIcon_();
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
this.eventManager.listen(this.video, 'pause', () => {
|
|
48
|
+
this.updateIcon_();
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
/** @private */
|
|
54
|
+
updateIcon_() {
|
|
55
|
+
const Icons = shaka.ui.Enums.MaterialDesignIcons;
|
|
56
|
+
this.button.textContent = this.isPaused() ? Icons.PLAY : Icons.PAUSE;
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* @implements {shaka.extern.IUIElement.Factory}
|
|
63
|
+
* @final
|
|
64
|
+
*/
|
|
65
|
+
shaka.ui.SmallPlayButton.Factory = class {
|
|
66
|
+
/** @override */
|
|
67
|
+
create(rootElement, controls) {
|
|
68
|
+
return new shaka.ui.SmallPlayButton(rootElement, controls);
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
shaka.ui.Controls.registerElement(
|
|
73
|
+
'play_pause', new shaka.ui.SmallPlayButton.Factory());
|