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
package/build/test.py
CHANGED
|
@@ -191,8 +191,8 @@ class Launcher:
|
|
|
191
191
|
action='store_true')
|
|
192
192
|
running_commands.add_argument(
|
|
193
193
|
'--runs',
|
|
194
|
-
help='Set the number of times each test should run.
|
|
195
|
-
'
|
|
194
|
+
help='Set the number of times each test should run. (default '
|
|
195
|
+
'%(default)s) ',
|
|
196
196
|
type=_IntGreaterThanZero,
|
|
197
197
|
default=1,
|
|
198
198
|
dest='runs')
|
|
@@ -215,16 +215,16 @@ class Launcher:
|
|
|
215
215
|
running_commands.add_argument(
|
|
216
216
|
'--capture-timeout',
|
|
217
217
|
help='Kill the browser if it does not capture in the given time [ms]. '
|
|
218
|
-
'
|
|
218
|
+
'(default %(default)s)',
|
|
219
219
|
type=int,
|
|
220
220
|
default=60000)
|
|
221
221
|
running_commands.add_argument(
|
|
222
222
|
'--delay-tests',
|
|
223
|
-
help='Insert an
|
|
223
|
+
help='Insert an artificial delay between tests, in seconds. '
|
|
224
224
|
'This can be helpful when tracking down asynchronous test '
|
|
225
225
|
'pollution, in which an async process belonging to one test may '
|
|
226
226
|
'trigger a failure after other tests have begun. '
|
|
227
|
-
'
|
|
227
|
+
'(default %(const)s)',
|
|
228
228
|
type=int,
|
|
229
229
|
default=None,
|
|
230
230
|
const=2,
|
|
@@ -242,6 +242,12 @@ class Launcher:
|
|
|
242
242
|
type=str,
|
|
243
243
|
metavar='KEY_SYSTEM_ID=LICENSE_SERVER_URI',
|
|
244
244
|
action=_HandleKeyValuePairs)
|
|
245
|
+
running_commands.add_argument(
|
|
246
|
+
'--test-timeout',
|
|
247
|
+
help='Sets the test timeout value [ms] (default %(default)s)',
|
|
248
|
+
dest='test_timeout',
|
|
249
|
+
default=120000,
|
|
250
|
+
type=int)
|
|
245
251
|
|
|
246
252
|
|
|
247
253
|
logging_commands.add_argument(
|
|
@@ -267,9 +273,9 @@ class Launcher:
|
|
|
267
273
|
action='store_true')
|
|
268
274
|
logging_commands.add_argument(
|
|
269
275
|
'--enable-logging',
|
|
270
|
-
help='Print log messages from tests and limits the type of log
|
|
271
|
-
'printed. If
|
|
272
|
-
'
|
|
276
|
+
help='Print log messages from tests and limits the type of log '
|
|
277
|
+
'messages printed. If --enable-logging is not given, no logs '
|
|
278
|
+
'will be printed. (default %(const)s)',
|
|
273
279
|
choices=['none', 'error', 'warning', 'info', 'debug', 'v1', 'v2'],
|
|
274
280
|
default='none',
|
|
275
281
|
const='info',
|
|
@@ -348,6 +354,7 @@ class Launcher:
|
|
|
348
354
|
'delay_tests',
|
|
349
355
|
'test_custom_asset',
|
|
350
356
|
'test_custom_license_server',
|
|
357
|
+
'test_timeout',
|
|
351
358
|
]
|
|
352
359
|
|
|
353
360
|
# Check each value before setting it to avoid passing null values.
|
|
@@ -379,6 +386,10 @@ class Launcher:
|
|
|
379
386
|
if self.parsed_args.exclude_browsers and 'browsers' in self.karma_config:
|
|
380
387
|
all_browsers = set(self.karma_config['browsers'])
|
|
381
388
|
bad_browsers = set(self.parsed_args.exclude_browsers)
|
|
389
|
+
if bad_browsers - all_browsers:
|
|
390
|
+
raise RuntimeError('Attempting to exclude unselected browsers: %s' %
|
|
391
|
+
','.join(bad_browsers - all_browsers))
|
|
392
|
+
|
|
382
393
|
good_browsers = all_browsers - bad_browsers
|
|
383
394
|
self.karma_config['browsers'] = list(good_browsers)
|
|
384
395
|
|
|
@@ -421,7 +432,8 @@ class Launcher:
|
|
|
421
432
|
# Run the command.
|
|
422
433
|
results = []
|
|
423
434
|
for run in range(self.parsed_args.runs):
|
|
424
|
-
logging.info('Running test (%d / %d
|
|
435
|
+
logging.info('Running test (%d / %d, %d failed so far)...',
|
|
436
|
+
run + 1, self.parsed_args.runs, len(results) - results.count(0))
|
|
425
437
|
results.append(shakaBuildHelpers.execute_get_code(cmd))
|
|
426
438
|
|
|
427
439
|
# Print a summary of the results.
|
package/build/types/core
CHANGED
package/build/types/ui
CHANGED
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
+../../third_party/language-mapping-list/language-mapping-list.js
|
|
4
4
|
+../../ui/audio_language_selection.js
|
|
5
5
|
+../../ui/externs/ui.js
|
|
6
|
+
+../../ui/play_button.js
|
|
7
|
+
+../../ui/big_play_button.js
|
|
6
8
|
+../../ui/cast_button.js
|
|
7
9
|
+../../ui/controls.js
|
|
8
10
|
+../../ui/constants.js
|
|
@@ -15,10 +17,13 @@
|
|
|
15
17
|
+../../ui/mute_button.js
|
|
16
18
|
+../../ui/overflow_menu.js
|
|
17
19
|
+../../ui/pip_button.js
|
|
18
|
-
+../../ui/
|
|
20
|
+
+../../ui/small_play_button.js
|
|
19
21
|
+../../ui/presentation_time.js
|
|
22
|
+
+../../ui/range_element.js
|
|
20
23
|
+../../ui/resolution_selection.js
|
|
21
24
|
+../../ui/rewind_button.js
|
|
25
|
+
+../../ui/seek_bar.js
|
|
26
|
+
+../../ui/settings_menu.js
|
|
22
27
|
+../../ui/spacer.js
|
|
23
28
|
+../../ui/text_displayer.js
|
|
24
29
|
+../../ui/text_selection.js
|
package/demo/asset_card.js
CHANGED
|
@@ -16,17 +16,20 @@
|
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
18
|
|
|
19
|
+
goog.provide('shakaDemo.AssetCard');
|
|
20
|
+
|
|
21
|
+
|
|
19
22
|
/**
|
|
20
23
|
* Creates and contains an MDL card that presents info about the given asset.
|
|
21
24
|
* @final
|
|
22
25
|
*/
|
|
23
|
-
class
|
|
26
|
+
shakaDemo.AssetCard = class {
|
|
24
27
|
/**
|
|
25
28
|
* @param {!Element} parentDiv
|
|
26
29
|
* @param {!ShakaDemoAssetInfo} asset
|
|
27
30
|
* @param {boolean} isFeatured True if this card should use the "featured"
|
|
28
31
|
* style, which use the asset's short name and have descriptions.
|
|
29
|
-
* @param {function(!AssetCard)} remakeButtonsFn
|
|
32
|
+
* @param {function(!shakaDemo.AssetCard)} remakeButtonsFn
|
|
30
33
|
*/
|
|
31
34
|
constructor(parentDiv, asset, isFeatured, remakeButtonsFn) {
|
|
32
35
|
/** @private {!Element} */
|
|
@@ -38,8 +41,15 @@ class AssetCard {
|
|
|
38
41
|
/** @private {!Element} */
|
|
39
42
|
this.featureIconsContainer_ = document.createElement('div');
|
|
40
43
|
/** @private {!Element} */
|
|
41
|
-
this.
|
|
42
|
-
|
|
44
|
+
this.progressCircle_ = document.createElement('div');
|
|
45
|
+
const svgns = 'http://www.w3.org/2000/svg';
|
|
46
|
+
/** @private {!Element} */
|
|
47
|
+
this.progressCircleSvg_ = document.createElementNS(svgns, 'svg');
|
|
48
|
+
/** @private {!Element} */
|
|
49
|
+
this.progressCircleBack_ = document.createElementNS(svgns, 'circle');
|
|
50
|
+
/** @private {!Element} */
|
|
51
|
+
this.progressCircleBar_ = document.createElementNS(svgns, 'circle');
|
|
52
|
+
/** @private {function(!shakaDemo.AssetCard)} */
|
|
43
53
|
this.remakeButtonsFn_ = remakeButtonsFn;
|
|
44
54
|
|
|
45
55
|
// Lay out the card.
|
|
@@ -53,7 +63,8 @@ class AssetCard {
|
|
|
53
63
|
this.card_.appendChild(titleDiv);
|
|
54
64
|
const titleText = document.createElement('h2');
|
|
55
65
|
titleText.classList.add('mdl-card__title-text');
|
|
56
|
-
titleText.textContent =
|
|
66
|
+
titleText.textContent =
|
|
67
|
+
isFeatured ? (asset.shortName || asset.name) : asset.name;
|
|
57
68
|
titleDiv.appendChild(titleText);
|
|
58
69
|
|
|
59
70
|
if (asset.iconUri) {
|
|
@@ -92,12 +103,17 @@ class AssetCard {
|
|
|
92
103
|
this.actions_.classList.add('mdl-card--border');
|
|
93
104
|
this.card_.appendChild(this.actions_);
|
|
94
105
|
|
|
95
|
-
|
|
96
|
-
this.
|
|
97
|
-
this.
|
|
98
|
-
this.
|
|
99
|
-
|
|
100
|
-
this.
|
|
106
|
+
this.progressCircle_.classList.add('hidden');
|
|
107
|
+
this.progressCircle_.classList.add('progress-circle');
|
|
108
|
+
this.card_.appendChild(this.progressCircle_);
|
|
109
|
+
this.progressCircleSvg_.appendChild(this.progressCircleBack_);
|
|
110
|
+
this.progressCircleSvg_.appendChild(this.progressCircleBar_);
|
|
111
|
+
this.progressCircle_.appendChild(this.progressCircleSvg_);
|
|
112
|
+
// You can't use access the classList of an svg on IE, so set the class
|
|
113
|
+
// attribute instead.
|
|
114
|
+
this.progressCircleSvg_.setAttribute('class', 'progress-circle-svg');
|
|
115
|
+
this.progressCircleBack_.setAttribute('class', 'progress-circle-back');
|
|
116
|
+
this.progressCircleBar_.setAttribute('class', 'progress-circle-bar');
|
|
101
117
|
|
|
102
118
|
parentDiv.appendChild(this.card_);
|
|
103
119
|
// Remake buttons AFTER appending to parent div, so that any tooltips can
|
|
@@ -105,6 +121,23 @@ class AssetCard {
|
|
|
105
121
|
this.remakeButtons();
|
|
106
122
|
}
|
|
107
123
|
|
|
124
|
+
/**
|
|
125
|
+
* @param {number} progress
|
|
126
|
+
* @private
|
|
127
|
+
*/
|
|
128
|
+
styleProgressCircle_(progress) {
|
|
129
|
+
const svg = this.progressCircleSvg_;
|
|
130
|
+
const bar = this.progressCircleBar_;
|
|
131
|
+
const circleSize = 45;
|
|
132
|
+
const circleThickness = 5;
|
|
133
|
+
const circleRadius = (circleSize - circleThickness) / 2;
|
|
134
|
+
const circumference = 2 * Math.PI * circleRadius;
|
|
135
|
+
|
|
136
|
+
svg.setAttribute('viewBox', '0 0 ' + circleSize + ' ' + circleSize);
|
|
137
|
+
bar.setAttribute('stroke-dasharray', circumference);
|
|
138
|
+
bar.setAttribute('stroke-dashoffset', (circumference * (1 - progress)));
|
|
139
|
+
}
|
|
140
|
+
|
|
108
141
|
/**
|
|
109
142
|
* @param {string} icon
|
|
110
143
|
* @param {string} title
|
|
@@ -116,7 +149,7 @@ class AssetCard {
|
|
|
116
149
|
iconDiv.setAttribute('icon', icon);
|
|
117
150
|
this.featureIconsContainer_.appendChild(iconDiv);
|
|
118
151
|
|
|
119
|
-
|
|
152
|
+
shakaDemo.Tooltips.make(iconDiv, title);
|
|
120
153
|
}
|
|
121
154
|
|
|
122
155
|
/**
|
|
@@ -162,7 +195,7 @@ class AssetCard {
|
|
|
162
195
|
|
|
163
196
|
/**
|
|
164
197
|
* Modify an asset to make it clear that it is unsupported.
|
|
165
|
-
* @param {
|
|
198
|
+
* @param {string} unsupportedReason
|
|
166
199
|
*/
|
|
167
200
|
markAsUnsupported(unsupportedReason) {
|
|
168
201
|
this.card_.classList.add('asset-card-unsupported');
|
|
@@ -172,7 +205,7 @@ class AssetCard {
|
|
|
172
205
|
/**
|
|
173
206
|
* Make a button that represents the lack of a working button.
|
|
174
207
|
* @param {string} buttonName
|
|
175
|
-
* @param {
|
|
208
|
+
* @param {string} unsupportedReason
|
|
176
209
|
* @return {!Element}
|
|
177
210
|
* @private
|
|
178
211
|
*/
|
|
@@ -180,22 +213,17 @@ class AssetCard {
|
|
|
180
213
|
const button = this.addButton(buttonName, () => {});
|
|
181
214
|
button.setAttribute('disabled', '');
|
|
182
215
|
|
|
183
|
-
//
|
|
184
|
-
// tooltip won't be clipped by other asset cards.
|
|
185
|
-
// Also, tooltips don't work on disabled buttons (on some platforms), so
|
|
216
|
+
// Tooltips don't work on disabled buttons (on some platforms), so
|
|
186
217
|
// the button itself has to be "uprooted" and placed in a synthetic div
|
|
187
218
|
// specifically to attach the tooltip to.
|
|
188
|
-
const
|
|
189
|
-
if (
|
|
190
|
-
|
|
191
|
-
if (button.parentElement) {
|
|
192
|
-
button.parentElement.removeChild(button);
|
|
193
|
-
}
|
|
194
|
-
attachPoint.classList.add('tooltip-attach-point');
|
|
195
|
-
attachPoint.appendChild(button);
|
|
196
|
-
this.actions_.appendChild(attachPoint);
|
|
197
|
-
ShakaDemoTooltips.make(tooltipContainer, attachPoint, unsupportedReason);
|
|
219
|
+
const attachPoint = document.createElement('div');
|
|
220
|
+
if (button.parentElement) {
|
|
221
|
+
button.parentElement.removeChild(button);
|
|
198
222
|
}
|
|
223
|
+
attachPoint.classList.add('tooltip-attach-point');
|
|
224
|
+
attachPoint.appendChild(button);
|
|
225
|
+
this.actions_.appendChild(attachPoint);
|
|
226
|
+
shakaDemo.Tooltips.make(attachPoint, unsupportedReason);
|
|
199
227
|
|
|
200
228
|
return button;
|
|
201
229
|
}
|
|
@@ -229,10 +257,12 @@ class AssetCard {
|
|
|
229
257
|
* Makes the contents of the button into an MDL icon, and moves it into the
|
|
230
258
|
* upper-righthand corner with CSS styles.
|
|
231
259
|
* @param {!Element} button
|
|
260
|
+
* @param {!Element} attachPoint If there is no attach point, just pass the
|
|
261
|
+
* button in here.
|
|
232
262
|
* @param {string} iconText
|
|
233
263
|
*/
|
|
234
|
-
const styleAsDownloadButton = (button, iconText) => {
|
|
235
|
-
|
|
264
|
+
const styleAsDownloadButton = (button, attachPoint, iconText) => {
|
|
265
|
+
attachPoint.classList.add('asset-card-corner-button');
|
|
236
266
|
const icon = document.createElement('i');
|
|
237
267
|
icon.textContent = iconText;
|
|
238
268
|
icon.classList.add('material-icons');
|
|
@@ -241,27 +271,85 @@ class AssetCard {
|
|
|
241
271
|
|
|
242
272
|
const unsupportedReason = shakaDemoMain.getAssetUnsupportedReason(
|
|
243
273
|
this.asset_, /* needOffline= */ true);
|
|
244
|
-
if (unsupportedReason
|
|
274
|
+
if (!unsupportedReason) {
|
|
275
|
+
goog.asserts.assert(this.asset_.storeCallback,
|
|
276
|
+
'A storage callback is expected for all supported assets!');
|
|
277
|
+
}
|
|
278
|
+
if (unsupportedReason) {
|
|
245
279
|
// This can't be stored.
|
|
246
280
|
const button = this.makeUnsupportedButton_('', unsupportedReason);
|
|
247
|
-
|
|
281
|
+
// As this is a unsupported button, it is wrapped in an "attach point";
|
|
282
|
+
// that is the element this has to move with CSS, otherwise the tooltip
|
|
283
|
+
// will end up coming out of the wrong place.
|
|
284
|
+
const attachPoint = button.parentElement || button;
|
|
285
|
+
styleAsDownloadButton(button, attachPoint, 'get_app');
|
|
248
286
|
return;
|
|
249
287
|
}
|
|
250
288
|
if (this.asset_.isStored()) {
|
|
251
|
-
const deleteButton = this.addButton('',
|
|
252
|
-
deleteButton
|
|
253
|
-
await this.asset_.unstoreCallback();
|
|
254
|
-
this.remakeButtons();
|
|
289
|
+
const deleteButton = this.addButton('', () => {
|
|
290
|
+
this.makeDeleteDialog_(deleteButton);
|
|
255
291
|
});
|
|
256
|
-
styleAsDownloadButton(deleteButton, '
|
|
292
|
+
styleAsDownloadButton(deleteButton, deleteButton, 'offline_pin');
|
|
257
293
|
} else {
|
|
258
294
|
const downloadButton = this.addButton('', async () => {
|
|
259
295
|
downloadButton.disabled = true;
|
|
260
296
|
await this.asset_.storeCallback();
|
|
261
297
|
this.remakeButtons();
|
|
262
298
|
});
|
|
263
|
-
styleAsDownloadButton(downloadButton, 'get_app');
|
|
299
|
+
styleAsDownloadButton(downloadButton, downloadButton, 'get_app');
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
/**
|
|
304
|
+
* @param {!Element} deleteButton
|
|
305
|
+
* @private
|
|
306
|
+
*/
|
|
307
|
+
makeDeleteDialog_(deleteButton) {
|
|
308
|
+
const parentDiv = this.card_.parentElement;
|
|
309
|
+
if (!parentDiv) {
|
|
310
|
+
return;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
const dialog = document.createElement('dialog');
|
|
314
|
+
dialog.classList.add('mdl-dialog');
|
|
315
|
+
parentDiv.appendChild(dialog);
|
|
316
|
+
if (!dialog.showModal) {
|
|
317
|
+
dialogPolyfill.registerDialog(dialog);
|
|
264
318
|
}
|
|
319
|
+
|
|
320
|
+
const textElement = document.createElement('h2');
|
|
321
|
+
textElement.classList.add('mdl-typography--title');
|
|
322
|
+
// TODO: Localize these messages.
|
|
323
|
+
textElement.textContent = 'Delete the offline copy?';
|
|
324
|
+
dialog.appendChild(textElement);
|
|
325
|
+
|
|
326
|
+
const buttonsDiv = document.createElement('div');
|
|
327
|
+
dialog.appendChild(buttonsDiv);
|
|
328
|
+
const makeButton = (text, fn) => {
|
|
329
|
+
const button = document.createElement('button');
|
|
330
|
+
button.textContent = text;
|
|
331
|
+
button.classList.add('mdl-button');
|
|
332
|
+
button.classList.add('mdl-button--colored');
|
|
333
|
+
button.classList.add('mdl-js-button');
|
|
334
|
+
button.classList.add('mdl-js-ripple-effect');
|
|
335
|
+
button.addEventListener('click', () => {
|
|
336
|
+
fn();
|
|
337
|
+
});
|
|
338
|
+
buttonsDiv.appendChild(button);
|
|
339
|
+
button.blur();
|
|
340
|
+
};
|
|
341
|
+
// TODO: Localize these messages.
|
|
342
|
+
makeButton('Yes', async () => {
|
|
343
|
+
dialog.close();
|
|
344
|
+
deleteButton.disabled = true;
|
|
345
|
+
await this.asset_.unstoreCallback();
|
|
346
|
+
this.remakeButtons();
|
|
347
|
+
});
|
|
348
|
+
makeButton('No', () => {
|
|
349
|
+
dialog.close();
|
|
350
|
+
});
|
|
351
|
+
|
|
352
|
+
dialog.showModal();
|
|
265
353
|
}
|
|
266
354
|
|
|
267
355
|
/**
|
|
@@ -269,17 +357,17 @@ class AssetCard {
|
|
|
269
357
|
*/
|
|
270
358
|
updateProgress() {
|
|
271
359
|
if (this.asset_.storedProgress < 1) {
|
|
272
|
-
this.
|
|
360
|
+
this.progressCircle_.classList.remove('hidden');
|
|
273
361
|
for (const button of this.actions_.childNodes) {
|
|
274
362
|
button.disabled = true;
|
|
275
363
|
}
|
|
276
364
|
} else {
|
|
277
|
-
this.
|
|
365
|
+
this.progressCircle_.classList.add('hidden');
|
|
278
366
|
for (const button of this.actions_.childNodes) {
|
|
279
367
|
button.disabled = false;
|
|
280
368
|
}
|
|
281
369
|
}
|
|
282
|
-
this.
|
|
370
|
+
this.styleProgressCircle_(this.asset_.storedProgress);
|
|
283
371
|
}
|
|
284
372
|
|
|
285
373
|
/**
|
|
@@ -304,4 +392,4 @@ class AssetCard {
|
|
|
304
392
|
this.actions_.appendChild(button);
|
|
305
393
|
return button;
|
|
306
394
|
}
|
|
307
|
-
}
|
|
395
|
+
};
|
|
@@ -53,6 +53,14 @@ body {
|
|
|
53
53
|
display: none;
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
+
/* The UI default style for fullscreen is to make the font size relative to the
|
|
57
|
+
* window height. That is also appropriate for the cast receiver experience.
|
|
58
|
+
* Since playback here is not technically in fullscreen mode, we just duplicate
|
|
59
|
+
* the style. */
|
|
60
|
+
.shaka-text-container {
|
|
61
|
+
font-size: 4.4vh;
|
|
62
|
+
}
|
|
63
|
+
|
|
56
64
|
#idle {
|
|
57
65
|
position: absolute;
|
|
58
66
|
top: 0;
|
|
@@ -64,7 +72,6 @@ body {
|
|
|
64
72
|
* they will be visible on top until we decide to hide them and show the
|
|
65
73
|
* player. */
|
|
66
74
|
z-index: 99;
|
|
67
|
-
|
|
68
75
|
padding-top: 60px;
|
|
69
76
|
padding-left: 0;
|
|
70
77
|
background-color: black;
|
|
@@ -97,18 +104,25 @@ body:after {
|
|
|
97
104
|
}
|
|
98
105
|
|
|
99
106
|
@keyframes bg-change {
|
|
100
|
-
0%
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
107
|
+
0% { background-image: url('idle1.jpg'); padding-left: 0; }
|
|
108
|
+
|
|
109
|
+
32% { background-image: url('idle1.jpg'); padding-left: 0; }
|
|
110
|
+
|
|
111
|
+
34% { background-image: url('idle2.jpg'); padding-left: 0; }
|
|
112
|
+
|
|
113
|
+
49% { background-image: url('idle2.jpg'); padding-left: 0; }
|
|
114
|
+
|
|
115
|
+
50% { background-image: url('idle2.jpg'); padding-left: 400px; }
|
|
116
|
+
|
|
117
|
+
65% { background-image: url('idle2.jpg'); padding-left: 400px; }
|
|
118
|
+
|
|
119
|
+
67% { background-image: url('idle3.jpg'); padding-left: 400px; }
|
|
120
|
+
|
|
121
|
+
87% { background-image: url('idle3.jpg'); padding-left: 400px; }
|
|
122
|
+
|
|
123
|
+
88% { background-image: url('idle3.jpg'); padding-left: 0; }
|
|
124
|
+
|
|
125
|
+
98% { background-image: url('idle3.jpg'); padding-left: 0; }
|
|
112
126
|
|
|
113
127
|
100% { background-image: url('idle1.jpg'); padding-left: 0; }
|
|
114
128
|
}
|
package/demo/close_button.js
CHANGED
|
@@ -16,21 +16,22 @@
|
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
18
|
|
|
19
|
+
goog.provide('shakaDemo.CloseButton');
|
|
20
|
+
|
|
21
|
+
|
|
19
22
|
/**
|
|
20
23
|
* A custom UI button, to allow users to close the video element.
|
|
21
24
|
* This cannot actually extend shaka.ui.Element, as that class does not exist
|
|
22
25
|
* at load-time when in uncompiled mode.
|
|
23
|
-
* @
|
|
26
|
+
* @extends {shaka.ui.Element}
|
|
24
27
|
*/
|
|
25
|
-
class
|
|
28
|
+
shakaDemo.CloseButton = class extends shaka.ui.Element {
|
|
26
29
|
/**
|
|
27
30
|
* @param {!HTMLElement} parent
|
|
28
31
|
* @param {!shaka.ui.Controls} controls
|
|
29
32
|
*/
|
|
30
33
|
constructor(parent, controls) {
|
|
31
|
-
|
|
32
|
-
this.parent = parent;
|
|
33
|
-
|
|
34
|
+
super(parent, controls);
|
|
34
35
|
this.button_ = document.createElement('button');
|
|
35
36
|
this.button_.classList.add('material-icons');
|
|
36
37
|
this.button_.classList.add('close-button');
|
|
@@ -38,12 +39,6 @@ class CloseButton {
|
|
|
38
39
|
this.parent.appendChild(this.button_);
|
|
39
40
|
|
|
40
41
|
this.button_.addEventListener('click', () => {
|
|
41
|
-
if (document.fullscreenElement) {
|
|
42
|
-
document.exitFullscreen();
|
|
43
|
-
}
|
|
44
|
-
if (document.pictureInPictureElement) {
|
|
45
|
-
document.exitPictureInPicture();
|
|
46
|
-
}
|
|
47
42
|
shakaDemoMain.unload();
|
|
48
43
|
});
|
|
49
44
|
|
|
@@ -55,19 +50,19 @@ class CloseButton {
|
|
|
55
50
|
destroy() {
|
|
56
51
|
return Promise.resolve();
|
|
57
52
|
}
|
|
58
|
-
}
|
|
53
|
+
};
|
|
59
54
|
|
|
60
55
|
/**
|
|
61
56
|
* @implements {shaka.extern.IUIElement.Factory}
|
|
62
57
|
* @final
|
|
63
58
|
*/
|
|
64
|
-
CloseButton.Factory = class {
|
|
59
|
+
shakaDemo.CloseButton.Factory = class {
|
|
65
60
|
/** @override */
|
|
66
61
|
create(rootElement, controls) {
|
|
67
|
-
return new CloseButton(rootElement, controls);
|
|
62
|
+
return new shakaDemo.CloseButton(rootElement, controls);
|
|
68
63
|
}
|
|
69
64
|
};
|
|
70
65
|
|
|
71
|
-
// This button is registered inside setup in
|
|
66
|
+
// This button is registered inside setup in shakaDemo.Main, rather than
|
|
72
67
|
// statically here, since shaka.ui.Controls does not exist in this stage of the
|
|
73
68
|
// load process.
|
package/demo/common/asset.js
CHANGED
|
@@ -18,8 +18,6 @@
|
|
|
18
18
|
|
|
19
19
|
goog.provide('ShakaDemoAssetInfo');
|
|
20
20
|
|
|
21
|
-
goog.require('goog.asserts');
|
|
22
|
-
|
|
23
21
|
|
|
24
22
|
/**
|
|
25
23
|
* An object that contains information about an asset.
|
|
@@ -127,9 +125,6 @@ const ShakaDemoAssetInfo = class {
|
|
|
127
125
|
* @return {!ShakaDemoAssetInfo}
|
|
128
126
|
*/
|
|
129
127
|
addFeature(feature) {
|
|
130
|
-
goog.asserts.assert(feature != shakaAssets.Feature.STORED,
|
|
131
|
-
'Assets should not be given the synthetic "STORED" ' +
|
|
132
|
-
'property!');
|
|
133
128
|
this.features.push(feature);
|
|
134
129
|
// Sort the features list, so that features are in a predictable order.
|
|
135
130
|
this.features.sort(ShakaDemoAssetInfo.caseLessAlphaComparator_);
|
|
@@ -141,7 +136,7 @@ const ShakaDemoAssetInfo = class {
|
|
|
141
136
|
* @return {!ShakaDemoAssetInfo}
|
|
142
137
|
*/
|
|
143
138
|
addKeySystem(keySystem) {
|
|
144
|
-
if (this.
|
|
139
|
+
if (this.isClear()) {
|
|
145
140
|
// Once an asset has an actual key system, it's no longer a CLEAR asset.
|
|
146
141
|
this.drm = [];
|
|
147
142
|
}
|
|
@@ -151,6 +146,11 @@ const ShakaDemoAssetInfo = class {
|
|
|
151
146
|
return this;
|
|
152
147
|
}
|
|
153
148
|
|
|
149
|
+
/** @return {boolean} */
|
|
150
|
+
isClear() {
|
|
151
|
+
return this.drm.length == 1 && this.drm[0] == shakaAssets.KeySystem.CLEAR;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
154
|
/**
|
|
155
155
|
* @param {!Object} extraConfig
|
|
156
156
|
* @return {!ShakaDemoAssetInfo}
|