284 lines
6.6 KiB
JavaScript
284 lines
6.6 KiB
JavaScript
/* global alert, XMLHttpRequest, STREAM_SERVER, STREAM_NAME */
|
|
import Hls from 'hls.js'
|
|
|
|
// Elements
|
|
let player = document.querySelector('.livecnt')
|
|
let vid = player.querySelector('#stream')
|
|
let overlay = player.querySelector('.overlay')
|
|
let btn = overlay.querySelector('#playbtn')
|
|
let time = overlay.querySelector('#duration')
|
|
let fullscreenbtn = overlay.querySelector('#fullscrbtn')
|
|
let playbtn = overlay.querySelector('#playbtn')
|
|
let mutebtn = overlay.querySelector('#mutebtn')
|
|
let lstat = overlay.querySelector('.live')
|
|
let opts = overlay.querySelector('.controls')
|
|
let bigbtn = overlay.querySelector('.bigplaybtn')
|
|
let volumebar = overlay.querySelector('#volume_seek')
|
|
let volumeseek = volumebar.querySelector('.seeker')
|
|
let volumeseekInner = volumeseek.querySelector('.seekbar')
|
|
|
|
// Variables
|
|
let hls
|
|
let hideTimeout
|
|
let retryTimeout
|
|
let vidReady = false
|
|
let shouldHide = true
|
|
let inFullscreen = false
|
|
let errored = false
|
|
|
|
function GET (url, istext) {
|
|
return new Promise((resolve, reject) => {
|
|
var xmlHttp = new XMLHttpRequest()
|
|
|
|
xmlHttp.onreadystatechange = function () {
|
|
if (xmlHttp.readyState === 4 && xmlHttp.status === 200) {
|
|
resolve(xmlHttp.responseText)
|
|
} else if (xmlHttp.readyState === 4 && xmlHttp.status >= 400) {
|
|
let err = new Error(xmlHttp.status)
|
|
err.request = xmlHttp
|
|
reject(err)
|
|
}
|
|
}
|
|
|
|
xmlHttp.open('GET', url, true)
|
|
istext && (xmlHttp.responseType = 'text')
|
|
xmlHttp.send(null)
|
|
})
|
|
}
|
|
|
|
function clampAddition (val) {
|
|
let volume = vid.volume
|
|
|
|
if (volume + val > 1) {
|
|
volume = 1
|
|
} else if (volume + val < 0) {
|
|
volume = 0
|
|
} else {
|
|
volume += val
|
|
}
|
|
|
|
return volume.toFixed(2)
|
|
}
|
|
|
|
function showBigBtn (show) {
|
|
if (show) {
|
|
bigbtn.className = 'bigplaybtn'
|
|
} else {
|
|
bigbtn.className = 'bigplaybtn hidden'
|
|
}
|
|
}
|
|
|
|
function updateVolume () {
|
|
volumeseekInner.style.width = vid.volume * 100 + '%'
|
|
}
|
|
|
|
function liveStatus (status) {
|
|
if (status) {
|
|
lstat.innerHTML = 'live now'
|
|
lstat.className = 'live'
|
|
clearTimeout(retryTimeout)
|
|
if (vid.paused) {
|
|
showBigBtn(true)
|
|
}
|
|
} else {
|
|
lstat.innerHTML = 'offline'
|
|
lstat.className = 'live offline'
|
|
retryTimeout = setTimeout(() => {
|
|
if (vidReady) return
|
|
hls.loadSource(STREAM_SERVER + STREAM_NAME + '.m3u8')
|
|
}, 10000)
|
|
}
|
|
}
|
|
|
|
function hide () {
|
|
if (vid.paused || !shouldHide) {
|
|
overlay.className = 'overlay'
|
|
return
|
|
}
|
|
|
|
overlay.className = 'overlay hidden'
|
|
}
|
|
|
|
function resetHide () {
|
|
overlay.className = 'overlay'
|
|
clearTimeout(hideTimeout)
|
|
|
|
if (vid.paused) return
|
|
if (!shouldHide) return
|
|
|
|
hideTimeout = setTimeout(() => {
|
|
hide()
|
|
}, 5000)
|
|
}
|
|
|
|
function updateTime () {
|
|
let minutes = Math.floor(vid.currentTime / 60)
|
|
let seconds = Math.floor(vid.currentTime - minutes * 60)
|
|
time.innerHTML = minutes + ':' + (seconds < 10 ? '0' + seconds : seconds)
|
|
}
|
|
|
|
function toggleStream () {
|
|
if (!vid) return
|
|
if (!vidReady) return
|
|
if (vid.paused) {
|
|
vid.play()
|
|
btn.innerHTML = '<i class="fa fa-pause fa-fw"></i>'
|
|
showBigBtn(false)
|
|
} else {
|
|
vid.pause()
|
|
btn.innerHTML = '<i class="fa fa-play fa-fw"></i>'
|
|
showBigBtn(true)
|
|
}
|
|
}
|
|
|
|
function toggleSound () {
|
|
let muteicon = mutebtn.querySelector('.fa')
|
|
if (vid.muted) {
|
|
vid.muted = false
|
|
muteicon.className = 'fa fa-volume-up fa-fw'
|
|
} else {
|
|
vid.muted = true
|
|
muteicon.className = 'fa fa-volume-off fa-fw'
|
|
}
|
|
}
|
|
|
|
function exitHandler () {
|
|
if (!(document.fullScreen || document.webkitIsFullScreen || document.mozFullScreen)) {
|
|
inFullscreen = false
|
|
}
|
|
|
|
if (inFullscreen) {
|
|
fullscreenbtn.innerHTML = '<i class="fa fa-compress fa-fw"></i>'
|
|
} else {
|
|
fullscreenbtn.innerHTML = '<i class="fa fa-expand fa-fw"></i>'
|
|
}
|
|
}
|
|
|
|
function toggleFullscreen () {
|
|
if (vid.enterFullscreen) {
|
|
if (!document.fullScreen) {
|
|
player.requestFullScreen()
|
|
inFullscreen = true
|
|
} else {
|
|
document.cancelFullScreen()
|
|
}
|
|
} else if (vid.webkitEnterFullscreen) {
|
|
if (!document.webkitIsFullScreen) {
|
|
player.webkitRequestFullScreen()
|
|
inFullscreen = true
|
|
} else {
|
|
document.webkitCancelFullScreen()
|
|
}
|
|
} else if (vid.mozRequestFullScreen) {
|
|
if (!document.mozFullScreen) {
|
|
player.mozRequestFullScreen()
|
|
inFullscreen = true
|
|
} else {
|
|
document.mozCancelFullScreen()
|
|
}
|
|
} else {
|
|
alert('Your browser doesn\'t support fullscreen!')
|
|
}
|
|
}
|
|
|
|
window.addEventListener('onblur', () => {
|
|
shouldHide = true
|
|
}, false)
|
|
|
|
window.addEventListener('onfocus', () => {
|
|
shouldHide = true
|
|
}, false)
|
|
|
|
player.addEventListener('mousemove', resetHide)
|
|
|
|
opts.addEventListener('mouseenter', () => {
|
|
shouldHide = false
|
|
})
|
|
|
|
opts.addEventListener('mouseleave', () => {
|
|
shouldHide = true
|
|
})
|
|
|
|
opts.addEventListener('mousemove', () => {
|
|
shouldHide = false
|
|
})
|
|
|
|
bigbtn.addEventListener('click', () => {
|
|
toggleStream()
|
|
})
|
|
|
|
volumeseek.addEventListener('click', (e) => {
|
|
vid.volume = ((e.pageX - volumeseek.offsetLeft) / volumeseek.clientWidth)
|
|
updateVolume()
|
|
})
|
|
|
|
let mousewheelevt = (/Firefox/i.test(navigator.userAgent)) ? 'DOMMouseScroll' : 'mousewheel'
|
|
|
|
volumebar.addEventListener(mousewheelevt, (e) => {
|
|
e.preventDefault()
|
|
let scrollAmnt = (e.wheelDelta == null ? e.detail * -40 : e.wheelDelta)
|
|
|
|
if (scrollAmnt < 0) {
|
|
vid.volume = clampAddition(-0.1)
|
|
} else {
|
|
vid.volume = clampAddition(0.1)
|
|
}
|
|
|
|
updateVolume()
|
|
}, false)
|
|
|
|
function loadSource () {
|
|
if (!hls) return
|
|
hls.loadSource(STREAM_SERVER + STREAM_NAME + '.m3u8')
|
|
}
|
|
|
|
if (Hls.isSupported()) {
|
|
hls = new Hls()
|
|
hls.attachMedia(vid)
|
|
loadSource()
|
|
hls.on(Hls.Events.MANIFEST_PARSED, () => {
|
|
vidReady = true
|
|
})
|
|
hls.on(Hls.Events.ERROR, (e) => {
|
|
vidReady = false
|
|
|
|
if (!vid.paused) {
|
|
toggleStream()
|
|
resetHide()
|
|
}
|
|
})
|
|
} else {
|
|
alert('Your browser does not support HLS streaming!')
|
|
}
|
|
|
|
function getStreamStatus () {
|
|
GET('/api/channel/' + STREAM_NAME).then((data) => {
|
|
let jd = JSON.parse(data)
|
|
if (jd.error) {
|
|
errored = true
|
|
return alert(jd.error)
|
|
}
|
|
|
|
if (jd.live && !vidReady) loadSource()
|
|
liveStatus(jd.live)
|
|
}, (e) => {
|
|
errored = true
|
|
liveStatus(false)
|
|
})
|
|
|
|
if (!errored) setTimeout(getStreamStatus, 8000)
|
|
}
|
|
|
|
playbtn.addEventListener('click', toggleStream)
|
|
mutebtn.addEventListener('click', toggleSound)
|
|
fullscreenbtn.addEventListener('click', toggleFullscreen)
|
|
|
|
document.addEventListener('webkitfullscreenchange', exitHandler, false)
|
|
document.addEventListener('mozfullscreenchange', exitHandler, false)
|
|
document.addEventListener('fullscreenchange', exitHandler, false)
|
|
document.addEventListener('MSFullscreenChange', exitHandler, false)
|
|
|
|
vid.addEventListener('timeupdate', updateTime, false)
|
|
|
|
getStreamStatus()
|