rx-player 3.31.0-dev.2023052200 → 3.31.1-dev.2023062700

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 (27) hide show
  1. package/CHANGELOG.md +11 -3
  2. package/VERSION +1 -1
  3. package/dist/_esm5.processed/core/api/public_api.d.ts +32 -0
  4. package/dist/_esm5.processed/core/api/public_api.js +95 -4
  5. package/dist/_esm5.processed/core/api/utils.d.ts +10 -0
  6. package/dist/_esm5.processed/core/api/utils.js +20 -0
  7. package/dist/_esm5.processed/core/decrypt/session_events_listener.js +7 -1
  8. package/dist/_esm5.processed/core/init/directfile_content_initializer.d.ts +60 -1
  9. package/dist/_esm5.processed/core/init/directfile_content_initializer.js +51 -7
  10. package/dist/_esm5.processed/core/init/media_source_content_initializer.js +1 -1
  11. package/dist/_esm5.processed/core/init/types.d.ts +9 -1
  12. package/dist/_esm5.processed/core/init/utils/initialize_content_decryption.js +2 -2
  13. package/dist/_esm5.processed/core/stream/representation/utils/get_buffer_status.js +2 -1
  14. package/dist/rx-player.js +1083 -916
  15. package/dist/rx-player.min.js +1 -1
  16. package/package.json +31 -31
  17. package/scripts/build/generate_build.js +1 -1
  18. package/scripts/fast_demo_build.js +3 -2
  19. package/sonar-project.properties +1 -1
  20. package/src/core/api/public_api.ts +110 -4
  21. package/src/core/api/utils.ts +26 -0
  22. package/src/core/decrypt/session_events_listener.ts +6 -1
  23. package/src/core/init/directfile_content_initializer.ts +75 -15
  24. package/src/core/init/media_source_content_initializer.ts +1 -1
  25. package/src/core/init/types.ts +9 -1
  26. package/src/core/init/utils/initialize_content_decryption.ts +2 -2
  27. package/src/core/stream/representation/utils/get_buffer_status.ts +2 -1
package/CHANGELOG.md CHANGED
@@ -1,9 +1,19 @@
1
1
  # Changelog
2
2
 
