let client; var SequenceStatus; (function (SequenceStatus) { SequenceStatus[SequenceStatus["IDLE"] = 0] = "IDLE"; SequenceStatus[SequenceStatus["RUNNING"] = 1] = "RUNNING"; SequenceStatus[SequenceStatus["PAUSED"] = 2] = "PAUSED"; })(SequenceStatus || (SequenceStatus = {})); class Display { constructor() { this.sequence = false; this.offsetX = 0; this.offsetY = 0; this.width = 0; this.height = 0; this.canvasScale = 0; this.canvasWidth = 0; this.canvasHeight = 0; this.canvasOffsetX = 0; this.canvasOffsetY = 0; this.screenWidth = 0; this.screenHeight = 0; this.screenOffsetX = 0; this.screenOffsetY = 0; this.displayWidth = 0; this.displayHeight = 0; this.displayOffsetX = 0; this.displayOffsetY = 0; this.parentElement = document.getElementById('display'); this.create(); window.onresize = this.onResize.bind(this); } create() { this.canvas = this.parentElement.getElementsByTagName('canvas')[0]; this.ctx = this.canvas.getContext('2d'); this.screen = { width: parseInt(document.getElementById('width').value), height: parseInt(document.getElementById('height').value) }; this.updateSize(); this.clear(); this.updateScreen(); this.updateDisplay(); } updateSize() { this.canvasScale = window.devicePixelRatio; this.canvasWidth = this.parentElement.clientWidth - 12; this.canvasHeight = this.parentElement.clientHeight - 12; this.canvas.width = this.canvasWidth; this.canvas.height = this.canvasHeight; } clear() { this.ctx.fillStyle = 'rgb(0, 0, 0)'; this.ctx.fillRect(0, 0, this.canvasWidth, this.canvasHeight); } updateScreen() { const clientRatio = this.canvasWidth / this.canvasHeight; const screenRatio = this.screen.width / this.screen.height; if (screenRatio > clientRatio) { this.screenWidth = this.canvasWidth - 2; this.screenHeight = Math.floor(this.canvasWidth / screenRatio); this.screenOffsetX = 1; this.screenOffsetY = Math.round((this.canvasHeight - this.screenHeight) / 2); } else { this.screenWidth = Math.round(this.canvasHeight * screenRatio); this.screenHeight = this.canvasHeight - 2; this.screenOffsetY = 1; this.screenOffsetX = Math.round((this.canvasWidth - this.screenWidth) / 2); } this.ctx.strokeStyle = 'rgb(0, 0, 255)'; this.ctx.rect(this.screenOffsetX, this.screenOffsetY, this.screenWidth, this.screenHeight); this.ctx.stroke(); } updateDisplay() { if (!this.sequence) { return; } const screenScaleX = this.screenWidth / this.screen.width; const screenScaleY = this.screenHeight / this.screen.height; this.displayWidth = Math.round(this.width * screenScaleX); this.displayHeight = Math.round(this.height * screenScaleY); this.displayOffsetX = this.screenOffsetX + Math.round(this.offsetX * screenScaleX); this.displayOffsetY = this.screenOffsetY + Math.round(this.offsetY * screenScaleY); this.ctx.fillStyle = 'rgb(0, 0, 0)'; this.ctx.fillRect(this.displayOffsetX, this.displayOffsetY, this.displayWidth, this.displayHeight); this.updateImage(); } updateImage() { this.img = new Image; this.img.onload = function () { this.ctx.drawImage(this.img, this.displayOffsetX, this.displayOffsetY, this.displayWidth, this.displayHeight); }.bind(this); this.img.src = `/${this.displayWidth}/${this.displayHeight}/image.jpg?cacheBreaker=${+new Date()}`; } update(msg) { } set(state) { this.sequence = true; this.offsetX = state.offset.x; this.offsetY = state.offset.y; this.width = state.display.width; this.height = state.display.height; this.updateDisplay(); } onResize(event) { this.updateSize(); this.clear(); this.updateScreen(); this.updateDisplay(); } } class Client { constructor() { this.connected = false; this.frames = 0; let uri = this.getWebsocketUri(); this.progress = document.getElementById('progress'); this.progressText = document.getElementById('progressText'); this.client = new WebSocket(uri); this.display = new Display(); this.client.onopen = this.onOpen.bind(this); this.client.onclose = this.onClose.bind(this); this.client.onmessage = this.onMessage.bind(this); this.resetForm('sequenceSelectForm'); this.resetForm('sequenceCtrlForm'); this.resetForm('manualCtrlForm'); this.resetForm('exposureCtrlForm'); this.resetForm('statisticsForm'); this.disableClass('sequenceCtrl'); this.disableClass('manualCtrl'); this.disableClass('exposureCtrl'); this.setProgress({ hash: null, progress: 0 }); } getWebsocketUri() { const host = (window.location.host + '').split(':')[0]; return `ws://${host}:${WEBSOCKET_PORT}`; } onMessage(event) { const msg = JSON.parse(event.data); if (typeof msg.cmd !== 'undefined' && msg.cmd !== null) { this.cmd(msg); } } onOpen(event) { console.log('Connected'); this.connected = true; this.active(); this.enableClass('manualCtrl'); } onClose(event) { console.log('Disconnected'); this.connected = false; this.inactive(); } setSequence(state) { this.setProgress(state.sequence); this.setFrame(state.sequence); this.setStatus(state.sequence); this.setExposure(state); this.setDisplay(state); this.set('sequence', state.sequence.hash); this.removeClass('sequence', 'edited'); } setUpdate(state) { this.setProgress(state.sequence); this.setFrame(state.sequence); this.setStatus(state.sequence); this.setExposure(state); this.setStatistics(state.statistics); this.display.updateImage(); } setStatus(sequence) { let status; switch (sequence.status) { case SequenceStatus.IDLE: status = 'Idle'; break; case SequenceStatus.RUNNING: status = 'Running'; break; case SequenceStatus.PAUSED: status = 'Paused'; break; default: status = 'Unknown State'; } this.frames = sequence.frames; document.getElementById('sequenceStatus').innerText = status; document.getElementById('sequenceName').innerText = sequence.name; document.getElementById('sequenceLength').innerText = `Sequence Length: ${sequence.frames}`; } setProgress(sequence) { const percent = sequence.progress * 100.0; this.progress.value = sequence.progress; this.progressText.innerText = `Progress: ${Math.floor(percent)}%`; } setFrame(sequence) { if (typeof sequence.current !== 'undefined') { this.set('frame', `${sequence.current}`.padStart(5, '0')); this.removeClass('frame', 'edited'); } } setExposure(state) { if (typeof state.exposure !== 'undefined') { const el = document.getElementById('exposure'); this.enableClass('exposureCtrl'); this.set('exposure', `${state.exposure}`); this.removeClass('exposure', 'edited'); } } setDisplay(state) { if (typeof state.display !== 'undefined') { this.set('displayWidth', state.display.width.toString()); this.set('displayHeight', state.display.height.toString()); this.set('offsetLeft', state.offset.x.toString()); this.set('offsetTop', state.offset.y.toString()); this.set('sourceWidth', state.source.width.toString()); this.set('sourceHeight', state.source.height.toString()); this.display.set(state); } } edited(el) { el.classList.add('edited'); } setStatistics(stats) { if (stats !== null) { this.set('statsFrameTotalLast', this.roundDigits(stats.totalFrameLast, 0)); this.set('statsFrameTotalAvg', this.roundDigits(stats.totalFrameAvg, 2)); this.set('statsFrameTotalMargin', this.roundDigits(stats.totalFrameMargin, 1)); this.set('statsFPS', this.roundDigits(stats.fps, 2)); this.set('statsFrameLoadAvg', this.roundDigits(stats.loadAvg, 2)); this.set('statsFrameLoadMargin', this.roundDigits(stats.loadMargin, 1)); this.set('statsFrameOpenLast', this.roundDigits(stats.openLast, 0)); this.set('statsFrameOpenAvg', this.roundDigits(stats.openAvg, 2)); this.set('statsFrameOpenMargin', this.roundDigits(stats.openMargin, 1)); this.set('statsFrameCloseLast', this.roundDigits(stats.closeLast, 0)); this.set('statsFrameCloseAvg', this.roundDigits(stats.closeAvg, 2)); this.set('statsFrameCloseMargin', this.roundDigits(stats.closeMargin, 1)); this.set('statsExposureLast', this.roundDigits(stats.exposureLast, 0)); this.set('statsExposureAvg', this.roundDigits(stats.exposureAvg, 2)); this.set('statsExposureMargin', this.roundDigits(stats.exposureMargin, 1)); this.set('statsElapsed', this.roundDigits(stats.elapsed, 0)); this.set('statsEstimate', this.roundDigits(stats.estimate, 0)); this.set('statsElapsedHuman', this.shortenHumanize(Math.round(stats.elapsed))); this.set('statsEstimateHuman', this.shortenHumanize(Math.round(stats.estimate))); } } cmd(msg) { switch (msg.cmd) { case 'ping': this.receivePing(); break; case 'open': this.receiveCameraOpen(); break; case 'close': this.receiveCameraClose(); break; case 'select': this.receiveSelect(msg); break; case 'update': this.receiveUpdate(msg); break; case 'focus': this.receiveFocus(msg); break; case 'display': this.receiveDisplay(msg); break; default: console.warn(`No command "${msg.cmd}"`); break; } } disableClass(className) { console.log(`Disabling class: ${className}`); document.querySelectorAll(`.${className}`).forEach((el) => { el.disabled = true; }); } enableClass(className) { console.log(`Enabling class: ${className}`); document.querySelectorAll(`.${className}`).forEach((el) => { el.disabled = false; }); } sendCameraOpen() { console.log('send camera open'); this.disableClass('manualCtrl'); this.client.send(JSON.stringify({ cmd: 'open' })); } receivePing() { this.sendPong(); } receiveCameraOpen() { console.log('got camera open'); this.enableClass('manualCtrl'); } sendCameraClose() { console.log('send camera close'); this.disableClass('manualCtrl'); this.client.send(JSON.stringify({ cmd: 'close' })); } receiveCameraClose() { console.log('got camera close'); this.enableClass('manualCtrl'); } sendPong() { this.client.send(JSON.stringify({ cmd: 'pong' })); } sendAdvance() { this.client.send(JSON.stringify({ cmd: 'advance' })); } sendRewind() { this.client.send(JSON.stringify({ cmd: 'rewind' })); } sendFrameSet() { const frameStr = document.getElementById('frame').value; let frameNum = null; try { frameNum = parseInt(frameStr); } catch (err) { console.error(`Error parsing ${frameStr}`); } if (frameNum === null) { frameNum = 0; } if (frameNum < 0) { frameNum = 0; } if (frameNum > this.frames - 1) { frameNum = this.frames - 1; } this.client.send(JSON.stringify({ cmd: 'set', state: { sequence: { current: frameNum } } })); } sendToEnd() { this.client.send(JSON.stringify({ cmd: 'set', state: { sequence: { current: this.frames - 1 } } })); } sendToStart() { this.client.send(JSON.stringify({ cmd: 'set', state: { sequence: { current: 0 } } })); } sendSelect() { const hash = document.getElementById('sequence').value; let msg; if (hash === '- Select Image Sequence -') { return; } msg = { cmd: 'select', state: { sequence: { hash } } }; console.log(`send select ${hash}`); this.client.send(JSON.stringify(msg)); } receiveSelect(msg) { this.enableClass('sequenceCtrl'); this.setSequence(msg.state); } sendStart() { this.client.send(JSON.stringify({ cmd: 'start' })); } sendStop() { this.client.send(JSON.stringify({ cmd: 'stop' })); } sendExposure() { const exposure = parseInt(this.get('exposure')); this.client.send(JSON.stringify({ cmd: 'exposure', state: { exposure } })); } receiveUpdate(msg) { this.setUpdate(msg.state); } receiveDisplay(msg) { this.display.clear(); this.display.updateScreen(); this.setDisplay(msg.state); } sendFocus() { console.log('send focus'); this.client.send(JSON.stringify({ cmd: 'focus' })); } receiveFocus(msg) { this.display.updateImage(); } sendOffset(x, y) { this.client.send(JSON.stringify({ cmd: 'offset', x, y })); } sendSize(width, height) { this.client.send(JSON.stringify({ cmd: 'size', width, height })); } sendScale(scale) { this.client.send(JSON.stringify({ cmd: 'scale', scale })); } fullscreen() { if (!document.fullscreenElement) { document.documentElement.requestFullscreen(); } else { this.exitFullscreen(); } } exitFullscreen() { if (document.fullscreenElement) { document.exitFullscreen(); } } active() { this.addClass('overlay', 'active'); } inactive() { this.removeClass('overlay', 'active'); } addClass(id, className) { document.getElementById(id).classList.add(className); } removeClass(id, className) { document.getElementById(id).classList.remove(className); } set(id, value) { try { document.getElementById(id).value = value; } catch (err) { console.warn(`Element ${id} does not exist or cannot be set`); } } get(id) { return document.getElementById(id).value; } resetForm(id) { document.getElementById(id).reset(); } shortenHumanize(val) { const str = humanizeDuration(val, { round: true }); return str.replace('years', 'y').replace('year', 'y') .replace('months', 'mo').replace('month', 'mo') .replace('weeks', 'w').replace('week', 'w') .replace('days', 'd').replace('day', 'd') .replace('hours', 'h').replace('hour', 'h') .replace('minutes', 'm').replace('minute', 'm') .replace('seconds', 's').replace('second', 's'); } roundDigits(val, digits) { const mult = Math.pow(10.0, digits); const rounded = Math.round(val * mult) / mult; return rounded.toString(); } } client = new Client(); //# sourceMappingURL=index.js.map