icytv/src/player.js

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()