3
- ## v3.31.0-dev.2023052200 (2023-05-22)
3
+ ## v3.31.1-dev.2023062700 (2023-06-27)
4
+
5
+ ### Other improvements
6
+
7
+ - Do not load the last text segment if the current position goes after it as it is unnecessary [#1256]
8
+ - Set a better error message for when no `keySystems` option is set when playing an encrypted content
9
+
10
+
11
+ ## v3.31.0 (2023-06-14)
4
12
 
5
13
  ### Features
6
14
 
15
+ - Add `isContentLoaded`, `isBuffering`, `isPaused`, and `getLastStoredContentPosition` methods [#1248]
16
+ - Add `play` and `paused` events [#1253]
7
17
  - Add `trackInfo` property to some `MediaError` to expose information on the track that caused the error [#1241]
8
18
 
9
19
  ### Bug fixes
@@ -12,13 +22,11 @@
12
22
  - Return actual ending duration through the `getVideoDuration` method when playing dynamic contents whose future end is already known [#1235]
13
23
  - DASH/WASM: actually reject the `DASH_WASM.initialize`'s Promise if it fails [#1238]
14
24
  - On the PlayStation 5, set `Infinity` MediaSource duration for live contents to prevent playback issues [#1250]
15
- - DASH/WASM: actually reject the DASH_WASM.initialize's Promise if it fails [#1238]
16
25
 
17
26
  ### Other improvements
18
27
 
19
28
  - adaptive: Perform various adaptive tweaks to avoid switching too much between qualities in some conditions [#1237]
20
29
  - Directfile: Detect "forced" subtitles on Safari when playing directfile contents (such as HLS) [#1239]
21
- - DRM: Reload when playback is unexpectedly frozen with encrypted but only decipherable data in the buffer [#1236]
22
30
  - Improve `"direct"` `audioTrackSwitchingMode` compatibility by re-seeking [#1246]
23
31
  - The `DEBUG_ELEMENT` feature now uses the `monospace` fallback font as a default for a better rendering on apple devices
24
32
  - doc: externalize documentation-generator code
package/VERSION CHANGED
@@ -1 +1 @@
1
- 3.31.0-dev.2023052200
1
+ 3.31.1-dev.2023062700
@@ -105,6 +105,10 @@ declare class Player extends EventEmitter<IPublicAPIEvent> {
105
105
  * It should refer to the last content being played.
106
106
  */
107
107
  private _priv_reloadingMetadata;
108
+ /**
109
+ * Store last value of autoPlay, from the last load or reload.
110
+ */
111
+ private _priv_lastAutoPlay;
108
112
  /** All possible Error types emitted by the RxPlayer. */
109
113
  static get ErrorTypes(): Record<IErrorType, IErrorType>;
110
114
  /** All possible Error codes emitted by the RxPlayer. */
@@ -217,6 +221,26 @@ declare class Player extends EventEmitter<IPublicAPIEvent> {
217
221
  * @returns {string} - The current Player's state
218
222
  */
219
223
  getPlayerState(): string;
224
+ /**
225
+ * Returns true if a content is loaded.
226
+ * @returns {Boolean} - `true` if a content is loaded, `false` otherwise.
227
+ */
228
+ isContentLoaded(): boolean;
229
+ /**
230
+ * Returns true if the player is buffering.
231
+ * @returns {Boolean} - `true` if the player is buffering, `false` otherwise.
232
+ */
233
+ isBuffering(): boolean;
234
+ /**
235
+ * Returns the play/pause status of the player :
236
+ * - when `LOADING` or `RELOADING`, returns the scheduled play/pause condition
237
+ * for when loading is over,
238
+ * - in other states, returns the `<video>` element .paused value,
239
+ * - if the player is disposed, returns `true`.
240
+ * @returns {Boolean} - `true` if the player is paused or will be after loading,
241
+ * `false` otherwise.
242
+ */
243
+ isPaused(): boolean;
220
244
  /**
221
245
  * Returns true if both:
222
246
  * - a content is loaded
@@ -303,6 +327,12 @@ declare class Player extends EventEmitter<IPublicAPIEvent> {
303
327
  * @returns {Number}
304
328
  */
305
329
  getPosition(): number;
330
+ /**
331
+ * Returns the last stored content position, in seconds.
332
+ *
333
+ * @returns {number|undefined}
334
+ */
335
+ getLastStoredContentPosition(): number | undefined;
306
336
  /**
307
337
  * Returns the current playback rate at which the video plays.
308
338
  * @returns {Number}
@@ -832,6 +862,8 @@ interface IPublicAPIEvent {
832
862
  availableTextTracksChange: IAvailableTextTrack[];
833
863
  availableVideoTracksChange: IAvailableVideoTrack[];
834
864
  decipherabilityUpdate: IDecipherabilityUpdateContent[];
865
+ play: null;
866
+ pause: null;
835
867
  seeking: null;
836
868
  seeked: null;
837
869
  streamEvent: IStreamEvent;
@@ -51,6 +51,7 @@ import { ErrorCodes, ErrorTypes, formatError, MediaError, } from "../../errors";
51
51
  import features from "../../features";
52
52
  import log from "../../log";
53
53
  import areArraysOfNumbersEqual from "../../utils/are_arrays_of_numbers_equal";
54
+ import arrayIncludes from "../../utils/array_includes";
54
55
  import assert from "../../utils/assert";
55
56
  import EventEmitter from "../../utils/event_emitter";
56
57
  import idGenerator from "../../utils/id_generator";
@@ -65,7 +66,7 @@ import MediaSourceContentInitializer from "../init/media_source_content_initiali
65
66
  import { checkReloadOptions, parseConstructorOptions, parseLoadVideoOptions, } from "./option_utils";
66
67
  import PlaybackObserver from "./playback_observer";
67
68
  import TrackChoiceManager from "./tracks_management/track_choice_manager";
68
- import { constructPlayerStateReference, emitSeekEvents, isLoadedState, } from "./utils";
69
+ import { constructPlayerStateReference, emitPlayPauseEvents, emitSeekEvents, isLoadedState, } from "./utils";
69
70
  /* eslint-disable @typescript-eslint/naming-convention */
70
71
  var generateContentId = idGenerator();
71
72
  var getPageActivityRef = events.getPageActivityRef, getPictureOnPictureStateRef = events.getPictureOnPictureStateRef, getVideoVisibilityRef = events.getVideoVisibilityRef, getVideoWidthRef = events.getVideoWidthRef, onFullscreenChange = events.onFullscreenChange, onTextTrackAdded = events.onTextTrackAdded, onTextTrackRemoved = events.onTextTrackRemoved;
@@ -89,7 +90,7 @@ var Player = /** @class */ (function (_super) {
89
90
  // Workaround to support Firefox autoplay on FF 42.
90
91
  // See: https://bugzilla.mozilla.org/show_bug.cgi?id=1194624
91
92
  videoElement.preload = "auto";
92
- _this.version = /* PLAYER_VERSION */ "3.31.0-dev.2023052200";
93
+ _this.version = /* PLAYER_VERSION */ "3.31.1-dev.2023062700";
93
94
  _this.log = log;
94
95
  _this.state = "STOPPED";
95
96
  _this.videoElement = videoElement;
@@ -172,6 +173,7 @@ var Player = /** @class */ (function (_super) {
172
173
  _this._priv_preferredTextTracks = preferredTextTracks;
173
174
  _this._priv_preferredVideoTracks = preferredVideoTracks;
174
175
  _this._priv_reloadingMetadata = {};
176
+ _this._priv_lastAutoPlay = false;
175
177
  return _this;
176
178
  }
177
179
  Object.defineProperty(Player, "ErrorTypes", {
@@ -269,6 +271,7 @@ var Player = /** @class */ (function (_super) {
269
271
  log.info("API: Calling loadvideo", options.url, options.transport);
270
272
  this._priv_reloadingMetadata = { options: options };
271
273
  this._priv_initializeContentPlayback(options);
274
+ this._priv_lastAutoPlay = options.autoPlay;
272
275
  };
273
276
  /**
274
277
  * Reload the last loaded content.
@@ -432,6 +435,9 @@ var Player = /** @class */ (function (_super) {
432
435
  this._priv_currentError = null;
433
436
  throw new Error("DirectFile feature not activated in your build.");
434
437
  }
438
+ else if (isNullOrUndefined(url)) {
439
+ throw new Error("No URL for a DirectFile content");
440
+ }
435
441
  mediaElementTrackChoiceManager =
436
442
  this._priv_initializeMediaElementTrackChoiceManager(defaultAudioTrack, defaultTextTrack, currentContentCanceller.signal);
437
443
  if (currentContentCanceller.isUsed()) {
@@ -485,11 +491,12 @@ var Player = /** @class */ (function (_super) {
485
491
  log.warn("API: Sending warning:", formattedError);
486
492
  _this.trigger("warning", formattedError);
487
493
  });
488
- initializer.addEventListener("reloadingMediaSource", function () {
494
+ initializer.addEventListener("reloadingMediaSource", function (payload) {
489
495
  contentInfos.segmentBuffersStore = null;
490
496
  if (contentInfos.trackChoiceManager !== null) {
491
497
  contentInfos.trackChoiceManager.resetPeriods();
492
498
  }
499
+ _this._priv_lastAutoPlay = payload.autoPlay;
493
500
  });
494
501
  initializer.addEventListener("inbandEvents", function (inbandEvents) {
495
502
  return _this.trigger("inbandEvents", inbandEvents);
@@ -591,6 +598,48 @@ var Player = /** @class */ (function (_super) {
591
598
  break;
592
599
  }
593
600
  };
601
+ /**
602
+ * `TaskCanceller` allowing to stop emitting `"play"` and `"pause"`
603
+ * events.
604
+ * `null` when such events are not emitted currently.
605
+ */
606
+ var playPauseEventsCanceller = null;
607
+ /**
608
+ * Callback emitting `"play"` and `"pause`" events once the content is
609
+ * loaded, starting from the state indicated in argument.
610
+ * @param {boolean} willAutoPlay - If `false`, we're currently paused.
611
+ */
612
+ var triggerPlayPauseEventsWhenReady = function (willAutoPlay) {
613
+ if (playPauseEventsCanceller !== null) {
614
+ playPauseEventsCanceller.cancel(); // cancel previous logic
615
+ playPauseEventsCanceller = null;
616
+ }
617
+ playerStateRef.onUpdate(function (val, stopListeningToStateUpdates) {
618
+ if (!isLoadedState(val)) {
619
+ return; // content not loaded yet: no event
620
+ }
621
+ stopListeningToStateUpdates();
622
+ if (playPauseEventsCanceller !== null) {
623
+ playPauseEventsCanceller.cancel();
624
+ }
625
+ playPauseEventsCanceller = new TaskCanceller();
626
+ playPauseEventsCanceller.linkToSignal(currentContentCanceller.signal);
627
+ if (willAutoPlay !== !videoElement.paused) {
628
+ // paused status is not at the expected value on load: emit event
629
+ if (videoElement.paused) {
630
+ _this.trigger("pause", null);
631
+ }
632
+ else {
633
+ _this.trigger("play", null);
634
+ }
635
+ }
636
+ emitPlayPauseEvents(videoElement, function () { return _this.trigger("play", null); }, function () { return _this.trigger("pause", null); }, currentContentCanceller.signal);
637
+ }, { emitCurrentValue: false, clearSignal: currentContentCanceller.signal });
638
+ };
639
+ triggerPlayPauseEventsWhenReady(autoPlay);
640
+ initializer.addEventListener("reloadingMediaSource", function (payload) {
641
+ triggerPlayPauseEventsWhenReady(payload.autoPlay);
642
+ });
594
643
  /**
595
644
  * `TaskCanceller` allowing to stop emitting `"seeking"` and `"seeked"`
596
645
  * events.
@@ -732,6 +781,40 @@ var Player = /** @class */ (function (_super) {
732
781
  Player.prototype.getPlayerState = function () {
733
782
  return this.state;
734
783
  };
784
+ /**
785
+ * Returns true if a content is loaded.
786
+ * @returns {Boolean} - `true` if a content is loaded, `false` otherwise.
787
+ */
788
+ Player.prototype.isContentLoaded = function () {
789
+ return !arrayIncludes(["LOADING", "RELOADING", "STOPPED"], this.state);
790
+ };
791
+ /**
792
+ * Returns true if the player is buffering.
793
+ * @returns {Boolean} - `true` if the player is buffering, `false` otherwise.
794
+ */
795
+ Player.prototype.isBuffering = function () {
796
+ return arrayIncludes(["BUFFERING", "SEEKING", "LOADING", "RELOADING"], this.state);
797
+ };
798
+ /**
799
+ * Returns the play/pause status of the player :
800
+ * - when `LOADING` or `RELOADING`, returns the scheduled play/pause condition
801
+ * for when loading is over,
802
+ * - in other states, returns the `<video>` element .paused value,
803
+ * - if the player is disposed, returns `true`.
804
+ * @returns {Boolean} - `true` if the player is paused or will be after loading,
805
+ * `false` otherwise.
806
+ */
807
+ Player.prototype.isPaused = function () {
808
+ if (this.videoElement) {
809
+ if (arrayIncludes(["LOADING", "RELOADING"], this.state)) {
810
+ return !this._priv_lastAutoPlay;
811
+ }
812
+ else {
813
+ return this.videoElement.paused;
814
+ }
815
+ }
816
+ return true;
817
+ };
735
818
  /**
736
819
  * Returns true if both:
737
820
  * - a content is loaded
@@ -897,6 +980,14 @@ var Player = /** @class */ (function (_super) {
897
980
  }
898
981
  return this.videoElement.currentTime;
899
982
  };
983
+ /**
984
+ * Returns the last stored content position, in seconds.
985
+ *
986
+ * @returns {number|undefined}
987
+ */
988
+ Player.prototype.getLastStoredContentPosition = function () {
989
+ return this._priv_reloadingMetadata.reloadPosition;
990
+ };
900
991
  /**
901
992
  * Returns the current playback rate at which the video plays.
902
993
  * @returns {Number}
@@ -2340,5 +2431,5 @@ var Player = /** @class */ (function (_super) {
2340
2431
  };
2341
2432
  return Player;
2342
2433
  }(EventEmitter));
2343
- Player.version = /* PLAYER_VERSION */ "3.31.0-dev.2023052200";
2434
+ Player.version = /* PLAYER_VERSION */ "3.31.1-dev.2023062700";
2344
2435
  export default Player;
@@ -30,6 +30,16 @@ import { IPlaybackObservation, IReadOnlyPlaybackObserver } from "./playback_obse
30
30
  * remove all listeners this function has registered.
31
31
  */
32
32
  export declare function emitSeekEvents(mediaElement: HTMLMediaElement | null, playbackObserver: IReadOnlyPlaybackObserver<IPlaybackObservation>, onSeeking: () => void, onSeeked: () => void, cancelSignal: CancellationSignal): void;
33
+ /**
34
+ * @param {HTMLMediaElement} mediaElement
35
+ * @param {function} onPlay - Callback called when a play operation has started
36
+ * on `mediaElement`.
37
+ * @param {function} onPause - Callback called when a pause operation has
38
+ * started on `mediaElement`.
39
+ * @param {Object} cancelSignal - When triggered, stop calling callbacks and
40
+ * remove all listeners this function has registered.
41
+ */
42
+ export declare function emitPlayPauseEvents(mediaElement: HTMLMediaElement | null, onPlay: () => void, onPause: () => void, cancelSignal: CancellationSignal): void;
33
43
  /** Player state dictionnary. */
34
44
  export declare const enum PLAYER_STATES {
35
45
  STOPPED = "STOPPED",
@@ -49,6 +49,26 @@ export function emitSeekEvents(mediaElement, playbackObserver, onSeeking, onSeek
49
49
  }
50
50
  }, { includeLastObservation: true, clearSignal: cancelSignal });
51
51
  }
52
+ /**
53
+ * @param {HTMLMediaElement} mediaElement
54
+ * @param {function} onPlay - Callback called when a play operation has started
55
+ * on `mediaElement`.
56
+ * @param {function} onPause - Callback called when a pause operation has
57
+ * started on `mediaElement`.
58
+ * @param {Object} cancelSignal - When triggered, stop calling callbacks and
59
+ * remove all listeners this function has registered.
60
+ */
61
+ export function emitPlayPauseEvents(mediaElement, onPlay, onPause, cancelSignal) {
62
+ if (cancelSignal.isCancelled() || mediaElement === null) {
63
+ return;
64
+ }
65
+ mediaElement.addEventListener("play", onPlay);
66
+ mediaElement.addEventListener("pause", onPause);
67
+ cancelSignal.register(function () {
68
+ mediaElement.removeEventListener("play", onPlay);
69
+ mediaElement.removeEventListener("pause", onPause);
70
+ });
71
+ }
52
72
  export function constructPlayerStateReference(initializer, mediaElement, playbackObserver, cancelSignal) {
53
73
  var playerStateRef = createSharedReference("LOADING" /* PLAYER_STATES.LOADING */, cancelSignal);
54
74
  initializer.addEventListener("loaded", function () {
@@ -130,7 +130,13 @@ export default function SessionEventsListener(session, keySystemOptions, keySyst
130
130
  log.info("DRM: No license given, skipping session.update");
131
131
  }
132
132
  else {
133
- return updateSessionWithMessage(session, licenseObject);
133
+ try {
134
+ return updateSessionWithMessage(session, licenseObject);
135
+ }
136
+ catch (err) {
137
+ manualCanceller.cancel();
138
+ callbacks.onError(err);
139
+ }
134
140
  }
135
141
  })
136
142
  .catch(function (err) {
@@ -18,21 +18,80 @@ import { IReadOnlySharedReference } from "../../utils/reference";
18
18
  import { PlaybackObserver } from "../api";
19
19
  import { ContentInitializer } from "./types";
20
20
  import { IInitialTimeOptions } from "./utils/get_initial_time";
21
+ /**
22
+ * `ContentIntializer` which will load contents by putting their URL in the
23
+ * `src` attribute of the given HTMLMediaElement.
24
+ *
25
+ * Because such contents are mainly loaded by the browser, those (called
26
+ * "directfile" contents in the RxPlayer) needs a simpler logic in-JS when
27
+ * compared to a content that relies on the MSE API.
28
+ *
29
+ * @class DirectFileContentInitializer
30
+ */
21
31
  export default class DirectFileContentInitializer extends ContentInitializer {
32
+ /**
33
+ * Initial options given to the `DirectFileContentInitializer`.
34
+ */
22
35
  private _settings;
36
+ /**
37
+ * Allows to abort and clean everything the `DirectFileContentInitializer` is
38
+ * doing.
39
+ */
23
40
  private _initCanceller;
41
+ /**
42
+ * Creates a new `DirectFileContentInitializer` linked to the given settings.
43
+ * @param {Object} settings
44
+ */
24
45
  constructor(settings: IDirectFileOptions);
46
+ /**
47
+ * "Prepare" content so it can later be played by calling `start`.
48
+ */
25
49
  prepare(): void;
50
+ /**
51
+ * Start playback of the content linked to this `DirectFileContentInitializer`
52
+ * on the given `HTMLMediaElement` and its associated `PlaybackObserver`.
53
+ * @param {HTMLMediaElement} mediaElement - HTMLMediaElement on which the
54
+ * content will be played.
55
+ * @param {Object} playbackObserver - Object regularly emitting playback
56
+ * information.
57
+ */
26
58
  start(mediaElement: HTMLMediaElement, playbackObserver: PlaybackObserver): void;
59
+ /**
60
+ * Update URL this `ContentIntializer` depends on.
61
+ * @param {Array.<string>|undefined} _urls
62
+ * @param {boolean} _refreshNow
63
+ */
27
64
  updateContentUrls(_urls: string[] | undefined, _refreshNow: boolean): void;
65
+ /**
66
+ * Stop content and free all resources linked to this `ContentIntializer`.
67
+ */
28
68
  dispose(): void;
69
+ /**
70
+ * Logic performed when a fatal error was triggered.
71
+ * @param {*} err - The fatal error in question.
72
+ */
29
73
  private _onFatalError;
74
+ /**
75
+ * Perform the initial seek (to begin playback at an initially-calculated
76
+ * position based on settings) and auto-play if needed when loaded.
77
+ * @param {HTMLMediaElement} mediaElement
78
+ * @param {Object} playbackObserver
79
+ */
30
80
  private _seekAndPlay;
31
81
  }
82
+ /** Options used by the `DirectFileContentInitializer` */
32
83
  export interface IDirectFileOptions {
84
+ /** If `true` we will play right after the content is considered "loaded". */
33
85
  autoPlay: boolean;
86
+ /**
87
+ * Encryption-related settings. Can be left as an empty array if the content
88
+ * isn't encrypted.
89
+ */
34
90
  keySystems: IKeySystemOption[];
91
+ /** Communicate the playback rate wanted by the user. */
35
92
  speed: IReadOnlySharedReference<number>;
93
+ /** Optional initial position to start at. */
36
94
  startAt?: IInitialTimeOptions | undefined;
37
- url?: string | undefined;
95
+ /** URL that should be played. */
96
+ url: string;
38
97
  }
@@ -34,6 +34,7 @@ var __extends = (this && this.__extends) || (function () {
34
34
  */
35
35
  import { clearElementSrc } from "../../compat";
36
36
  import log from "../../log";
37
+ import assert from "../../utils/assert";
37
38
  import createSharedReference from "../../utils/reference";
38
39
  import TaskCanceller from "../../utils/task_canceller";
39
40
  import { ContentInitializer } from "./types";
@@ -42,25 +43,51 @@ import performInitialSeekAndPlay from "./utils/initial_seek_and_play";
42
43
  import initializeContentDecryption from "./utils/initialize_content_decryption";
43
44
  import RebufferingController from "./utils/rebuffering_controller";
44
45
  import listenToMediaError from "./utils/throw_on_media_error";
46
+ /**
47
+ * `ContentIntializer` which will load contents by putting their URL in the
48
+ * `src` attribute of the given HTMLMediaElement.
49
+ *
50
+ * Because such contents are mainly loaded by the browser, those (called
51
+ * "directfile" contents in the RxPlayer) needs a simpler logic in-JS when
52
+ * compared to a content that relies on the MSE API.
53
+ *
54
+ * @class DirectFileContentInitializer
55
+ */
45
56
  var DirectFileContentInitializer = /** @class */ (function (_super) {
46
57
  __extends(DirectFileContentInitializer, _super);
58
+ /**
59
+ * Creates a new `DirectFileContentInitializer` linked to the given settings.
60
+ * @param {Object} settings
61
+ */
47
62
  function DirectFileContentInitializer(settings) {
48
63
  var _this = _super.call(this) || this;
49
64
  _this._settings = settings;
50
65
  _this._initCanceller = new TaskCanceller();
51
66
  return _this;
52
67
  }
68
+ /**
69
+ * "Prepare" content so it can later be played by calling `start`.
70
+ */
53
71
  DirectFileContentInitializer.prototype.prepare = function () {
54
72
  return; // Directfile contents do not have any preparation
55
73
  };
74
+ /**
75
+ * Start playback of the content linked to this `DirectFileContentInitializer`
76
+ * on the given `HTMLMediaElement` and its associated `PlaybackObserver`.
77
+ * @param {HTMLMediaElement} mediaElement - HTMLMediaElement on which the
78
+ * content will be played.
79
+ * @param {Object} playbackObserver - Object regularly emitting playback
80
+ * information.
81
+ */
56
82
  DirectFileContentInitializer.prototype.start = function (mediaElement, playbackObserver) {
57
83
  var _this = this;
58
84
  var cancelSignal = this._initCanceller.signal;
59
85
  var _a = this._settings, keySystems = _a.keySystems, speed = _a.speed, url = _a.url;
60
86
  clearElementSrc(mediaElement);
61
- if (url == null) {
62
- throw new Error("No URL for a DirectFile content");
63
- }
87
+ /**
88
+ * Create dummy encryption data emitter, as those are not sent from the
89
+ * RxPlayer for directfile contents.
90
+ */
64
91
  var decryptionRef = createSharedReference(null);
65
92
  decryptionRef.finish();
66
93
  var drmInitRef = initializeContentDecryption(mediaElement, keySystems, decryptionRef, {
@@ -89,7 +116,7 @@ var DirectFileContentInitializer = /** @class */ (function (_super) {
89
116
  rebufferingController.start();
90
117
  drmInitRef.onUpdate(function (evt, stopListeningToDrmUpdates) {
91
118
  if (evt.initializationState.type === "uninitialized") {
92
- return;
119
+ return; // nothing done yet
93
120
  }
94
121
  stopListeningToDrmUpdates();
95
122
  // Start everything! (Just put the URL in the element's src).
@@ -104,26 +131,43 @@ var DirectFileContentInitializer = /** @class */ (function (_super) {
104
131
  if (newDrmStatus.initializationState.type === "initialized") {
105
132
  stopListeningToDrmUpdatesAgain();
106
133
  _this._seekAndPlay(mediaElement, playbackObserver);
107
- return;
108
134
  }
109
135
  }, { emitCurrentValue: true, clearSignal: cancelSignal });
110
136
  }
111
137
  else {
138
+ assert(evt.initializationState.type === "initialized");
112
139
  _this._seekAndPlay(mediaElement, playbackObserver);
113
- return;
114
140
  }
115
141
  }, { emitCurrentValue: true, clearSignal: cancelSignal });
116
142
  };
143
+ /**
144
+ * Update URL this `ContentIntializer` depends on.
145
+ * @param {Array.<string>|undefined} _urls
146
+ * @param {boolean} _refreshNow
147
+ */
117
148
  DirectFileContentInitializer.prototype.updateContentUrls = function (_urls, _refreshNow) {
118
149
  throw new Error("Cannot update content URL of directfile contents");
119
150
  };
151
+ /**
152
+ * Stop content and free all resources linked to this `ContentIntializer`.
153
+ */
120
154
  DirectFileContentInitializer.prototype.dispose = function () {
121
155
  this._initCanceller.cancel();
122
156
  };
157
+ /**
158
+ * Logic performed when a fatal error was triggered.
159
+ * @param {*} err - The fatal error in question.
160
+ */
123
161
  DirectFileContentInitializer.prototype._onFatalError = function (err) {
124
162
  this._initCanceller.cancel();
125
163
  this.trigger("error", err);
126
164
  };
165
+ /**
166
+ * Perform the initial seek (to begin playback at an initially-calculated
167
+ * position based on settings) and auto-play if needed when loaded.
168
+ * @param {HTMLMediaElement} mediaElement
169
+ * @param {Object} playbackObserver
170
+ */
127
171
  DirectFileContentInitializer.prototype._seekAndPlay = function (mediaElement, playbackObserver) {
128
172
  var _this = this;
129
173
  var cancelSignal = this._initCanceller.signal;
@@ -156,7 +200,7 @@ export default DirectFileContentInitializer;
156
200
  /**
157
201
  * calculate initial time as a position in seconds.
158
202
  * @param {HTMLMediaElement} mediaElement
159
- * @param {Object|undefined} startAt
203
+ * @param {Object|undefined} [startAt]
160
204
  * @returns {number}
161
205
  */
162
206
  function getDirectFileInitialTime(mediaElement, startAt) {
@@ -249,7 +249,7 @@ var MediaSourceContentInitializer = /** @class */ (function (_super) {
249
249
  if (initCanceller.isUsed()) {
250
250
  return;
251
251
  }
252
- triggerEvent("reloadingMediaSource", null);
252
+ triggerEvent("reloadingMediaSource", reloadOrder);
253
253
  if (initCanceller.isUsed()) {
254
254
  return;
255
255
  }
@@ -95,7 +95,15 @@ export interface IContentInitializerEvents {
95
95
  * Event sent when we're starting attach a new MediaSource to the media element
96
96
  * (after removing the previous one).
97
97
  */
98
- reloadingMediaSource: null;
98
+ reloadingMediaSource: {
99
+ /** The position we're reloading at, in seconds. */
100
+ position: number;
101
+ /**
102
+ * If `true`, we'll play directly after finishing the reloading operation.
103
+ * If `false`, we'll be paused after it.
104
+ */
105
+ autoPlay: boolean;
106
+ };
99
107
  /** Event sent after the player stalled. */
100
108
  stalled: IStallingSituation;
101
109
  /** Event sent when the player goes out of a stalling situation. */
@@ -34,8 +34,8 @@ export default function initializeContentDecryption(mediaElement, keySystems, pr
34
34
  return;
35
35
  }
36
36
  stopListening();
37
- log.error("Init: Encrypted event but EME feature not activated");
38
- var err = new EncryptedMediaError("MEDIA_IS_ENCRYPTED_ERROR", "EME feature not activated.");
37
+ log.error("Init: Encrypted event but no `keySystems` given");
38
+ var err = new EncryptedMediaError("MEDIA_IS_ENCRYPTED_ERROR", "no `keySystems` given.");
39
39
  callbacks.onError(err);
40
40
  }, { clearSignal: cancelSignal });
41
41
  var ref = createSharedReference({
@@ -15,7 +15,7 @@
15
15
  */
16
16
  import config from "../../../../config";
17
17
  import isNullOrUndefined from "../../../../utils/is_null_or_undefined";
18
- import { SegmentBufferOperation, } from "../../../segment_buffers";
18
+ import SegmentBuffersStore, { SegmentBufferOperation, } from "../../../segment_buffers";
19
19
  import checkForDiscontinuity from "./check_for_discontinuity";
20
20
  import getNeededSegments from "./get_needed_segments";
21
21
  import getSegmentPriority from "./get_segment_priority";
@@ -116,6 +116,7 @@ function getRangeOfNeededSegments(content, initialWantedTime, bufferGoal) {
116
116
  // avoid ending the last Period - and by extension the content - with a
117
117
  // segment which isn't the last one.
118
118
  if (!isNullOrUndefined(lastIndexPosition) &&
119
+ SegmentBuffersStore.isNative(content.adaptation.type) &&
119
120
  initialWantedTime >= lastIndexPosition &&
120
121
  representationIndex.isInitialized() &&
121
122
  representationIndex.isFinished() &&