rx-player
Version:
Canal+ HTML5 Video Player
180 lines (179 loc) • 7.97 kB
JavaScript
;
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
var manifest_1 = require("../../manifest");
var array_includes_1 = require("../../utils/array_includes");
var event_emitter_1 = require("../../utils/event_emitter");
var noop_1 = require("../../utils/noop");
var reference_1 = require("../../utils/reference");
var task_canceller_1 = require("../../utils/task_canceller");
/**
* Class handling track changes and quality locking for a single Period and
* Adaptation type.
* @class TrackDispatcher
*/
var TrackDispatcher = /** @class */ (function (_super) {
__extends(TrackDispatcher, _super);
/**
* Create a new `TrackDispatcher` by giving its Reference and an initial track
* setting.
* This constructor will update the Reference with the right preferences
* synchronously.
* @param {Object} adaptationRef
*/
function TrackDispatcher(adaptationRef) {
var _this = _super.call(this) || this;
_this._canceller = new task_canceller_1.default("TrackDispatcher initial");
_this._adaptationRef = adaptationRef;
_this._updateToken = false;
_this._lastEmitted = undefined;
_this.refresh = noop_1.default;
return _this;
}
/**
* Returns `true` if the initial track choice has been sent by this
* `TrackDispatcher`.
* Returns `false` if that's not the case yet.
* @returns {boolean}
*/
TrackDispatcher.prototype.hasSetTrack = function () {
return this._adaptationRef.getValue() !== undefined;
};
/**
* Update the wanted track on the Reference linked to this `TrackDispatcher`.
* @param {Object|null} newTrackInfo
*/
TrackDispatcher.prototype.updateTrack = function (newTrackInfo) {
this._updateToken = true;
if (newTrackInfo === null) {
if (this._lastEmitted === null) {
return;
}
this._updateToken = false;
this._canceller.cancel("track update null");
// has no point but let's still create one for simplicity sake
this._canceller = new task_canceller_1.default("TrackDispatcher null");
this._lastEmitted = null;
this._adaptationRef.setValue(null);
return;
}
var adaptation = newTrackInfo.adaptation, switchingMode = newTrackInfo.switchingMode, relativeResumingPosition = newTrackInfo.relativeResumingPosition;
this._canceller.cancel("track update");
this._canceller = new task_canceller_1.default("TrackDispatcher " + adaptation.type);
var reference = this._constructLockedRepresentationsReference(newTrackInfo);
if (!this._updateToken) {
return;
}
this._lastEmitted = {
adaptation: adaptation,
switchingMode: switchingMode,
lockedRepresentations: null,
};
this._updateToken = false;
this._adaptationRef.setValue({
adaptationId: adaptation.id,
switchingMode: switchingMode,
representations: reference,
relativeResumingPosition: relativeResumingPosition,
});
};
/**
* Create a shared reference which will emit the wanted locked Representations
* based on the current capabilities and the last user settings.
*
* @param {Object} trackInfo
* @returns {Object}
*/
TrackDispatcher.prototype._constructLockedRepresentationsReference = function (trackInfo) {
/* Initialize it. Will be at its true value at the end of the function. */
var reference = new reference_1.default({
representationIds: [],
switchingMode: "lazy",
});
// eslint-disable-next-line @typescript-eslint/no-this-alias
var self = this;
this.refresh = updateReferenceIfNeeded;
this._canceller.signal.register(removeListeners);
trackInfo.lockedRepresentations.onUpdate(updateReferenceIfNeeded, {
clearSignal: this._canceller.signal,
emitCurrentValue: false,
});
updateReferenceIfNeeded();
return reference;
function updateReferenceIfNeeded() {
var repSettings = trackInfo.lockedRepresentations.getValue();
var switchingMode;
/** Representations for which a `RepresentationStream` can be created. */
var playableRepresentations;
if (repSettings === null) {
// unlocking
playableRepresentations = trackInfo.adaptation.representations.filter(function (representation) { return (0, manifest_1.isRepresentationPlayable)(representation) === true; });
// No need to remove the previous content when unlocking
switchingMode = "lazy";
}
else {
var representationIds_1 = repSettings.representationIds;
switchingMode = repSettings.switchingMode;
var representations = trackInfo.adaptation.representations.filter(function (r) {
return (0, array_includes_1.default)(representationIds_1, r.id);
});
playableRepresentations = representations.filter(function (representation) { return (0, manifest_1.isRepresentationPlayable)(representation) === true; });
if (playableRepresentations.length === 0) {
self.trigger("noPlayableLockedRepresentation", null);
return;
}
}
if (playableRepresentations.length <= 0) {
self.trigger("noPlayableRepresentation", null);
return;
}
// Check if Locked Representations have changed
var oldRef = reference.getValue();
var sortedReps = playableRepresentations
.map(function (r) { return r.id; })
.slice()
.sort();
if (sortedReps.length !== oldRef.representationIds.length) {
reference.setValue({ representationIds: sortedReps, switchingMode: switchingMode });
return;
}
for (var i = 0; i < sortedReps.length; i++) {
if (oldRef.representationIds[i] !== sortedReps[i]) {
reference.setValue({ representationIds: sortedReps, switchingMode: switchingMode });
return;
}
}
}
function removeListeners() {
self.refresh = noop_1.default;
}
};
/**
* Free the resources (e.g. `Manifest` event listeners) linked to this
* `TrackDispatcher`.
* @param {string | undefined} reason - Human-inspectable reason behind the
* dispose. Used for debugging matters, especially for debug log
* inspection.
*/
TrackDispatcher.prototype.dispose = function (reason) {
this.removeEventListener();
this._canceller.cancel(reason !== null && reason !== void 0 ? reason : "TrackDispatcher dispose");
this._adaptationRef.finish();
};
return TrackDispatcher;
}(event_emitter_1.default));
exports.default = TrackDispatcher;