UNPKG

ovenplayer

Version:

OvenPlayer is Open-Source HTML5 Player. OvenPlayer supports WebRTC Signaling from OvenMediaEngine for Sub-Second Latency Streaming.

420 lines (354 loc) 13.9 kB
/** * Created by hoho on 2018. 7. 20.. */ import OvenTemplate from 'view/engine/OvenTemplate'; import Helpers from 'view/components/helpers/main'; import Controls from 'view/components/controls/main'; import PanelManager from "view/global/PanelManager"; import ContextPanel from 'view/components/helpers/contextPanel'; import LA$ from 'utils/likeA$'; import ResizeSensor from "utils/resize-sensor"; import getTouchSection from "utils/getTouchSection"; import { READY, DESTROY, PLAYER_RESIZED, PLAYER_PLAY, STATE_IDLE, STATE_AD_PLAYING, STATE_PLAYING, STATE_STALLED, STATE_LOADING, STATE_COMPLETE, STATE_PAUSED, STATE_ERROR, CONTENT_META, PLAYER_STATE, PLAYER_CLICKED, ERROR } from "api/constants"; import '../../stylesheet/ovenplayer.less'; const View = function ($container) { let viewTemplate = "", controls = "", helper = "", $playerRoot, contextPanel = "", api = null, autoHideTimer = "", playerState = STATE_IDLE; let isShiftPressed = false; let panelManager = PanelManager(); let screenSize = ""; let currentPlayerSize = ""; let resizeSensor = null; let that = {}; //Member Functions function setHide(hide, autoHide) { if (autoHideTimer) { clearTimeout(autoHideTimer); autoHideTimer = null; } if (hide) { if (panelManager.size() > 0) { return false; } $playerRoot.addClass("op-autohide"); } else { $playerRoot.removeClass("op-autohide"); if (autoHide) { autoHideTimer = setTimeout(function () { if (panelManager.size() > 0) { return false; } $playerRoot.addClass("op-autohide"); }, 3000); } } } function togglePlayPause() { const currentState = playerState; if (currentState === STATE_IDLE || currentState === STATE_PAUSED || currentState === STATE_COMPLETE) { if (currentState === STATE_COMPLETE) { api.seek(0); } api.play(); } else if (currentState === STATE_PLAYING) { api.pause(); } } function seek(seconds, isRewind) { const duration = api.getDuration(); const currentPosition = api.getPosition(); let position = 0; if (isRewind) { position = Math.max(currentPosition - seconds, 0); } else { position = Math.min(currentPosition + seconds, duration); } api.seek(position); } function volume(isUp) { const currentVolumn = api.getVolume(); let newVolume = 0; if (isUp) { newVolume = Math.min(currentVolumn + 5, 100); } else { newVolume = Math.max(currentVolumn - 5, 0); } api.setVolume(newVolume); } function createContextPanel(pageX, pageY) { if (contextPanel) { contextPanel.destroy(); contextPanel = null; } contextPanel = ContextPanel($playerRoot, api, { pageX: pageX, pageY: pageY }); } function calcPlayerWidth() { let playerWidth = $playerRoot.width(); if (playerWidth < 576) { screenSize = "xsmall"; $playerRoot.addClass("xsmall"); if (playerWidth < 490) { $playerRoot.addClass("xxsmall"); } } else if (playerWidth < 768) { screenSize = "small"; $playerRoot.addClass("small"); } else if (playerWidth < 992) { screenSize = "medium"; $playerRoot.addClass("medium"); } else { screenSize = "large"; $playerRoot.addClass("large"); } } const onRendered = function ($current, template) { $playerRoot = $current; viewTemplate = template; calcPlayerWidth(); currentPlayerSize = screenSize; resizeSensor = new ResizeSensor($playerRoot.get(), function () { $playerRoot.removeClass("large"); $playerRoot.removeClass("medium"); $playerRoot.removeClass("small"); $playerRoot.removeClass("xsmall"); $playerRoot.removeClass("xxsmall"); calcPlayerWidth(); if (screenSize !== currentPlayerSize) { currentPlayerSize = screenSize; if (api) { api.trigger(PLAYER_RESIZED, currentPlayerSize); } } }); }; const onDestroyed = function () { if (resizeSensor) { resizeSensor.detach(); resizeSensor = null; } if (helper) { helper.destroy(); helper = null; } if (controls) { controls.destroy(); controls = null; } }; const events = { "click .ovenplayer": function (event, $current, template) { if (api) { api.trigger(PLAYER_CLICKED, event); } if (contextPanel) { event.preventDefault(); contextPanel.destroy(); contextPanel = null; return false; } if (!(LA$(event.target).closest(".op-controls-container") || LA$(event.target).closest(".op-setting-panel"))) { if (panelManager.size() > 0) { event.preventDefault(); panelManager.clear(); return false; } if (api.getDuration() !== Infinity && !api.getBrowser().mobile) { togglePlayPause(); } } }, "dblclick .ovenplayer": function (event, $current, template) { if (api) { const touchPosition = getTouchSection(event); const currentPosition = api.getPosition(); const tapToSeekEnabled = api.getConfig().doubleTapToSeek; // seek back 10s if (tapToSeekEnabled && touchPosition == 'left') { const newPosition = Math.max(currentPosition - 10, 0); OvenPlayerConsole.log(`Seeking to ${newPosition}`); api.seek(newPosition); } // seek forward 10s if (tapToSeekEnabled && touchPosition === 'right') { const newPosition = Math.min(currentPosition + 10, api.getDuration()); OvenPlayerConsole.log(`Seeking to ${newPosition}`); api.seek(newPosition); } if (touchPosition === 'middle' || !tapToSeekEnabled) { OvenPlayerConsole.log(`Toggling fullscreen`); if (api.getConfig().expandFullScreenUI && api.toggleFullScreen) { if (!(LA$(event.target).closest(".op-controls-container") || LA$(event.target).closest(".op-setting-panel"))) { api.toggleFullScreen(); } } } } }, //For iOS safari "touchstart .ovenplayer": function (event, $current, template) { if (playerState === STATE_PLAYING || playerState === STATE_IDLE || playerState === STATE_LOADING || (playerState === STATE_AD_PLAYING && screenSize === "xsmall")) { setHide(false, true); } else { setHide(false); } }, "mouseenter .ovenplayer": function (event, $current, template) { event.preventDefault(); //small screen with STATE_AD_PLAYING setHide too. becuase mobile hide ad ui. if (playerState === STATE_PLAYING || playerState === STATE_IDLE || playerState === STATE_LOADING || (playerState === STATE_AD_PLAYING && screenSize === "xsmall")) { setHide(false, true); } else { setHide(false); } }, "mousemove .ovenplayer": function (event, $current, template) { event.preventDefault(); if (playerState === STATE_PLAYING || playerState === STATE_IDLE || playerState === STATE_LOADING || (playerState === STATE_AD_PLAYING && screenSize === "xsmall")) { setHide(false, true); } else { setHide(false); } }, "mouseleave .ovenplayer": function (event, $current, template) { event.preventDefault(); if (playerState === STATE_PLAYING || playerState === STATE_IDLE || playerState === STATE_LOADING || (playerState === STATE_AD_PLAYING && screenSize === "xsmall")) { setHide(true); } }, "keydown .ovenplayer": function (event, $current, template) { let frameMode = api.getFramerate(); switch (event.keyCode) { case 16: //shift event.preventDefault(); isShiftPressed = true; break; case 32: //space event.preventDefault(); togglePlayPause(); break; case 37: //arrow left event.preventDefault(); if (!api.getConfig().disableSeekUI) { if (isShiftPressed && frameMode) { api.seekFrame(-1); } else { seek(5, true); } } break; case 39: //arrow right event.preventDefault(); if (!api.getConfig().disableSeekUI) { if (isShiftPressed && frameMode) { api.seekFrame(1); } else { seek(5, false); } } break; case 38: //arrow up event.preventDefault(); volume(true); break; case 40: //arrow up event.preventDefault(); volume(false); break; } }, "keyup .ovenplayer": function (event, $current, template) { switch (event.keyCode) { case 16: //shift event.preventDefault(); isShiftPressed = false; break; } }, "contextmenu .ovenplayer": function (event, $current, template) { event.stopPropagation(); if (!LA$(event.currentTarget).find("object")) { event.preventDefault(); createContextPanel(event.pageX, event.pageY); return false; } } }; that = OvenTemplate($container, "View", null, $container.id, events, onRendered, onDestroyed, true); that.getMediaElementContainer = () => { return $playerRoot.find(".op-media-element-container").get(); }; that.setApi = (playerInstance) => { api = playerInstance; api.getContainerElement = () => { return $playerRoot.get(); }; api.getContainerId = () => { return $playerRoot.get().id; }; api.on(READY, function (data) { if (!controls) { controls = Controls($playerRoot.find(".op-ui"), playerInstance); } if (!showControlBar) { $playerRoot.addClass("op-no-controls"); } setHide(false, true); }); api.on(ERROR, function (error) { if (api) { let sources = api.getSources() || []; if (controls && (sources.length <= 1)) { // controls.destroy(); // controls = null; } } }); api.on(DESTROY, function (data) { viewTemplate.destroy(); }); api.on(PLAYER_PLAY, function (data) { if (!controls && showControlBar) { controls = Controls($playerRoot.find(".op-ui"), playerInstance); } }); let showControlBar = api.getConfig() && api.getConfig().controls; helper = Helpers($playerRoot.find(".op-ui"), playerInstance); controls = Controls($playerRoot.find(".op-ui"), playerInstance); let aspectRatio = api.getConfig().aspectRatio; if (aspectRatio) { if (aspectRatio.split(':').length === 2) { let width = aspectRatio.split(':')[0] * 1; let height = aspectRatio.split(':')[1] * 1; let ratio = height / width * 100; $playerRoot.find('.op-ratio').css('padding-bottom', ratio + '%'); } } api.showControls = function (show, keepOpen) { if (show) { $playerRoot.removeClass("op-no-controls"); let autoHide = !keepOpen setHide(false, autoHide); } else { $playerRoot.addClass("op-no-controls"); } }; }; return that; }; export default View;