blob: 22fd2ad6271fbd689098e4f03d9ae1276ee2d97f [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2009, 2015 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
//
// Ad-hoc codes to bridge the gap between the HTML5 spec and browser implementations
//
if (true) { // if (typeof TextTrack == 'undefined') { // As of Mar 2015, no major browser sufficiently supports TextTrack.
(function () {
TextTrack = function (kind, label, language) { // See: http://www.w3.org/TR/html5/embedded-content-0.html#texttrack
this.kind = kind;
this.label = label;
this.language = language;
this.mode = TextTrack.HIDDEN;
this.cues = new TextTrackCueList();
this.activeCues = new TextTrackCueList();
};
TextTrack.DISABLED = 0;
TextTrack.HIDDEN = 1;
TextTrack.SHOWING = 2;
TextTrack.prototype.addCue = function (cue) {
cue.track = cue.__track__ = this;
this.cues.__addCue__(cue);
};
TextTrack.prototype.removeCue = function (cue) {
cue.track = cue.__track__ = null;
this.cues.__removeCue__(cue);
};
TextTrack.prototype.toString = function () {
return 'TextTrack <' + this.kind + '> ' + this.label + ' (' + this.language + ') : ' + this.cues;
};
TextTrackList = function () { // See: http://www.w3.org/TR/html5/embedded-content-0.html#texttracklist
var list = [];
list.getTrackById = function (id) {
for (var i = 0; i < this.length; ++i) {
var e = this[i];
if (e.id == id) {
return e;
}
}
return null;
};
list.toString = function () {
return 'TextTrackList [\n\t' + this.join(',\n\t') + '\n]';
};
return list;
};
TextTrackCue = function (startTime, endTime, text) { // See: http://www.w3.org/TR/html5/embedded-content-0.html#texttrackcue
if (typeof VTTCue != 'undefined') {
return new VTTCue(startTime, endTime, text);
}
else {
this.startTime = startTime;
this.endTime = endTime;
this.text = text;
}
};
TextTrackCue.prototype.toString = function () {
return 'TextTrackCue <' + this.id + '> ' + this.startTime + ' -> ' + this.endTime + ' : ' + this.text + (this.pauseOnExit ? ' * pause-on-exit * ' : ' ');
};
TextTrackCueList = function () { // See: http://www.w3.org/TR/html5/embedded-content-0.html#texttrackcuelist
var list = [];
list.getCueById = function (id) {
for (var i = 0; i < this.length; ++i) {
var e = this[i];
if (e.id == id) {
return e;
}
}
return null;
};
list.__addCue__ = function (cue) {
this.push(cue);
};
list.__removeCue__ = function (cue) {
for (var i = 0; i < this.length; ++i) {
if (this[i] === cue) {
this.splice(i--, 1);
}
}
};
list.toString = function () {
return 'TextTrackCueList [\n\t' + this.join(',\n\t') + '\n]';
};
return list;
};
var fixMediaElement = function (m) {
m.textTracks = m.__textTracks__ = new TextTrackList();
m.addTextTrack = m.__addTextTrack__ = addTextTrack;
m.__lastTime__ = m.currentTime;
m.addEventListener('timeupdate', updateCues, false);
m.addEventListener('seeked', updateCues, false);
};
var fixTrackElement = function (t) {
t.kind = t.getAttribute('kind');
t.src = t.getAttribute('src');
t.srclang = t.getAttribute('srclang');
t.label = t.getAttribute('label');
t['default'] = t.getAttribute('default') != null; // .default causes an error in IE
if (!t.dataset) {
var d = {};
var a = t.attributes;
for (var i = 0; i < a.length; ++i) {
if (a[i].name.indexOf('data-') == 0) {
d[a[i].name.substr(5)] = a[i].value;
}
}
t.dataset = d;
}
};
var addTextTrack = function (kind, label, language) { // HTMLMediaElement#addTextTrack
var t = new TextTrack(kind, label, language);
this.__textTracks__.push(t);
return t;
};
var updateCues = function (e) { // http://dev.w3.org/html5/spec/media-elements.html#media-playback
var video = e.target;
var currentTime = video.currentTime;
var lastTime = video.__lastTime__; video.__lastTime__ = currentTime;
var isMonotonicIncrease = currentTime > lastTime && currentTime <= lastTime + .5; // major browsers fire timeupdate events every 250 ms
var currentCues = [];
var otherCues = [];
var conflicted = false;
var tracks = video.__textTracks__;
for (var i = 0; i < tracks.length; ++i) {
var t = tracks[i];
if (t.mode != TextTrack.DISABLED) {
var cues = t.cues;
for (var j = 0; j < cues.length; ++j) {
var c = cues[j];
if (c.startTime <= currentTime && c.endTime > currentTime) {
currentCues.push(c);
c.__missed__ = false;
conflicted = conflicted || !c.__active__;
}
else {
otherCues.push(c);
c.__missed__ = isMonotonicIncrease && c.startTime >= lastTime && c.endTime <= currentTime;
conflicted = conflicted || c.__active__ || c.__missed__;
}
}
}
}
if (!conflicted) {
return;
}
var events = [];
for (var i = 0; i < otherCues.length; ++i) {
var c = otherCues[i];
if (c.pauseOnExit && (c.__active__ || c.__missed__)) {
video.pause();
}
if (c.__missed__) {
events.push({ type: 'enter', timeStamp: c.startTime, target: c });
}
if (c.__active__ || c.__missed__) {
events.push({ type: 'exit', timeStamp: c.endTime, target: c });
}
c.__active__ = false;
c.__track__.activeCues.__removeCue__(c);
}
for (var i = 0; i < currentCues.length; ++i) {
var c = currentCues[i];
if (!c.__active__) {
events.push({ type: 'enter', timeStamp: c.startTime, target: c });
}
c.__active__ = true;
c.__track__.activeCues.__addCue__(c);
}
events.sort(function (a, b) { return a.timeStamp - b.timeStamp });
for (var i = 0; i < events.length; ++i) {
var e = events[i];
var f = e.target['on' + e.type];
if (f) {
f.call(e.target, e);
}
}
};
var videoElems = document.getElementsByTagName('video');
for (var i = 0; i < videoElems.length; ++i) {
fixMediaElement(videoElems[i]);
}
var audioElems = document.getElementsByTagName('audio');
for (var i = 0; i < audioElems.length; ++i) {
fixMediaElement(audioElems[i]);
}
var trackElems = document.getElementsByTagName('track');
for (var i = 0; i < trackElems.length; ++i) {
var t = trackElems[i];
fixTrackElement(t);
t.track = t.__track__ = t.parentNode.__addTextTrack__(t.kind, t.label, t.srclang);
}
})();
}
if (true) { // if (typeof MediaController == 'undefined') { // As of Mar 2015, no major browser sufficiently supports MediaController.
(function () {
MediaController = function () {}; // See: http://www.w3.org/TR/html5/embedded-content-0.html#mediacontroller
MediaController.prototype.__syncTime__ = function (kicker) {
if (kicker.__seekedForSync__) {
kicker.__seekedForSync__ = false;
return;
}
var slaveElems = getSlaveElementsOf(this);
var currentTime = kicker.currentTime;
for (var i = 0; i < slaveElems.length; ++i) {
var s = slaveElems[i];
if (s !== kicker) {
s.__seekedForSync__ = true;
s.currentTime = currentTime;
}
}
};
MediaController.prototype.__syncPlayback__ = function (kicker) {
var slaveElems = getSlaveElementsOf(this);
var readyState = 0;
var paused = false;
for (var i = 0; i < slaveElems.length; ++i) {
var s = slaveElems[i];
readyState = Math.max(readyState, s.readyState);
paused = paused || s.ended || (s.paused && !s.__pausedForSync__);
}
this.readyState = readyState;
this.paused = paused || readyState < 4; // < HAVE_ENOUGH_DATA
for (var i = 0; i < slaveElems.length; ++i) {
var s = slaveElems[i];
if (this.paused) {
if (!s.paused) {
s.__pausedForSync__ = true;
s.pause();
}
else {
}
}
else {
if (s.paused) {
s.__pausedForSync__ = false;
s.play();
}
else {
s.__pausedForSync__ = false;
}
}
}
};
var getSlaveElementsOf = function (controller) {
var videoElems = document.getElementsByTagName('video');
var audioElems = document.getElementsByTagName('audio');
var slaveElems = [];
for (var i = 0; i < videoElems.length; ++i) {
var v = videoElems[i];
if (v.controller === controller) {
slaveElems.push(v);
}
}
for (var i = 0; i < audioElems.length; ++i) {
var a = audioElems[i];
if (a.controller === controller) {
slaveElems.push(a);
}
}
return slaveElems;
};
var controllers = {};
var fixMediaElement = function (m) {
m.mediaGroup = m.getAttribute('mediagroup');
if (!m.mediaGroup) {
return;
}
m.controller = controllers[m.mediaGroup] || (controllers[m.mediaGroup] = new MediaController());
m.addEventListener('seeked', syncTime, false);
m.addEventListener('seeked', syncPlayback, false);
m.addEventListener('playing', syncPlayback, false);
m.addEventListener('waiting', syncPlayback, false);
m.addEventListener('pause', syncPlayback, false);
m.addEventListener('ended', syncPlayback, false);
m.__pausedForSync__ = true;
};
var syncTime = function (e) {
e.target.controller.__syncTime__(e.target);
};
var syncPlayback = function (e) {
e.target.controller.__syncPlayback__(e.target);
};
var videoElems = document.getElementsByTagName('video');
for (var i = 0; i < videoElems.length; ++i) {
fixMediaElement(videoElems[i]);
}
var audioElems = document.getElementsByTagName('audio');
for (var i = 0; i < audioElems.length; ++i) {
fixMediaElement(audioElems[i]);
}
})();
}