/*Canopy - The next generation of stoner streaming software Copyright (C) 2024-2025 Rainbownapkin and the TTN Community This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see .*/ class mediaHandler{ constructor(client, player, media){ //Get parents this.client = client; this.player = player; this.syncTolerance = 1; this.syncDelta = 6; //Ingest media object from server this.startMedia(media); } startMedia(media){ //If we properly ingested the media if(this.ingestMedia(media)){ //Build the video player this.buildPlayer(); //Call the start function this.start(); } } buildPlayer(){ //Create player this.video = document.createElement('video'); //Append it to page this.player.videoContainer.appendChild(this.video); //Reset player lock this.lock = false; } destroyPlayer(){ //Remove player from page this.video.remove(); //Null out video property this.video = null; } ingestMedia(media){ //Set now playing this.nowPlaying = media; //return true to signify success return true; } start(){ } sync(timestamp){ } end(){ this.nowPlaying = null; this.destroyPlayer(); } setPlayerLock(lock){ //toggle controls this.video.controls = !lock; //Only toggle mute if we're locking, or if we're unlocking after being locked //If this is ran twice without locking we don't want to surprise unmute on the user if(lock || this.lock){ //toggle mute this.video.muted = lock; } //toggle looping this.video.loop = lock; //set lock property this.lock = lock; } getRatio(){ return this.video.videoWidth / this.video.videoHeight; } } class nullHandler extends mediaHandler{ constructor(client, player){ //Call derived constructor super(client, player, {}); } start(){ //Lock the player super.setPlayerLock(true); //Set the static placeholder this.video.src = '/video/static.webm'; //Set video title this.player.title.textContent = 'NULL'; //play the placeholder video this.video.play(); } } class rawFileHandler extends mediaHandler{ constructor(client, player, media){ //Call derived constructor super(client, player, media); } start(){ //Set video this.video.src = this.nowPlaying.id; //Set video title this.player.title.textContent = this.nowPlaying.title; //Unlock player super.setPlayerLock(false); //play video this.video.play(); } sync(timestamp){ //Check if timestamp evenly devides into sync delta, effectively only checking for sync every X seconds if(timestamp % this.syncDelta == 0){ //Get absolute difference between syncronization timestamp and actual video timestamp, and check if it's over the sync tolerance if(Math.abs(timestamp - this.video.currentTime) > this.syncTolerance){ //If we need to sync, then sync the video! this.video.currentTime = timestamp; } } } }