rx-player
Version:
Canal+ HTML5 Video Player
511 lines (510 loc) • 20 kB
JavaScript
"use strict";
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var __values = (this && this.__values) || function(o) {
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
if (m) return m.call(o);
if (o && typeof o.length === "number") return {
next: function () {
if (o && i >= o.length) o = void 0;
return { value: o && o[i++], done: !o };
}
};
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.EventScheduler = void 0;
var ranges_1 = require("../../../utils/ranges");
var EventScheduler = /** @class */ (function () {
function EventScheduler() {
this._scheduled = [];
}
EventScheduler.prototype.schedule = function (obj, evtName, cancelSignal) {
var _this = this;
return new Promise(function (res, rej) {
/* eslint-disable */
_this._scheduled.push({
resolve: res,
reject: rej,
obj: obj,
evtName: evtName,
cancelSignal: cancelSignal !== null && cancelSignal !== void 0 ? cancelSignal : null,
});
/* eslint-enable */
if (_this._scheduled.length === 1) {
_this._start();
}
});
};
EventScheduler.prototype._start = function () {
var _this = this;
var _a;
var elt = this._scheduled[0];
if (elt === undefined) {
return;
}
/* eslint-disable */
var timeout;
timeout = setTimeout(function () {
var evtName = elt.evtName, obj = elt.obj;
timeout = null;
var event = new Event(evtName);
var handlerFnName = "on".concat(evtName);
if (obj[handlerFnName] !== null) {
try {
obj[handlerFnName](event);
}
catch (e) {
// nothing
}
}
timeout = setTimeout(function () {
timeout = null;
obj.trigger(evtName, event);
var index = _this._scheduled.indexOf(elt);
if (index >= 0) {
_this._scheduled.splice(index, 1);
}
elt.resolve();
_this._start();
}, 0);
}, 0);
/* eslint-enable */
(_a = elt.cancelSignal) === null || _a === void 0 ? void 0 : _a.register(function (err) {
if (timeout !== null) {
clearTimeout(timeout);
timeout = null;
}
var index = _this._scheduled.indexOf(elt);
if (index >= 0) {
_this._scheduled.splice(index, 1);
}
elt.reject(err);
_this._start();
});
};
return EventScheduler;
}());
exports.EventScheduler = EventScheduler;
/**
* Simulate TimeRanges as returned by SourceBuffer.prototype.buffered.
* Add an "insert" and "remove" methods to manually update it.
* @class TimeRangesWithMetadata
*/
var TimeRangesWithMetadata = /** @class */ (function () {
function TimeRangesWithMetadata() {
this._ranges = [];
this._rangesWithMetadata = [];
this.length = 0;
}
TimeRangesWithMetadata.prototype.insert = function (start, end, info) {
(0, ranges_1.insertInto)(this._ranges, { start: start, end: end });
this.length = this._ranges.length;
insertToMetadataRanges(this._rangesWithMetadata, { start: start, end: end, info: info });
};
TimeRangesWithMetadata.prototype.getMetadataFor = function (time) {
var e_1, _a;
try {
for (var _b = __values(this._rangesWithMetadata), _c = _b.next(); !_c.done; _c = _b.next()) {
var element = _c.value;
if (element.start <= time && element.end > time) {
return element.info;
}
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
}
finally { if (e_1) throw e_1.error; }
}
return null;
};
TimeRangesWithMetadata.prototype.getRangeFor = function (time) {
var e_2, _a;
try {
for (var _b = __values(this._rangesWithMetadata), _c = _b.next(); !_c.done; _c = _b.next()) {
var element = _c.value;
if (element.start <= time && element.end > time) {
return { start: element.start, end: element.end };
}
}
}
catch (e_2_1) { e_2 = { error: e_2_1 }; }
finally {
try {
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
}
finally { if (e_2) throw e_2.error; }
}
return null;
};
TimeRangesWithMetadata.prototype.remove = function (start, end) {
var rangesToIntersect = [];
if (start > 0) {
rangesToIntersect.push({ start: 0, end: start });
}
if (end < Infinity) {
rangesToIntersect.push({ start: end, end: Infinity });
}
this._ranges = (0, ranges_1.keepRangeIntersection)(this._ranges, rangesToIntersect);
this.length = this._ranges.length;
for (var i = 0; i < this._rangesWithMetadata.length; i++) {
var element = this._rangesWithMetadata[i];
if (element.end > start) {
if (element.start >= end) {
// Our element is after:
//
// Case 1:
// element : |=======|
// removing : |====|
//
// Case 2:
// element : |=======|
// removing : |====|
return;
}
if (element.end <= end) {
if (element.start >= start) {
// Our element is totally included:
//
// Case 1:
// element : |=======|
// removing : |=======|
//
// Case 2:
// element : |=======|
// removing : |=========|
//
// Case 3:
// element : |=======|
// removing : |=========|
//
// Case 4:
// element : |=======|
// removing : |========|
this._rangesWithMetadata.splice(i, 1);
i--;
}
else {
// Our element starts before:
//
// Case 1:
// element : |=======|
// removing : |=====|
// result : |=|
//
// Case 2:
// element : |=======|
// removing : |=====|
// result : |===|
element.end = start;
}
}
else if (element.start >= start) {
// Our element just ends after
//
// Case 1:
// element : |==========|
// removing : |=======|
// result : |====|
//
// Case 2:
// element : |============|
// removing : |=========|
// result : |==|
element.start = end;
return;
}
else {
// Case 1:
// element : |=============|
// removing : |====|
// result : |===| |====|
var oldEnd = element.end;
element.end = start;
var nextElement = {
start: end,
end: oldEnd,
info: element.info,
};
this._rangesWithMetadata.splice(i + 1, 0, nextElement);
return;
}
}
}
};
TimeRangesWithMetadata.prototype.start = function (index) {
if (index >= this._ranges.length) {
throw new Error("INDEX_SIZE_ERROR");
}
return this._ranges[index].start;
};
TimeRangesWithMetadata.prototype.end = function (index) {
if (index >= this._ranges.length) {
throw new Error("INDEX_SIZE_ERROR");
}
return this._ranges[index].end;
};
return TimeRangesWithMetadata;
}());
exports.default = TimeRangesWithMetadata;
function insertToMetadataRanges(ranges, element) {
var start = element.start, end = element.end;
if (start >= end) {
return;
}
// begin by the end as in most use cases this will be faster
for (var i = ranges.length - 1; i >= 0; i--) {
var elementI = ranges[i];
if (elementI.start <= start) {
if (elementI.end <= start) {
// our element is after, push it after this one
//
// Case 1:
// prevElement : |------|
// element : |======|
// ===> : |------|======|
//
// Case 2:
// prevElement : |------|
// element : |======|
// ===> : |------| |======|
ranges.splice(i + 1, 0, __assign({}, element));
i += 2; // Go to element immediately after element
while (i < ranges.length && ranges[i].start < element.end) {
if (ranges[i].end > element.end) {
ranges[i].start = element.end;
return;
}
// The next element was completely contained in element.
// Remove it.
//
// Case 1:
// prevElement : |------|
// element : |======|
// nextElement : |---|
// ===> : |------|======|
//
// Case 2:
// prevElement : |------|
// element : |======|
// nextElement : |----|
// ===> : |------|======|
ranges.splice(i, 1);
}
return;
}
else {
if (elementI.start === start) {
if (elementI.end <= end) {
// In those cases, replace
//
// Case 1:
// prevElement : |-------|
// element : |=======|
// ===> : |=======|
//
// Case 2:
// prevElement : |-------|
// element : |==========|
// ===> : |==========|
ranges.splice(i, 1, element);
i += 1; // Go to element immediately after element
while (i < ranges.length && ranges[i].start < element.end) {
if (ranges[i].end > element.end) {
// The next element ends after element.
// Mutate the next element.
//
// Case 1:
// element : |======|
// nextElement : |----|
// ===> : |======|--|
ranges[i].start = element.end;
return;
}
// The next element was completely contained in element.
// Remove it.
//
// Case 1:
// element : |======|
// nextElement : |---|
// ===> : |======|
//
// Case 2:
// element : |======|
// nextElement : |----|
// ===> : |======|
ranges.splice(i, 1);
}
return;
}
else {
// The previous element starts at the same time and finishes
// after the new element.
// Update the start of the previous element and put the new
// element before.
//
// Case 1:
// prevElement : |------------|
// element : |==========|
// ===> : |==========|-|
ranges.splice(i, 0, element);
elementI.start = element.end;
return;
}
}
else {
if (elementI.end <= element.end) {
// our element has a "complex" relation with this one,
// update the old one end and add this one after it.
//
// Case 1:
// prevElement : |-------|
// element : |======|
// ===> : |--|======|
//
// Case 2:
// prevElement : |-------|
// element : |====|
// ===> : |--|====|
ranges.splice(i + 1, 0, element);
elementI.end = element.start;
i += 2; // Go to element immediately after element
while (i < ranges.length && ranges[i].start < element.end) {
if (ranges[i].end > element.end) {
// The next element ends after element.
// Mutate the next element.
//
// Case 1:
// element : |======|
// nextElement : |----|
// ===> : |======|--|
ranges[i].start = element.end;
return;
}
// The next element was completely contained in element.
// Remove it.
//
// Case 1:
// element : |======|
// nextElement : |---|
// ===> : |======|
//
// Case 2:
// element : |======|
// nextElement : |----|
// ===> : |======|
ranges.splice(i, 1);
}
return;
}
else {
// The previous element completely recovers the new element.
// Split the previous element into two elements, before and after
// the new element.
//
// Case 1:
// prevElement : |---------|
// element : |====|
// ===> : |--|====|-|
var nextElement = {
start: element.end,
end: elementI.end,
info: elementI.info,
};
elementI.end = element.start;
ranges.splice(i + 1, 0, element);
ranges.splice(i + 2, 0, nextElement);
return;
}
}
}
}
}
// if we got here, we are at the first element
// check bounds of the previous first element
var firstElement = ranges[0];
if (firstElement === undefined) {
// we do not have any element yet
ranges.push(element);
return;
}
if (firstElement.start >= end) {
// our element is before, put it before
//
// Case 1:
// firstElement : |----|
// element : |====|
// ===> : |====|----|
//
// Case 2:
// firstElement : |----|
// element : |====|
// ===> : |====| |----|
ranges.splice(0, 0, element);
}
else if (firstElement.end <= end) {
// Our segment is bigger, replace the first
//
// Case 1:
// firstElement : |---|
// element : |=======|
// ===> : |=======|
//
// Case 2:
// firstElement : |-----|
// element : |=======|
// ===> : |=======|
ranges.splice(0, 1, element);
while (ranges.length > 1 && ranges[1].start < element.end) {
if (ranges[1].end > element.end) {
// The next segment ends after element.
// Mutate the next segment.
//
// Case 1:
// element : |======|
// nextElement : |----|
// ===> : |======|--|
ranges[1].start = element.end;
return;
}
// The next segment was completely contained in element.
// Remove it.
//
// Case 1:
// element : |======|
// nextElement : |---|
// ===> : |======|
//
// Case 2:
// element : |======|
// nextElement : |----|
// ===> : |======|
ranges.splice(1, 1);
}
return;
}
else {
// our segment has a "complex" relation with the first one,
// update the old one start and add this one before it.
//
// Case 1:
// firstElement : |------|
// element : |======|
// ===> : |======|--|
firstElement.start = end;
ranges.splice(0, 0, element);
return;
}
}