/*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.lastTimestamp = 0; //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 = this.lastTimestamp){ } reload(){ //Get current timestamp const timestamp = this.video.currentTime; //Load video from source this.video.load(); //Set it back to the proper time this.video.currentTime = timestamp; //Play the video this.video.play(); } end(){ this.nowPlaying = null; this.destroyPlayer(); } play(){ } pause(){ } 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; } getTimestamp(){ } setVideoTitle(title){ this.player.title.textContent = `Currently Playing: ${title}`; } } class nullHandler extends mediaHandler{ constructor(client, player){ //Call derived constructor super(client, player, {}); } start(){ //Lock the player this.setPlayerLock(true); //Set the static placeholder this.video.src = '/video/static.webm'; //Set video title manually this.player.title.textContent = 'Channel Off Air'; //play the placeholder video this.video.play(); } } class rawFileHandler extends mediaHandler{ constructor(client, player, media){ //Call derived constructor super(client, player, media); //Since this media type has no way to tell between the user and code seek events, we need a flag to mark them this.selfSeek = false; //Define listeners this.defineListeners(); } defineListeners(){ this.video.addEventListener('pause', this.onPause.bind(this)); this.video.addEventListener('seeking', this.onSeek.bind(this)); } start(){ //Set video this.video.src = this.nowPlaying.id; //Set video title this.setVideoTitle(this.nowPlaying.title); //Unlock player this.setPlayerLock(false); //play video this.video.play(); } play(){ this.video.play(); } pause(){ this.video.pause(); } sync(timestamp = this.lastTimestamp){ //Set self seek flag this.selfSeek = true; //Set current video time based on timestamp received from server this.video.currentTime = timestamp; } reload(){ //Throw self seek flag to make sure we don't un-sync the player this.selfSeek = true; //Call derived reload function super.reload(); } onPause(event){ this.player.unlockSync(); } onSeek(event){ //If the video was seeked out-side of code if(!this.selfSeek){ this.player.unlockSync(); } //reset self seek flag this.selfSeek = false; } getTimestamp(){ //Return current timestamp return this.video.currentTime; } }