mirror of
https://codeberg.org/vlw/still-alive.git
synced 2025-09-14 00:13:41 +02:00

* dev21w41a * Added Monkeydo submodule Added Monkeydo to .gitmodules * dev21w41b * Added functional code before manifest and CSS The JS-part of this demo is now functional to the point where a Monkeydo manifest can be played on the different windows. CSS styling and an actual manifest will still have to be created. * Create README.md * Cake * Update README.md * Unsynced working example Everything is cued up and good to go. Now comes the fun part of syncing the lyrics with the song * Synchronized lyrics with music So, yeah this totally didn't take 6 hours to do. * Style changes and log removal Fixed the scroll direction for lyrics, made the art window's font clamp (and centered) and also removed some loggers. player.html will redirect to the main page if opened without a hash and will no longer be caught by crawlers that care about robots.txt
116 lines
No EOL
3.1 KiB
JavaScript
116 lines
No EOL
3.1 KiB
JavaScript
import { default as PlayerWindow } from "./PlayerWindow.mjs";
|
|
import { default as Monkeydo } from "./monkeydo/Monkeydo.mjs";
|
|
|
|
export default class WindowManager {
|
|
constructor(mediaElement) {
|
|
const self = this;
|
|
this.mediaElement = mediaElement;
|
|
|
|
// Bi-directional communcation to player windows
|
|
this.channels = {
|
|
"#lyrics": new BroadcastChannel("#lyrics"),
|
|
"#credits": new BroadcastChannel("#credits"),
|
|
"#art": new BroadcastChannel("#art")
|
|
};
|
|
|
|
for(const channel of Object.values(this.channels)) {
|
|
channel.addEventListener("message",event => this.message(event));
|
|
}
|
|
|
|
// Monkeydo methods
|
|
const methods = {
|
|
blank: (target) => {
|
|
self.channels[target].postMessage(["BLANK",target]);
|
|
},
|
|
lineFeed: (target) => {
|
|
self.channels[target].postMessage(["LINE_FEED"]);
|
|
},
|
|
textFeed: (text,target = "#lyrics") => {
|
|
self.channels[target].postMessage(["TEXT_FEED",text]);
|
|
},
|
|
drawArt: (index,target = "#art") => {
|
|
self.channels[target].postMessage(["DRAW_ART",index]);
|
|
},
|
|
playCredits: () => {
|
|
self.players.credits.do();
|
|
}
|
|
}
|
|
|
|
this.players = {
|
|
lyrics: new Monkeydo(methods),
|
|
credits: new Monkeydo(methods)
|
|
}
|
|
}
|
|
|
|
playbackFailed(promiseObject = false) {
|
|
console.log(promiseObject);
|
|
}
|
|
|
|
// Attempt to open a new window
|
|
async spawnPlayer(type) {
|
|
if(!type in this.channels) {
|
|
throw new Error(`Inavlid player type "${type}"`);
|
|
}
|
|
|
|
return await new Promise((resolve,reject) => {
|
|
const player = new PlayerWindow(type).open();
|
|
const channel = this.channels[type];
|
|
|
|
// Wait for window to emit ready state message before resolving
|
|
const ack = channel.addEventListener("message",event => {
|
|
if(event.data[0] === "WINDOW_READY" || event.data[1] === type) {
|
|
resolve("WINDOW_READY");
|
|
}
|
|
// Window failed to initialize
|
|
if(event.data[0] === "WINDOW_ERROR" || event.data[1][0] === type) {
|
|
reject(event.data[1]);
|
|
}
|
|
return false;
|
|
});
|
|
channel.removeEventListener("message",ack);
|
|
});
|
|
}
|
|
|
|
async play() {
|
|
for(const [key,player] of Object.entries(this.players)) {
|
|
const manifest = new URL(window.location.href + `monkeydo_${key}.json`);
|
|
|
|
await player.load(manifest.toString());
|
|
}
|
|
this.players.lyrics.do();
|
|
this.mediaElement.play();
|
|
}
|
|
|
|
// Open player windows and start playback
|
|
async init() {
|
|
const art = this.spawnPlayer("#art");
|
|
const credits = this.spawnPlayer("#credits");
|
|
const lyrics = this.spawnPlayer("#lyrics");
|
|
|
|
const timeout = new Promise(resolve => setTimeout(() => resolve("TIMEOUT")),3000);
|
|
const windows = await Promise.allSettled([lyrics,credits,art]);
|
|
|
|
// Wait for all windows to open and initialize (or timout and fail)
|
|
const status = Promise.race([windows,timeout]);
|
|
status.then(promises => {
|
|
promises.forEach(promiseObject => {
|
|
if(promiseObject.status !== "fulfilled") {
|
|
this.playbackFailed(promiseObject);
|
|
}
|
|
});
|
|
|
|
// Load Monkeydo manifest and start playback
|
|
this.play();
|
|
});
|
|
}
|
|
|
|
message(event) {
|
|
const type = event.data[0];
|
|
const data = event.data[1];
|
|
|
|
switch(type) {
|
|
case "PLAY": console.log("PLAY",event); break;
|
|
case "WINDOW_CLOSED": console.log("WINDOW_CLOSED",event); break;
|
|
}
|
|
}
|
|
} |