Created
April 2, 2018 15:00
-
-
Save indatawetrust/9713eeffb22758c482d916d7b7210300 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/**-------------------------------------------------------------------------------- | |
* | |
* Copyright (c) 2016, Samsung Electronics Co., Ltd | |
* | |
* Permission is hereby granted, free of charge, to any person obtaining a copy | |
* of this software and associated documentation files (the "Software"), to deal | |
* in the Software without restriction, including without limitation the rights | |
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
* copies of the Software, and to permit persons to whom the Software is | |
* furnished to do so, subject to the following conditions: | |
* | |
* The above copyright notice and this permission notice shall be included in | |
* all copies or substantial portions of the Software. | |
* | |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |
* THE SOFTWARE. | |
* | |
--------------------------------------------------------------------------------*/ | |
controls = { | |
/** | |
* config options for player controls customization | |
*/ | |
config: { | |
/** | |
* after this time controls will hide automatically, in milliseconds | |
*/ | |
visibilityTime: 5000, | |
language: { | |
/** | |
* default language values | |
* if some language has own translations it will be overwritten with language specific word | |
*/ | |
defaultLang: { | |
errormessage: "Error encountered during content playback. Press OK to return", | |
ok: "OK" | |
}, | |
en: {}, | |
us: {} | |
}, | |
/** | |
* time for progressBar refresh, in milliseconds | |
*/ | |
progressBarRefreshTime: 500, | |
/** | |
* custom speed values for e.g. fastForward x2, x4, x8 | |
* speeds are used toggled while pressing e.g. fastForward button | |
*/ | |
speed: { | |
rewind: [-1, -2, -4], | |
slowRewind: [-0.25, -0.5, -0.75], | |
slowPlay: [0.25, 0.5, 0.75], | |
fastForward: [2, 4, 8] | |
}, | |
/** | |
* current used UI language | |
*/ | |
uiLanguage: 'en' | |
}, | |
/** | |
* method returns translated text with use of language declared in controls.config.uiLanguage or with default language | |
* @param word | |
* @returns {*} | |
*/ | |
getLang: function (word) { | |
return controls.config.language[controls.config.uiLanguage][word.toLowerCase()] || controls.config.language.defaultLang[word.toLowerCase()] || word; | |
}, | |
/** | |
* player controls DOM | |
*/ | |
DOM: null, | |
/** | |
* player controls DOM children | |
*/ | |
DOMElement: {}, | |
/** | |
* keySet used to control player and player controls | |
*/ | |
keySet: null, | |
/** | |
* timer for auto hiding controls panel | |
*/ | |
autoHideTimer: null, | |
/** | |
* flag, informs is it player first run | |
*/ | |
isPlayerStarted: false, | |
/** | |
* flag, informs about visibility of player controls | |
*/ | |
isHidden: false, | |
/** | |
* reference to currently focused DOM element | |
*/ | |
focusedDOMElement: null, | |
/** | |
* incrementing HTML index added to focusable DOM elements | |
*/ | |
tabIndex: 0, | |
/** | |
* unified API for accessing player methods | |
*/ | |
player: { | |
/** | |
* declared playback speed - this variable is used to store playback speed that shall be valid after user trigger some method related to play speed | |
* if playback speed is equal to 1, and user will make pause (speed = 0) and immediately check controls.player.getSpeed() he can still receive "1" as play speed, because | |
* player need some time to make pause and set this speed value to "0" | |
*/ | |
playSpeed: null, | |
getSpeed: function () {}, // get player playback speed | |
getState: function () {}, // get player state | |
getPosition: function () {}, // get player position in "seconds" | |
getDuration: function () {}, // get duration of played content in "seconds" | |
object: null, | |
pause: function () {}, | |
play: function () {}, | |
seek: function () {}, | |
state: null, | |
stop: function () {} | |
}, | |
/** | |
* unifying AVObject and HTML5 video API to controls.player object | |
* @param object | |
* @param objectType | |
*/ | |
unifyVideoObjectsAPI: function (object, objectType) { | |
if (objectType === "video") { | |
this.player = { | |
object: object, | |
type: "video", | |
getDuration: function () { | |
return controls.player.object.duration * 1000; | |
}, | |
getPosition: function () { | |
return controls.player.object.currentTime * 1000; | |
}, | |
getSpeed: function () { | |
return controls.player.object.playbackRate; | |
}, | |
getState: function () { | |
return controls.player.state; | |
}, | |
pause: function () { | |
controls.player.object.pause(); | |
}, | |
play: function (playSpeed) { | |
if (typeof playSpeed == "undefined") { | |
playSpeed = 1; | |
} | |
controls.player.object.playbackRate = playSpeed; | |
if (playSpeed !== 0) { | |
controls.player.object.play(); | |
} | |
}, | |
seek: function (position) { | |
controls.player.object.currentTime = Math.round(position / 1000); | |
}, | |
stop: controls.callback.onStop | |
}; | |
controls.player.object.addEventListener('ended', controls.callback.onFinished); | |
controls.player.object.addEventListener('error', controls.callback.onError); | |
controls.player.object.addEventListener('pause', controls.callback.onPause); | |
controls.player.object.addEventListener('playing', controls.callback.onPlay); | |
controls.player.object.addEventListener('waiting', controls.callback.onLoading); | |
} else { | |
this.player = { | |
object: object, | |
type: "avobject", | |
getDuration: function () { | |
return controls.player.object.playTime; | |
}, | |
getPosition: function () { | |
return controls.player.object.playPosition; | |
}, | |
getSpeed: function () { | |
return controls.player.object.speed; | |
}, | |
getState: function () { | |
return controls.player.object.playState; | |
}, | |
pause: function () { | |
controls.player.object.play(0); | |
}, | |
play: function (playSpeed) { | |
controls.player.object.play(playSpeed); | |
}, | |
seek: function (position) { | |
controls.player.object.seek(position); | |
}, | |
stop: function () { | |
controls.player.object.stop(); | |
} | |
}; | |
controls.player.object.addEventListener("PlayStateChange", controls.AVObjectPlayStateChangeEventHandler); | |
} | |
}, | |
/** | |
* initialization of video player controls | |
*/ | |
initialize: function () { | |
controls.getPlayerObject(); | |
if (window.innerWidth === 1280) { | |
controls.css.addFile(_720); | |
} else { | |
controls.css.addFile(_1080); | |
} | |
controls.createLayout(); | |
controls.remoteController.activate(); | |
}, | |
/** | |
* create video player controls layout | |
*/ | |
createLayout: function () { | |
var documentFragment; | |
documentFragment = document.createDocumentFragment(); | |
controls.DOM = controls.createDOMElement("controls"); | |
controls.DOMElement.panel = controls.createDOMElement("panel"); | |
controls.DOM.appendChild(controls.DOMElement.panel); | |
controls.DOMElement.topArea = controls.createDOMElement("toparea"); | |
controls.DOMElement.infoArea = controls.createDOMElement("infoarea"); | |
controls.DOMElement.info1Line = controls.createDOMElement("info1line"); | |
controls.DOMElement.infoArea.appendChild(controls.DOMElement.info1Line); | |
controls.DOMElement.info2Line = controls.createDOMElement("info2Line"); | |
controls.DOMElement.infoArea.appendChild(controls.DOMElement.info2Line); | |
controls.DOMElement.topArea.appendChild(controls.DOMElement.infoArea); | |
controls.DOMElement.control1Area = controls.createDOMElement("control1area"); | |
controls.DOMElement.previousButton = controls.createDOMElement("previousbutton", null, true); | |
controls.DOMElement.control1Area.appendChild(controls.DOMElement.previousButton); | |
controls.DOMElement.rewindButton = controls.createDOMElement("rewindbutton", null, true); | |
controls.DOMElement.control1Area.appendChild(controls.DOMElement.rewindButton); | |
controls.DOMElement.playPauseButton = controls.createDOMElement("playpausebutton", null, true); | |
controls.DOMElement.control1Area.appendChild(controls.DOMElement.playPauseButton); | |
controls.DOMElement.fastForwardButton = controls.createDOMElement("fastforwardbutton", null, true); | |
controls.DOMElement.control1Area.appendChild(controls.DOMElement.fastForwardButton); | |
controls.DOMElement.nextButton = controls.createDOMElement("nextbutton", null, true); | |
controls.DOMElement.control1Area.appendChild(controls.DOMElement.nextButton); | |
controls.DOMElement.topArea.appendChild(controls.DOMElement.control1Area); | |
controls.DOMElement.control2Area = controls.createDOMElement("control2area"); | |
controls.DOMElement.debugButton = controls.createDOMElement("debugbutton", null, true); | |
controls.DOMElement.control2Area.appendChild(controls.DOMElement.debugButton); | |
controls.DOMElement.topArea.appendChild(controls.DOMElement.control2Area); | |
controls.DOMElement.panel.appendChild(controls.DOMElement.topArea); | |
controls.DOMElement.bottomArea = controls.createDOMElement("bottomarea"); | |
controls.DOMElement.statusModeIcon = controls.createDOMElement("statusmodeicon"); | |
controls.DOMElement.bottomArea.appendChild(controls.DOMElement.statusModeIcon); | |
controls.DOMElement.playTime = controls.createDOMElement("playtime"); | |
controls.DOMElement.bottomArea.appendChild(controls.DOMElement.playTime); | |
controls.progress.bar.container = controls.createDOMElement("progressbarcontainer"); | |
controls.progress.bar.DOM = controls.createDOMElement("progressbar"); | |
controls.progress.dot.DOM = controls.createDOMElement("progressdot", null, true); | |
controls.progress.bar.container.appendChild(controls.progress.bar.DOM); | |
controls.progress.bar.container.appendChild(controls.progress.dot.DOM); | |
controls.DOMElement.bottomArea.appendChild(controls.progress.bar.container); | |
controls.DOMElement.endTime = controls.createDOMElement("endtime"); | |
controls.DOMElement.bottomArea.appendChild(controls.DOMElement.endTime); | |
controls.DOMElement.panel.appendChild(controls.DOMElement.bottomArea); | |
controls.DOMElement.loader = controls.createDOMElement("loader"); | |
controls.DOM.appendChild(controls.DOMElement.loader); | |
documentFragment.appendChild(controls.DOM); | |
controls.DOMElement.info1Line.innerHTML = controls.getVideoName(); | |
document.body.appendChild(documentFragment); | |
}, | |
/** | |
* object with methods to manipulate CSS | |
*/ | |
css: { | |
/** | |
* adding CSS class to DOM element | |
* @param CSSClass | |
* @param element | |
*/ | |
addClass: function (CSSClass, element) { | |
element.className = (element.className + ' ' + CSSClass).trim(); | |
}, | |
/** | |
* adding CSS file to document HEAD | |
* @param fileName | |
*/ | |
addFile: function (fileName) { | |
var css; | |
css = document.createElement("link"); | |
css.href = fileName; | |
css.rel = "stylesheet"; | |
document.head.appendChild(css); | |
}, | |
/** | |
* checking if DOM element has CSS class | |
* @param CSSClass | |
* @param element | |
* @returns {boolean} | |
*/ | |
hasClass: function (CSSClass, element) { | |
var pattern; | |
pattern = new RegExp("\\b" + CSSClass + "\\b"); | |
return pattern.test(element.className); | |
}, | |
/** | |
* removing CSS class from DOM element | |
* @param CSSClass | |
* @param element | |
*/ | |
removeClass: function (CSSClass, element) { | |
var pattern; | |
pattern = new RegExp("\\b" + CSSClass + "\\b"); | |
element.className = element.className.replace(pattern ,'').trim(); | |
} | |
}, | |
/** | |
* search HTML document for used video player | |
*/ | |
getPlayerObject: function () { | |
var objects, | |
i, | |
type; | |
objects = document.getElementsByTagName("video"); | |
if (objects.length) { | |
this.unifyVideoObjectsAPI(objects[0], "video"); | |
} else { | |
objects = document.getElementsByTagName("object"); | |
if (objects.length) { | |
for (i = 0; i < objects.length; i++) { | |
type = objects[i].type; | |
if (type.indexOf("video") > -1 || type.indexOf("dash") > -1) { | |
this.unifyVideoObjectsAPI(objects[i], "object"); | |
} | |
} | |
} | |
} | |
}, | |
/** | |
* get title of used video | |
* @returns {*|string} | |
*/ | |
getVideoName: function () { | |
var pos, | |
name, | |
url; | |
name = this.player.object.name || this.player.object.title || this.player.object.alt; | |
if (name === '' || typeof name == "undefined") { | |
url = this.player.object.src || this.player.object.data || ''; | |
if (url === '') { | |
url = document.getElementsByTagName('source')[0].src; | |
} | |
pos = url.lastIndexOf('/'); | |
name = url.substr(pos + 1); | |
} | |
return name; | |
}, | |
/** | |
* method run after player start | |
*/ | |
onPlayerStart: function () { | |
this.progress.bar.width = parseInt(window.getComputedStyle(this.progress.bar.container).width, 10); | |
this.disableButton(controls.DOMElement.nextButton); | |
controls.DOMElement.playPauseButton.focus(); | |
this.isPlayerStarted = true; | |
controls.DOMElement.endTime.innerHTML = this.parseTime(this.player.getDuration()); | |
}, | |
/** | |
* checking if DOM element is currently focused | |
* @param element | |
* @returns {boolean} | |
*/ | |
isFocused: function (element) { | |
return controls.focusedDOMElement === element; | |
}, | |
/** | |
* creating DOM element | |
* @param id | |
* @param className | |
* @param tabIndex | |
* @returns {Element} | |
*/ | |
createDOMElement: function (id, className, tabIndex) { | |
var element = document.createElement("div"); | |
if (id) { | |
element.id = id; | |
} | |
if (className) { | |
element.className = className; | |
} | |
if (tabIndex) { | |
element.tabIndex = ++controls.tabIndex; | |
element.addEventListener("focus", function () { | |
controls.callback.onFocus(element); | |
}); | |
} | |
return element; | |
}, | |
/** | |
* retargeting callbacks from AVObject state change | |
*/ | |
AVObjectPlayStateChangeEventHandler: function () { | |
controls.restartAutoHide(); | |
switch (controls.player.getState()) { | |
case 0: // stop | |
controls.callback.onStop(); | |
break; | |
case 1: | |
controls.callback.onPlay(); // HTML5 playing, play | |
break; | |
case 2: // HTML5 pause | |
controls.callback.onPause(); | |
break; | |
case 3: // connecting // HTML5 waiting | |
controls.callback.onLoading(); | |
break; | |
case 4:// buffering // HTML5 waiting | |
controls.callback.onLoading(); | |
break; | |
case 5: // finished // HTML5 ended | |
controls.callback.onFinished(); | |
break; | |
case 6: // error // HTML5 error | |
controls.callback.onError(); | |
break; | |
} | |
}, | |
/** | |
* methods for IR Remote Controller support | |
*/ | |
remoteController: { | |
/** | |
* activate support for RC | |
*/ | |
activate: function () { | |
this.keySet = app.privateData.keyset; | |
this.keySet.setValue(this.keySet.VCR | this.keySet.NAVIGATION); | |
document.addEventListener("keydown", function (event) { | |
switch (event.keyCode) { | |
case 13: | |
controls.remoteController.press("enter"); | |
break; | |
case 19: | |
controls.action.pause(); | |
break; | |
case 37: | |
controls.remoteController.press("left", event); | |
break; | |
case 39: | |
controls.remoteController.press("right", event); | |
break; | |
case 38: | |
controls.remoteController.press("up"); | |
break; | |
case 40: | |
controls.remoteController.press("down", event); | |
break; | |
case 412: | |
controls.action.rewind(); | |
break; | |
case 413: | |
controls.action.stop(); | |
break; | |
case 415: | |
controls.action.play(); | |
break; | |
case 417: | |
controls.action.fastForward(); | |
break; | |
case 461: | |
controls.remoteController.press("return"); | |
break; | |
case 463: | |
controls.action.playPause(); | |
break; | |
} | |
}, false); | |
}, | |
/** | |
* semi event handler for RC keys input | |
* gives possibility to software emulate of RC key input for e.x. automatic tests | |
* @param button | |
* @param event | |
*/ | |
press: function (button, event) { | |
controls.restartAutoHide(); | |
switch (button) { | |
case "down": | |
if (controls.isHidden) { | |
controls.show(); | |
} else if (controls.player.playSpeed === 1 && controls.css.hasClass("playing", controls.DOM)) { | |
controls.progress.dot.DOM.focus(); | |
} else { | |
event.preventDefault(); | |
} | |
break; | |
case "enter": | |
if (controls.error) { | |
app.destroyApplication(); | |
} else if (controls.isHidden) { | |
controls.show(); | |
} else if (controls.progress.dot.isActive) { | |
controls.progress.dot.seekToPosition(); | |
controls.progress.dot.deactivate(); | |
controls.progress.dot.DOM.focus(); | |
} else { | |
controls.callback.onEnterPress(); | |
} | |
break; | |
case "left": | |
if (controls.isHidden) { | |
controls.show(); | |
} else if (controls.isFocused(controls.progress.dot.DOM)) { | |
controls.progress.dot.moveLeft(); | |
event.preventDefault(); | |
} | |
break; | |
case "return": | |
if (!controls.isHidden) { | |
controls.hide(); | |
} else { | |
app.destroyApplication(); | |
} | |
break; | |
case "right": | |
if (controls.isHidden) { | |
controls.show(); | |
} else if (controls.isFocused(controls.progress.dot.DOM)) { | |
controls.progress.dot.moveRight(); | |
event.preventDefault(); | |
} | |
break; | |
case "up": | |
if (controls.isHidden) { | |
controls.show(); | |
} else { | |
if (controls.progress.dot.isActive) { | |
controls.progress.dot.deactivate(); | |
} | |
controls.DOMElement.playPauseButton.focus(); | |
} | |
break; | |
} | |
} | |
}, | |
/** | |
* restart controls auto hide timer | |
*/ | |
restartAutoHide: function () { | |
clearTimeout(controls.autoHideTimer); | |
controls.autoHideTimer = setTimeout(controls.hide, controls.config.visibilityTime); | |
}, | |
/** | |
* interactions available for playback | |
*/ | |
action: { | |
/** | |
* action for fastForward button | |
*/ | |
fastForward: function () { | |
controls.show(); | |
if (controls.player.playSpeed >= 1 || controls.player.playSpeed <= -1) {// current state is playing or fastForward or rewind | |
controls.player.playSpeed = controls.getNextPlaySpeed("fastForward"); | |
} else {// current state is paused or slowRewind | |
controls.player.playSpeed = controls.getNextPlaySpeed("slowPlay"); | |
} | |
controls.DOM.className = "fastforward"; | |
controls.DOMElement.statusModeIcon.className = ("speed" + controls.player.playSpeed).replace('.', ''); | |
controls.player.play(controls.player.playSpeed); | |
controls.DOMElement.fastForwardButton.focus(); | |
}, | |
/** | |
* action for pause button | |
*/ | |
pause: function () { | |
controls.show(); | |
if (controls.player.getState() !== 2) { | |
controls.player.pause(); | |
} else { | |
controls.player.seek(controls.player.getPosition() + 500); | |
} | |
}, | |
/** | |
* action for play button | |
*/ | |
play: function () { | |
controls.show(); | |
controls.player.playSpeed = 1; | |
controls.player.play(controls.player.playSpeed); | |
}, | |
/** | |
* action toggle play/pause button | |
*/ | |
playPause: function () { | |
var state = controls.player.getState(); | |
if (state === 1 && controls.player.playSpeed === 1) {// playing | |
this.pause(); | |
} else if (state === 2 || (state === 1 && controls.player.playSpeed !== 1)) {// paused | |
this.play(); | |
} | |
}, | |
/** | |
* action for button "previous" | |
*/ | |
previous: function () { | |
controls.player.seek(0); | |
}, | |
/** | |
* action for rewind button | |
*/ | |
rewind: function () { | |
controls.show(); | |
if (controls.player.playSpeed >= 1 || controls.player.playSpeed <= -1) {// current state is playing, fastForward or rewind | |
controls.player.playSpeed = controls.getNextPlaySpeed("rewind"); | |
} else {// current state is paused or slowPlay | |
controls.player.playSpeed = controls.getNextPlaySpeed("slowRewind"); | |
} | |
controls.DOM.className = "rewind"; | |
controls.DOMElement.statusModeIcon.className = ("speed" + controls.player.playSpeed).replace(".", ""); | |
controls.player.play(controls.player.playSpeed); | |
controls.DOMElement.rewindButton.focus(); | |
}, | |
/** | |
* action for stop button | |
*/ | |
stop: function () { | |
controls.player.stop(); | |
} | |
}, | |
/** | |
* player callbacks | |
*/ | |
callback: { | |
/** | |
* callback fired after "enter" button press | |
*/ | |
onEnterPress: function () { | |
if (!controls.focusedDOMElement) { | |
return; | |
} | |
if (!controls.css.hasClass("disabled", controls.focusedDOMElement)) { | |
switch (controls.focusedDOMElement.id) { | |
case "playpausebutton": | |
controls.action.playPause(); | |
break; | |
case "rewindbutton": | |
controls.action.rewind(); | |
break; | |
case "fastforwardbutton": | |
controls.action.fastForward(); | |
break; | |
case "previousbutton": | |
controls.action.previous(); | |
break; | |
case "debugbutton": | |
if (!controls.debug.isEnabled) { | |
controls.debug.initialize(); | |
} else if (controls.debug.isHidden) { | |
controls.debug.DOM.style.display = "block"; | |
controls.debug.isHidden = false; | |
} else { | |
controls.debug.DOM.style.display = "none"; | |
controls.debug.isHidden = true; | |
} | |
break; | |
default: | |
break; | |
} | |
} | |
}, | |
/** | |
* callback fired after "error" occurs | |
*/ | |
onError: function () { | |
controls.player.state = 6; | |
controls.DOM.removeChild(controls.DOMElement.panel); | |
controls.DOM.removeChild(controls.DOMElement.loader); | |
controls.error = controls.createDOMElement("error"); | |
controls.error.innerHTML = controls.getLang("errorMessage"); | |
controls.errorButton = controls.createDOMElement("ok"); | |
controls.errorButton.innerHTML = controls.getLang("ok"); | |
controls.error.appendChild(controls.errorButton); | |
controls.DOM.appendChild(controls.error); | |
controls.errorButton.focus(); | |
}, | |
/** | |
* callback fired after video playback reach end | |
*/ | |
onFinished: function () { | |
app.destroyApplication(); | |
}, | |
/** | |
* callback fired when DOM element will become focus | |
* @param element | |
*/ | |
onFocus: function (element) { | |
if (typeof element != "undefined") { | |
controls.focusedDOMElement = element; | |
} | |
}, | |
/** | |
* callback fired when player state is changed to "loading" state, it's also buffering state | |
*/ | |
onLoading: function () { | |
controls.player.state = 3; | |
controls.DOMElement.loader.className = "visible"; | |
}, | |
/** | |
* callback fired when player state is changed to "paused" state | |
*/ | |
onPause: function () { | |
controls.player.state = 2; | |
controls.player.playSpeed = 0; | |
controls.DOMElement.playPauseButton.focus(); | |
controls.show(); | |
controls.DOM.className = "paused"; | |
controls.DOMElement.loader.className = ''; | |
controls.progress.timer.stop(); | |
controls.restartAutoHide(); | |
}, | |
/** | |
* callback fired when player state is changed to "playing" state | |
*/ | |
onPlay: function () { | |
var last_state = controls.player.state; | |
controls.player.state = 1; | |
controls.DOMElement.loader.className = ''; | |
if (!controls.player.playSpeed) { | |
controls.player.playSpeed = controls.player.getSpeed(); | |
} | |
if (!controls.isPlayerStarted) { | |
controls.onPlayerStart(); | |
controls.show(); | |
} | |
if (controls.progress.dot.isActive) { | |
controls.progress.dot.deactivate(); | |
} | |
if (controls.isFocused(controls.progress.dot.DOM)) { | |
controls.progress.dot.DOM.focus(); | |
} else { | |
if (controls.player.playSpeed === 1) { | |
controls.DOMElement.playPauseButton.focus(); | |
controls.DOM.className = "playing"; | |
} | |
if (last_state !== 3) { | |
controls.show(); | |
} | |
} | |
}, | |
/** | |
* callback fired when player state is changed to "stopped" state | |
*/ | |
onStop: function () { | |
app.destroyApplication(); | |
} | |
}, | |
/** | |
* show player controls | |
*/ | |
show: function () { | |
controls.isHidden = false; | |
controls.progress.update(); | |
controls.css.removeClass("hidden", controls.DOMElement.panel); | |
controls.restartAutoHide(); | |
controls.progress.timer.start(); | |
}, | |
/** | |
* hide player controls | |
*/ | |
hide: function () { | |
controls.isHidden = true; | |
controls.css.addClass("hidden", controls.DOMElement.panel); | |
clearTimeout(controls.autoHideTimer); | |
clearTimeout(controls.progress.timer.autoStop); | |
controls.progress.timer.autoStop = setTimeout(controls.progress.timer.stop, controls.config.visibilityTime); | |
}, | |
/** | |
* get next play speed from controls.config.speed for specific specific speed type | |
* @param speedType | |
* @returns {*} | |
*/ | |
getNextPlaySpeed: function (speedType) { | |
var i, | |
speedTypeLength, | |
nextPlaySpeed; | |
speedTypeLength = this.config.speed[speedType].length; | |
for (i = 0; i < speedTypeLength; i++) { | |
if (this.player.playSpeed === this.config.speed[speedType][i]) { | |
if (speedTypeLength > i + 1) { // last speed not reached | |
nextPlaySpeed = this.config.speed[speedType][i + 1]; | |
} | |
} | |
} | |
return nextPlaySpeed || this.config.speed[speedType][0]; | |
}, | |
/** | |
* disabling video controls button | |
* @param element | |
*/ | |
disableButton: function (element) { | |
this.css.addClass("disabled", element); | |
}, | |
/** | |
* enabling video controls button | |
* @param element | |
*/ | |
enableButton: function (element) { | |
this.css.removeClass("disabled", element); | |
}, | |
/** | |
* parsing time | |
* @param milisec | |
* @returns {string} | |
*/ | |
parseTime: function (milisec) { | |
var hour, | |
min, | |
sec, | |
tempsec; | |
tempsec = parseInt(milisec / 1000, 10); | |
min = Math.floor(tempsec / 60); | |
sec = tempsec % 60; | |
hour = Math.floor(min / 60); | |
if (hour > 0) { | |
min = min % 60; | |
} | |
return hour + ':' + (min < 10 ? '0' : '') + min + ':' + (sec < 10 ? '0' : '') + sec; | |
}, | |
/** | |
* object assembling all methods related to progress | |
*/ | |
progress: { | |
/** | |
* progress bar which is visible on controls panel | |
*/ | |
bar: { | |
/** | |
* container for progressBar DOM | |
*/ | |
container: null, | |
/** | |
* progressBar DOM | |
*/ | |
DOM: null, | |
/** | |
* update progressBar width | |
*/ | |
update: function () { | |
this.DOM.style.width = (controls.progress.percent * this.width / 100) + "px"; | |
}, | |
/** | |
* width of progressBar | |
*/ | |
width: 0 | |
}, | |
/** | |
* this is a Dot indicator that is moving on progressBar, it can be focused | |
*/ | |
dot: { | |
/** | |
* active progress dot gives possibility to pick point to seek | |
*/ | |
activate: function () { | |
if (!this.isActive) { | |
this.isActive = true; | |
controls.css.addClass("active", this.DOM); | |
this.percent = controls.progress.percent; | |
this.DOM.style.left = ((controls.progress.percent * controls.progress.bar.width) / 100) + "px"; | |
} | |
}, | |
/** | |
* remove activation from progress bar | |
*/ | |
deactivate: function () { | |
this.isActive = false; | |
controls.css.removeClass("active", this.DOM); | |
}, | |
/** | |
* progress dot DOM | |
*/ | |
DOM: null, | |
/** | |
* active state of progressDot is when progressDot is focused and then left/right arrow is pressed | |
* active state means that Dot position is not updated with progressBar, it shows position where user can make seek after pressing Enter button | |
*/ | |
isActive: false, | |
/** | |
* changes progress dot position to right (future time) | |
*/ | |
moveLeft: function () { | |
this.activate(); | |
this.percent -= 1000 / (controls.player.getDuration() / 1000); | |
if (this.percent < 0) { | |
this.percent = 0; | |
} | |
this.DOM.style.left = ((this.percent * controls.progress.bar.width) / 100) + "px"; | |
}, | |
/** | |
* changes progress dot position to left (previous time) | |
*/ | |
moveRight: function () { | |
this.activate(); | |
this.percent += 1000 / (controls.player.getDuration() / 1000); | |
if (this.percent > 100) { | |
this.percent = 100; | |
} | |
this.DOM.style.left = ((this.percent * controls.progress.bar.width) / 100) + "px"; | |
}, | |
/** | |
* position of progressDot on progressBar | |
*/ | |
percent: 0, | |
/** | |
* make seek to current position of progressDot | |
*/ | |
seekToPosition: function () { | |
controls.player.seek(this.percent / 100 * controls.player.getDuration()); | |
}, | |
/** | |
* update position of progressDot on progressBar | |
*/ | |
update: function () { | |
this.DOM.style.left = (controls.progress.percent * controls.progress.bar.width / 100) + "px"; | |
} | |
}, | |
/** | |
* percentage progress of video playback | |
*/ | |
percent: 0, | |
/** | |
* updating playback progress related elements | |
*/ | |
update: function () { | |
controls.progress.percent = Math.floor(controls.player.getPosition() / controls.player.getDuration() * 10000) / 100; | |
controls.progress.bar.update(); | |
controls.DOMElement.playTime.innerHTML = controls.parseTime(controls.player.getPosition()); | |
if (!controls.progress.dot.isActive) { | |
controls.progress.dot.update(); | |
} | |
}, | |
/** | |
* timer for updating progressBar width, progressDot position, and progress Time | |
*/ | |
timer: { | |
interval: null, | |
autoStop: null, | |
/** | |
* starting progress timer | |
*/ | |
start: function () { | |
this.stop(); | |
this.interval = setInterval(controls.progress.update, controls.config.progressBarRefreshTime); | |
}, | |
/** | |
* stopping progress timer | |
*/ | |
stop: function () { | |
clearTimeout(controls.progress.timer.autoStop); | |
controls.progress.timer.autoStop = null; | |
clearInterval(controls.progress.timer.interval); | |
controls.progress.timer.interval = null; | |
} | |
} | |
}, | |
/** | |
* object for debug player controls | |
*/ | |
debug: { | |
DOM: null, | |
isEnabled: false, | |
isHidden: true, | |
interval: null, | |
/** | |
* clearing logs displayed on the screen | |
*/ | |
clearLogs: function () { | |
controls.debug.console.innerHTML = ''; | |
}, | |
/** | |
* AVObject player event triggered when play position changed | |
*/ | |
onAVObjectPlayPositionChanged: function () { | |
controls.debug.playPosition.innerHTML = "playPosition = '" + controls.player.getPosition() + "' (" + controls.parseTime(controls.player.getPosition()) + ")"; | |
}, | |
/** | |
* AVObject player event triggered when play speed changed | |
*/ | |
onAVObjectPlaySpeedChanged: function () { | |
controls.debug.playSpeed.innerHTML = "playSpeed = '" + controls.player.getSpeed() + "'"; | |
}, | |
/** | |
* event triggered after RC key has been pressed | |
* @param e | |
*/ | |
onKeyPress: function (e) { | |
var keyName, | |
keyCode; | |
switch (e.keyCode) { | |
case 13: | |
keyName = "Enter"; | |
break; | |
case 19: | |
keyName = "Pause"; | |
break; | |
case 37: | |
keyName = "Left arrow"; | |
break; | |
case 38: | |
keyName = "Up arrow"; | |
break; | |
case 39: | |
keyName = "Right arrow"; | |
break; | |
case 40: | |
keyName = "Down arrow"; | |
break; | |
case 412: | |
keyName = "Rewind"; | |
break; | |
case 413: | |
keyName = "Stop"; | |
break; | |
case 415: | |
keyName = "Play"; | |
break; | |
case 417: | |
keyName = "FastForward"; | |
break; | |
case 461: | |
keyName = "Return"; | |
break; | |
case 404: | |
keyName = "VK_GREEN"; | |
controls.debug.clearLogs(); | |
break; | |
case 405: | |
keyName = "VK_YELLOW"; | |
controls.debug.scrollUp(); | |
break; | |
case 406: | |
keyName = "VK_BLUE"; | |
controls.debug.scrollDown(); | |
break; | |
default: | |
keyCode = e.keyCode; | |
console.log("keyCode '" + keyCode + "' not found"); | |
break; | |
} | |
if (keyName) { | |
controls.debug.keyPress.innerHTML = "last pressed key was '" + keyName + "'"; | |
} else { | |
controls.debug.keyPress.innerHTML = "last pressed key has keyCode = '" + keyCode + "'"; | |
} | |
}, | |
/** | |
* event triggered when player play state has been changed | |
*/ | |
onPlayStateChange: function () { | |
var playStateName = ""; | |
switch (controls.player.getState()) { | |
case 0: | |
playStateName = "stopped"; | |
break; | |
case 1: | |
playStateName = "playing"; | |
break; | |
case 2: | |
playStateName = "paused"; | |
break; | |
case 3: | |
playStateName = "connecting"; | |
break; | |
case 4: | |
playStateName = "buffering"; | |
break; | |
case 5: | |
playStateName = "finished"; | |
break; | |
case 6: | |
playStateName = "error"; | |
break; | |
} | |
controls.debug.playState.innerHTML = "playState = '" + controls.player.getState() + "' (" + playStateName + ")"; | |
controls.debug.playTime.innerHTML = "playTime = '" + controls.player.getDuration() + "' (" + controls.parseTime(controls.player.getDuration()) + ")"; | |
}, | |
/** | |
* HTML5 video player event triggered when play position changed | |
*/ | |
onVideoObjectPlayPositionChanged: function () { | |
controls.debug.playPosition.innerHTML = "currentTime = '" + controls.player.getPosition() + "' (" + controls.parseTime(controls.player.getPosition()) + ")"; | |
}, | |
/** | |
* HTML5 video player event triggered when play speed changed | |
*/ | |
onVideoObjectPlaySpeedChanged: function () { | |
controls.debug.playSpeed.innerHTML = "playbackRate = '" + controls.player.getSpeed() + "'"; | |
}, | |
/** | |
* debugger initialization | |
*/ | |
initialize: function(){ | |
var debugFragment; | |
controls.css.addFile(_debug); | |
debugFragment = document.createDocumentFragment(); | |
controls.debug.DOM = controls.createDOMElement("debug"); | |
controls.debug.console = controls.createDOMElement("debugconsole"); | |
controls.debug.DOM.appendChild(controls.debug.console); | |
controls.debug.playState = controls.createDOMElement("debugplaystate"); | |
controls.debug.DOM.appendChild(controls.debug.playState); | |
controls.debug.playSpeed = controls.createDOMElement("debugplayspeed"); | |
controls.debug.DOM.appendChild(controls.debug.playSpeed); | |
controls.debug.playTime = controls.createDOMElement("debugplaytime"); | |
controls.debug.DOM.appendChild(controls.debug.playTime); | |
controls.debug.playPosition = controls.createDOMElement("debugplayposition"); | |
controls.debug.DOM.appendChild(controls.debug.playPosition); | |
controls.debug.keyPress = controls.createDOMElement("debugkeypress"); | |
controls.debug.DOM.appendChild(controls.debug.keyPress); | |
controls.debug.helpBar = controls.createDOMElement("debughelpbar"); | |
controls.debug.helpGreen = controls.createDOMElement("debughelpgreen"); | |
controls.debug.helpBar.appendChild(controls.debug.helpGreen); | |
controls.debug.helpYellow = controls.createDOMElement("debughelpyellow"); | |
controls.debug.helpBar.appendChild(controls.debug.helpYellow); | |
controls.debug.helpBlue = controls.createDOMElement("debughelpblue"); | |
controls.debug.helpBar.appendChild(controls.debug.helpBlue); | |
controls.debug.DOM.appendChild(controls.debug.helpBar); | |
debugFragment.appendChild(controls.debug.DOM); | |
controls.DOM.appendChild(debugFragment); | |
document.addEventListener("keypress", controls.debug.onKeyPress); | |
console.log = function (log) { | |
controls.debug.print("log", log); | |
}; | |
console.warn = function (log) { | |
controls.debug.print("warn", log); | |
}; | |
console.error = function (log) { | |
controls.debug.print("error", log); | |
}; | |
console.debug = function (log) { | |
controls.debug.print("debug", log); | |
}; | |
if (controls.player.type === "video") { | |
controls.debug.initializeVideoObject(); | |
controls.debug.onPlayStateChange(); | |
} else { | |
controls.debug.initializeAVObject(); | |
controls.keySet = app.privateData.keyset; | |
controls.keySet.setValue(controls.keySet.VCR | controls.keySet.NAVIGATION | controls.keySet.GREEN | controls.keySet.YELLOW | controls.keySet.BLUE); | |
} | |
controls.debug.isEnabled = true; | |
controls.debug.isHidden = false; | |
}, | |
/** | |
* initialization of AVObject | |
*/ | |
initializeAVObject: function () { | |
controls.player.object.addEventListener("PlayStateChange", controls.debug.onPlayStateChange); | |
controls.player.object.addEventListener("PlayPositionChanged", controls.debug.onAVObjectPlayPositionChanged); | |
controls.player.object.addEventListener("PlaySpeedChanged", controls.debug.onAVObjectPlaySpeedChanged); | |
controls.debug.onPlayStateChange(); | |
controls.debug.onAVObjectPlayPositionChanged(); | |
controls.debug.onAVObjectPlaySpeedChanged(); | |
controls.debug.interval = setInterval(controls.debug.onAVObjectPlayPositionChanged, controls.config.progressBarRefreshTime); | |
}, | |
/** | |
* initialization of HTML5 video object | |
*/ | |
initializeVideoObject: function () { | |
controls.player.object.addEventListener("playing", controls.debug.onPlayStateChange); | |
controls.player.object.addEventListener("pause", controls.debug.onPlayStateChange); | |
controls.player.object.addEventListener("waiting", controls.debug.onPlayStateChange); | |
controls.player.object.addEventListener("ended", controls.debug.onPlayStateChange); | |
controls.player.object.addEventListener("error", controls.debug.onPlayStateChange); | |
controls.player.object.addEventListener("timeupdate", controls.debug.onVideoObjectPlayPositionChanged); | |
controls.player.object.addEventListener("ratechange", controls.debug.onVideoObjectPlaySpeedChanged); | |
}, | |
/** | |
* print logs on screen | |
* @param type | |
* @param txt | |
*/ | |
print: function (type, txt) { | |
var date, | |
log = document.createElement("div"); | |
date = new Date(); | |
if (type === "log") { | |
log.className = "log"; | |
} | |
if (type === "warn") { | |
log.className = "warn"; | |
} | |
if (type === "error") { | |
log.className = "error"; | |
} | |
if (type === "debug") { | |
log.className = "debug"; | |
} | |
log.innerHTML = date.getMinutes() + ':' + date.getSeconds() + '.' + date.getMilliseconds() + " - " +txt; | |
controls.debug.console.appendChild(log); | |
controls.debug.console.scrollTop = controls.debug.console.scrollHeight; | |
}, | |
/** | |
* scroll down logs list | |
*/ | |
scrollDown: function () { | |
controls.debug.console.scrollTop += 21; | |
}, | |
/** | |
* scroll up logs list | |
*/ | |
scrollUp: function () { | |
controls.debug.console.scrollTop -= 21; | |
} | |
} | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment