Compare commits
5 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
be327165b8 | |
|
|
c6c659535e | |
|
|
17f1cbfa9b | |
|
|
ac58c0e8c3 | |
|
|
1393acdc42 |
|
|
@ -0,0 +1,45 @@
|
||||||
|
let audioContext;
|
||||||
|
let gainNode;
|
||||||
|
|
||||||
|
function startAudio() {
|
||||||
|
audioContext = new (window.AudioContext || window.webkitAudioContext)();
|
||||||
|
gainNode = audioContext.createGain();
|
||||||
|
gainNode.gain.value = 0;
|
||||||
|
gainNode.connect(audioContext.destination);
|
||||||
|
}
|
||||||
|
|
||||||
|
function muter() {
|
||||||
|
fadeOutVolume();
|
||||||
|
}
|
||||||
|
|
||||||
|
function unMute() {
|
||||||
|
startAudio();
|
||||||
|
fadeInVolume();
|
||||||
|
}
|
||||||
|
|
||||||
|
function fadeInVolume() {
|
||||||
|
gainNode.gain.setValueAtTime(0, audioContext.currentTime); // Start at 0
|
||||||
|
gainNode.gain.linearRampToValueAtTime(1, audioContext.currentTime + 2); // Fade to full volume
|
||||||
|
}
|
||||||
|
|
||||||
|
function fadeOutVolume() {
|
||||||
|
gainNode.gain.setValueAtTime(1, audioContext.currentTime); // Start at 1
|
||||||
|
gainNode.gain.linearRampToValueAtTime(0, audioContext.currentTime + 2); // Fade to 0
|
||||||
|
}
|
||||||
|
|
||||||
|
export function playSound(instrument) {
|
||||||
|
if (interacted) {
|
||||||
|
// const source = audioContext.createBufferSource();
|
||||||
|
const samples = instrument.samples;
|
||||||
|
const sampleKeys = Object.keys(samples);
|
||||||
|
const numSamples = sampleKeys.length;
|
||||||
|
const randomSampleNumber = Math.floor(Math.random() * (numSamples - 0));
|
||||||
|
// const randomKey =
|
||||||
|
// sampleKeys[randomSampleNumber];
|
||||||
|
sendMidiMessage(instrument.midiChannelName, randomSampleNumber);
|
||||||
|
|
||||||
|
// source.buffer = samples[`${randomKey}`];
|
||||||
|
// source.connect(gainNode);
|
||||||
|
// source.start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,106 @@
|
||||||
|
import { loadInstruments } from "./instruments.js";
|
||||||
|
|
||||||
|
export class Conductor {
|
||||||
|
instruments;
|
||||||
|
|
||||||
|
constructor() {}
|
||||||
|
|
||||||
|
showingWhichContent;
|
||||||
|
interacted = true;
|
||||||
|
|
||||||
|
get instruments() {
|
||||||
|
return this.instruments;
|
||||||
|
}
|
||||||
|
|
||||||
|
static setTitle() {
|
||||||
|
const now = new Date();
|
||||||
|
const future = new Date(now.getTime() + 59 * 1000); // 59 seconds later
|
||||||
|
|
||||||
|
const formattedDate = `${Conductor.padZero(
|
||||||
|
now.getDate()
|
||||||
|
)}.${Conductor.padZero(now.getMonth() + 1)}.${now.getFullYear()}`;
|
||||||
|
const formattedTime = `${Conductor.padZero(
|
||||||
|
now.getHours()
|
||||||
|
)}:${Conductor.padZero(now.getMinutes())}:${this.padZero(
|
||||||
|
now.getSeconds()
|
||||||
|
)}`;
|
||||||
|
const formattedFutureTime = `${Conductor.padZero(
|
||||||
|
future.getHours()
|
||||||
|
)}:${Conductor.padZero(future.getMinutes())}:${Conductor.padZero(
|
||||||
|
future.getSeconds()
|
||||||
|
)}`;
|
||||||
|
|
||||||
|
title.innerHTML = `${formattedDate}<span class="tab-space"></span>${formattedTime} - ${formattedFutureTime} UTC`;
|
||||||
|
}
|
||||||
|
|
||||||
|
showMainContent() {
|
||||||
|
Conductor.setTitle();
|
||||||
|
const mute = document.getElementById("mute");
|
||||||
|
|
||||||
|
mute.addEventListener("click", () => {
|
||||||
|
const mutedSrc = "/assets/svg/sound-on.svg";
|
||||||
|
const unMutedSrc = "/assets/svg/mute.svg";
|
||||||
|
interacted = !interacted;
|
||||||
|
interacted ? unMute() : muter();
|
||||||
|
mute.src = interacted ? mutedSrc : unMutedSrc;
|
||||||
|
|
||||||
|
startAudio();
|
||||||
|
fadeInVolume();
|
||||||
|
});
|
||||||
|
|
||||||
|
this.fadeAndReplaceADiv("main-content", "loading-screen");
|
||||||
|
this.fadeAndReplaceADiv("buttons", "buttons");
|
||||||
|
this.showingWhichContent = "main-content";
|
||||||
|
|
||||||
|
document.getElementById("menu-button").onclick = function () {
|
||||||
|
toggleInfo();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleInfo() {
|
||||||
|
if (this.showingWhichContent === "main-content") {
|
||||||
|
this.fadeAndReplaceADiv("about-content", "main-content");
|
||||||
|
cleanUpAndRestart();
|
||||||
|
this.showingWhichContent = "about-content";
|
||||||
|
} else {
|
||||||
|
this.fadeAndReplaceADiv("main-content", "about-content");
|
||||||
|
this.showingWhichContent = "main-content";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fadeAndReplaceADiv(innyDivId, outtyDivId) {
|
||||||
|
const outty = document.getElementById(outtyDivId);
|
||||||
|
const inny = document.getElementById(innyDivId);
|
||||||
|
outty.classList.remove("fade-in");
|
||||||
|
outty.classList.add("fade-out");
|
||||||
|
|
||||||
|
outty.style.display = "none";
|
||||||
|
inny.style.display = "flex";
|
||||||
|
inny.style.opacity = "0";
|
||||||
|
void inny.offsetWidth;
|
||||||
|
inny.classList.add("fade-in");
|
||||||
|
inny.style.opacity = "1";
|
||||||
|
}
|
||||||
|
|
||||||
|
static padZero(num) {
|
||||||
|
return num.toString().padStart(2, "0");
|
||||||
|
}
|
||||||
|
|
||||||
|
async init() {
|
||||||
|
const instrumentsKey = document.getElementById("instrument-key-div");
|
||||||
|
this.instruments = await loadInstruments();
|
||||||
|
const instNames = Object.keys(this.instruments);
|
||||||
|
for (const instrument of instNames) {
|
||||||
|
const keyDiv = document.createElement("div");
|
||||||
|
const keySvg = document.createElement("object");
|
||||||
|
const keyName = document.createElement("div");
|
||||||
|
keyName.innerText = instrument.toUpperCase();
|
||||||
|
keySvg.type = "image/svg+xml";
|
||||||
|
keySvg.data = this.instruments[instrument].image;
|
||||||
|
keyDiv.appendChild(keySvg);
|
||||||
|
keyDiv.appendChild(keyName);
|
||||||
|
keyDiv.classList.add("instrument-key");
|
||||||
|
instrumentsKey.appendChild(keyDiv);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,83 @@
|
||||||
|
import { Conductor } from "./conductor";
|
||||||
|
|
||||||
|
export class Renderer {
|
||||||
|
timeIndicator;
|
||||||
|
currStaveNumber;
|
||||||
|
numStaves;
|
||||||
|
sheetWindow;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.numStaves = 6;
|
||||||
|
this.currStaveNumber = 1;
|
||||||
|
this.timeIndicator = document.querySelector("#time-indicator");
|
||||||
|
|
||||||
|
this.timeIndicator.addEventListener("animationiteration", () => {
|
||||||
|
this.currStaveNumber++;
|
||||||
|
if (this.currStaveNumber > this.numStaves) {
|
||||||
|
this.cleanUpAndRestart();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.sheetWindow = document.getElementById("music-window");
|
||||||
|
|
||||||
|
for (let i = 1; i <= this.numStaves; i++) {
|
||||||
|
const staveWrapper = document.createElement("div");
|
||||||
|
staveWrapper.classList.add("stave-wrapper");
|
||||||
|
staveWrapper.setAttribute("id", `stave-wrapper-${i}`);
|
||||||
|
staveWrapper.style.position = "relative";
|
||||||
|
|
||||||
|
const staveObject = document.createElement("object");
|
||||||
|
staveObject.type = "image/svg+xml";
|
||||||
|
staveObject.data = "assets/svg/stave.svg";
|
||||||
|
staveObject.classList.add("stave-svg");
|
||||||
|
|
||||||
|
staveWrapper.appendChild(staveObject);
|
||||||
|
this.sheetWindow.appendChild(staveWrapper);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
placeIcon = (instrument) => {
|
||||||
|
if (this.currStaveNumber > this.numStaves) this.currStaveNumber = 1;
|
||||||
|
|
||||||
|
const targetWrapper = document.getElementById(
|
||||||
|
`stave-wrapper-${this.currStaveNumber}`
|
||||||
|
);
|
||||||
|
|
||||||
|
const rect = this.timeIndicator.getBoundingClientRect();
|
||||||
|
const sheetLeft = this.sheetWindow.getBoundingClientRect().left;
|
||||||
|
const xPosition = rect.left + window.scrollX - sheetLeft;
|
||||||
|
|
||||||
|
const newObject = document.createElement("div");
|
||||||
|
newObject.classList.add("event-icon");
|
||||||
|
newObject.style.position = "absolute";
|
||||||
|
newObject.style.left = `${
|
||||||
|
xPosition - document.documentElement.clientWidth / 200
|
||||||
|
}px`;
|
||||||
|
newObject.style.top = `${instrument.yPos}`;
|
||||||
|
|
||||||
|
const eventIcon = document.createElement("object");
|
||||||
|
eventIcon.type = "image/svg+xml";
|
||||||
|
eventIcon.data = instrument.image;
|
||||||
|
|
||||||
|
newObject.appendChild(eventIcon);
|
||||||
|
targetWrapper.appendChild(newObject);
|
||||||
|
};
|
||||||
|
|
||||||
|
cleanUpAndRestart(reload = false) {
|
||||||
|
const icons = document.querySelectorAll(".event-icon");
|
||||||
|
this.timeIndicator = document.getElementById("time-indicator");
|
||||||
|
|
||||||
|
icons.forEach((icon) => {
|
||||||
|
icon.classList.add("fade-out");
|
||||||
|
icon.addEventListener("transitionend", () => {
|
||||||
|
icon.remove();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
this.currStaveNumber = 1;
|
||||||
|
|
||||||
|
Conductor.setTitle();
|
||||||
|
|
||||||
|
if (reload) location.reload();
|
||||||
|
}
|
||||||
|
}
|
||||||
301
src/script.js
301
src/script.js
|
|
@ -1,294 +1,37 @@
|
||||||
import { Client, BrowserSocketFactory } from "./blitz.js";
|
|
||||||
import { loadInstruments } from "./instruments.js";
|
|
||||||
import { sendMidiMessage } from "./midi.js";
|
import { sendMidiMessage } from "./midi.js";
|
||||||
|
import { Conductor } from "./conductor.js";
|
||||||
|
import { DataStream } from "./socket.js";
|
||||||
|
import { playSound } from "./audio";
|
||||||
|
import { Renderer, placeIcon } from "./render.js";
|
||||||
|
|
||||||
document.addEventListener("DOMContentLoaded", async () => {
|
document.addEventListener("DOMContentLoaded", async () => {
|
||||||
let showing;
|
|
||||||
let audioContext;
|
|
||||||
let interacted = true;
|
|
||||||
let gainNode;
|
|
||||||
|
|
||||||
sendMidiMessage();
|
sendMidiMessage();
|
||||||
|
|
||||||
function startAudio() {
|
const conductor = new Conductor();
|
||||||
audioContext = new (window.AudioContext || window.webkitAudioContext)();
|
await conductor.init();
|
||||||
gainNode = audioContext.createGain();
|
const dataStream = new DataStream();
|
||||||
gainNode.gain.value = 0;
|
const instruments = await conductor.instruments;
|
||||||
gainNode.connect(audioContext.destination);
|
console.log(instruments);
|
||||||
}
|
|
||||||
|
|
||||||
function muter() {
|
const renderer = new Renderer();
|
||||||
fadeOutVolume();
|
|
||||||
}
|
|
||||||
|
|
||||||
function unMute() {
|
dataStream.addEventListener("strike", () => {
|
||||||
startAudio();
|
const keys = Object.keys(instruments);
|
||||||
fadeInVolume();
|
const randomIndex = Math.floor(Math.random() * keys.length);
|
||||||
}
|
const selectedInstrument = instruments[keys[randomIndex]];
|
||||||
|
|
||||||
function padZero(num) {
|
renderer.placeIcon(selectedInstrument);
|
||||||
return num.toString().padStart(2, "0");
|
playSound(selectedInstrument);
|
||||||
}
|
|
||||||
|
|
||||||
function setTitle() {
|
|
||||||
const now = new Date();
|
|
||||||
const future = new Date(now.getTime() + 59 * 1000); // 59 seconds later
|
|
||||||
|
|
||||||
const formattedDate = `${padZero(now.getDate())}.${padZero(
|
|
||||||
now.getMonth() + 1
|
|
||||||
)}.${now.getFullYear()}`;
|
|
||||||
const formattedTime = `${padZero(now.getHours())}:${padZero(
|
|
||||||
now.getMinutes()
|
|
||||||
)}:${padZero(now.getSeconds())}`;
|
|
||||||
const formattedFutureTime = `${padZero(future.getHours())}:${padZero(
|
|
||||||
future.getMinutes()
|
|
||||||
)}:${padZero(future.getSeconds())}`;
|
|
||||||
|
|
||||||
title.innerHTML = `${formattedDate}<span class="tab-space"></span>${formattedTime} - ${formattedFutureTime} UTC`;
|
|
||||||
}
|
|
||||||
|
|
||||||
function fadeInVolume() {
|
|
||||||
gainNode.gain.setValueAtTime(0, audioContext.currentTime); // Start at 0
|
|
||||||
gainNode.gain.linearRampToValueAtTime(1, audioContext.currentTime + 2); // Fade to full volume
|
|
||||||
}
|
|
||||||
function fadeOutVolume() {
|
|
||||||
gainNode.gain.setValueAtTime(1, audioContext.currentTime); // Start at 1
|
|
||||||
gainNode.gain.linearRampToValueAtTime(0, audioContext.currentTime + 2); // Fade to 0
|
|
||||||
}
|
|
||||||
|
|
||||||
function showMainContent() {
|
|
||||||
setTitle();
|
|
||||||
const mute = document.getElementById("mute");
|
|
||||||
|
|
||||||
mute.addEventListener("click", () => {
|
|
||||||
const mutedSrc = "/assets/svg/sound-on.svg";
|
|
||||||
const unMutedSrc = "/assets/svg/mute.svg";
|
|
||||||
interacted = !interacted;
|
|
||||||
interacted ? unMute() : muter();
|
|
||||||
mute.src = interacted ? mutedSrc : unMutedSrc;
|
|
||||||
|
|
||||||
startAudio();
|
|
||||||
fadeInVolume();
|
|
||||||
});
|
|
||||||
|
|
||||||
fadeAndReplaceADiv("main-content", "loading-screen");
|
|
||||||
fadeAndReplaceADiv("buttons", "buttons");
|
|
||||||
showing = "main-content";
|
|
||||||
|
|
||||||
document.getElementById("menu-button").onclick = function () {
|
|
||||||
toggleInfo();
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function toggleInfo() {
|
|
||||||
if (showing === "main-content") {
|
|
||||||
fadeAndReplaceADiv("about-content", "main-content");
|
|
||||||
cleanUpAndRestart();
|
|
||||||
showing = "about-content";
|
|
||||||
} else {
|
|
||||||
fadeAndReplaceADiv("main-content", "about-content");
|
|
||||||
showing = "main-content";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function fadeAndReplaceADiv(innyDivId, outtyDivId) {
|
|
||||||
const outty = document.getElementById(outtyDivId);
|
|
||||||
const inny = document.getElementById(innyDivId);
|
|
||||||
outty.classList.remove("fade-in");
|
|
||||||
outty.classList.add("fade-out");
|
|
||||||
|
|
||||||
outty.style.display = "none";
|
|
||||||
inny.style.display = "flex";
|
|
||||||
inny.style.opacity = "0";
|
|
||||||
void inny.offsetWidth;
|
|
||||||
inny.classList.add("fade-in");
|
|
||||||
inny.style.opacity = "1";
|
|
||||||
}
|
|
||||||
|
|
||||||
const socketFactory = new BrowserSocketFactory();
|
|
||||||
let client = new Client(socketFactory);
|
|
||||||
client.connect();
|
|
||||||
let connectionTimeout; // Timeout for detecting inactivity
|
|
||||||
let lastReceived = Date.now(); // Tracks the last time data was received
|
|
||||||
|
|
||||||
function resetTimeout() {
|
|
||||||
clearTimeout(connectionTimeout);
|
|
||||||
connectionTimeout = setTimeout(() => {
|
|
||||||
// 15 seconds of inactivity
|
|
||||||
console.log("No data received in 15 seconds, reconnecting...");
|
|
||||||
reconnectWebSocket();
|
|
||||||
}, 15000);
|
|
||||||
}
|
|
||||||
|
|
||||||
function reconnectWebSocket() {
|
|
||||||
console.log("Reconnecting WebSocket...");
|
|
||||||
|
|
||||||
// Clean up the existing WebSocket connection
|
|
||||||
if (client) {
|
|
||||||
client.close(); // Ensure the current connection is closed
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a new client instance and re-establish the connection
|
|
||||||
client = new Client(new BrowserSocketFactory());
|
|
||||||
setupWebSocketListeners(); // Set up listeners for the new WebSocket
|
|
||||||
client.connect(); // Reconnect
|
|
||||||
|
|
||||||
// Reset timeout after reconnecting
|
|
||||||
resetTimeout(); // Ensure timeout is re-established after reconnection
|
|
||||||
}
|
|
||||||
|
|
||||||
function setupWebSocketListeners() {
|
|
||||||
client.removeAllListeners("data");
|
|
||||||
client.removeAllListeners("error");
|
|
||||||
client.removeAllListeners("close");
|
|
||||||
|
|
||||||
client.on("data", (strike) => {
|
|
||||||
lastReceived = Date.now(); // Update the last received timestamp
|
|
||||||
resetTimeout(); // Reset the timeout on any data received
|
|
||||||
|
|
||||||
// Process the strike (existing logic from your original code)
|
|
||||||
strikeNumber++;
|
|
||||||
if (strikeNumber == 1) {
|
|
||||||
const randomInstrumentNumber = Math.floor(
|
|
||||||
Math.random() * (Object.keys(instruments).length - 1)
|
|
||||||
);
|
|
||||||
const selectedInstrumentName =
|
|
||||||
Object.keys(instruments)[randomInstrumentNumber];
|
|
||||||
|
|
||||||
placeIcon(instruments[selectedInstrumentName]);
|
|
||||||
playSound(instruments[selectedInstrumentName]);
|
|
||||||
strikeNumber = 0;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
client.on("error", (message) => {
|
|
||||||
console.log("WebSocket error:", message);
|
|
||||||
reconnectWebSocket();
|
|
||||||
});
|
|
||||||
|
|
||||||
client.on("close", () => {
|
|
||||||
console.log("WebSocket closed, attempting to reconnect...");
|
|
||||||
reconnectWebSocket();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
let currStaveNumber = 1;
|
|
||||||
|
|
||||||
const instruments = await loadInstruments();
|
|
||||||
const instNames = Object.keys(instruments);
|
|
||||||
|
|
||||||
showMainContent();
|
|
||||||
|
|
||||||
/***
|
|
||||||
* Add the instrument images and names into the about section
|
|
||||||
*/
|
|
||||||
|
|
||||||
const instrumentsKey = document.getElementById("instrument-key-div");
|
|
||||||
for (const instrument of instNames) {
|
|
||||||
const keyDiv = document.createElement("div");
|
|
||||||
const keySvg = document.createElement("object");
|
|
||||||
const keyName = document.createElement("div");
|
|
||||||
keyName.innerText = instrument.toUpperCase();
|
|
||||||
keySvg.type = "image/svg+xml";
|
|
||||||
keySvg.data = instruments[instrument].image;
|
|
||||||
keyDiv.appendChild(keySvg);
|
|
||||||
keyDiv.appendChild(keyName);
|
|
||||||
keyDiv.classList.add("instrument-key");
|
|
||||||
instrumentsKey.appendChild(keyDiv);
|
|
||||||
}
|
|
||||||
|
|
||||||
const numStaves = 6;
|
|
||||||
const sheetWindow = document.getElementById("music-window");
|
|
||||||
|
|
||||||
for (let i = 1; i <= numStaves; i++) {
|
|
||||||
const staveWrapper = document.createElement("div");
|
|
||||||
staveWrapper.classList.add(`stave-wrapper`);
|
|
||||||
staveWrapper.setAttribute("id", `stave-wrapper-${i}`);
|
|
||||||
staveWrapper.style.position = "relative";
|
|
||||||
const staveObject = document.createElement("object");
|
|
||||||
staveObject.type = "image/svg+xml";
|
|
||||||
staveObject.data = "assets/svg/stave.svg";
|
|
||||||
staveObject.classList.add("stave-svg");
|
|
||||||
|
|
||||||
staveWrapper.appendChild(staveObject);
|
|
||||||
sheetWindow.appendChild(staveWrapper);
|
|
||||||
}
|
|
||||||
|
|
||||||
const timeIndicator = document.querySelector("#time-indicator");
|
|
||||||
|
|
||||||
timeIndicator.addEventListener("animationiteration", () => {
|
|
||||||
currStaveNumber++;
|
|
||||||
if (currStaveNumber > numStaves) {
|
|
||||||
cleanUpAndRestart();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const cleanUpAndRestart = (reload = false) => {
|
dataStream.init();
|
||||||
const icons = document.querySelectorAll(".event-icon");
|
|
||||||
const timeIndicator = document.getElementById("time-indicator");
|
|
||||||
icons.forEach((icon) => {
|
|
||||||
icon.classList.add("fade-out");
|
|
||||||
icon.addEventListener("transitionend", () => {
|
|
||||||
icon.remove();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
currStaveNumber = 1;
|
|
||||||
setTitle();
|
|
||||||
if (reload) location.reload();
|
|
||||||
};
|
|
||||||
|
|
||||||
const playSound = (instrument) => {
|
// let currStaveNumber = 1;
|
||||||
if (interacted) {
|
|
||||||
// const source = audioContext.createBufferSource();
|
|
||||||
const samples = instrument.samples;
|
|
||||||
const sampleKeys = Object.keys(samples);
|
|
||||||
const numSamples = sampleKeys.length;
|
|
||||||
const randomSampleNumber = Math.floor(Math.random() * (numSamples - 1));
|
|
||||||
// const randomKey =
|
|
||||||
// sampleKeys[randomSampleNumber];
|
|
||||||
sendMidiMessage(instrument.midiChannelName, randomSampleNumber);
|
|
||||||
|
|
||||||
// source.buffer = samples[`${randomKey}`];
|
conductor.showMainContent();
|
||||||
// source.connect(gainNode);
|
|
||||||
// source.start();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const placeIcon = (instrument) => {
|
// let strikeNumber = 0;
|
||||||
if (currStaveNumber > numStaves) currStaveNumber = 1;
|
|
||||||
// Select the staveWrapper in which to place the div
|
|
||||||
const staveWrapper = document.getElementById(
|
|
||||||
`stave-wrapper-${currStaveNumber}`
|
|
||||||
);
|
|
||||||
// Determine the position of the time indicator
|
|
||||||
const rect = timeIndicator.getBoundingClientRect();
|
|
||||||
const sheetLeft = sheetWindow.getBoundingClientRect().left;
|
|
||||||
const xPosition = rect.left + window.scrollX - sheetLeft;
|
|
||||||
|
|
||||||
// Create the icon div and give it its location data
|
// setupWebSocketListeners(); // Setup the WebSocket listeners
|
||||||
const newObject = document.createElement("div");
|
// resetTimeout(); // Start the timeout timer
|
||||||
newObject.classList.add("event-icon");
|
|
||||||
newObject.style.position = "absolute";
|
|
||||||
|
|
||||||
newObject.style.left = `${
|
|
||||||
xPosition - document.documentElement.clientWidth / 200
|
|
||||||
}px`;
|
|
||||||
newObject.style.top = `${instrument.yPos}`;
|
|
||||||
|
|
||||||
// Create the icon
|
|
||||||
const eventIcon = document.createElement("object");
|
|
||||||
eventIcon.type = "image/svg+xml";
|
|
||||||
eventIcon.data = instrument.image;
|
|
||||||
|
|
||||||
// Append icon to div
|
|
||||||
newObject.appendChild(eventIcon);
|
|
||||||
|
|
||||||
// Append the div to the staveWrapper
|
|
||||||
staveWrapper.appendChild(newObject);
|
|
||||||
};
|
|
||||||
|
|
||||||
let strikeNumber = 0;
|
|
||||||
|
|
||||||
setupWebSocketListeners(); // Setup the WebSocket listeners
|
|
||||||
resetTimeout(); // Start the timeout timer
|
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,62 @@
|
||||||
|
import { BrowserSocketFactory, Client } from "./blitz";
|
||||||
|
|
||||||
|
export class DataStream extends EventTarget {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.socketFactory = null;
|
||||||
|
this.client = null;
|
||||||
|
this.lastReceived = null;
|
||||||
|
this.connectionTimeout = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
async init() {
|
||||||
|
this.socketFactory = new BrowserSocketFactory();
|
||||||
|
this.client = new Client(this.socketFactory);
|
||||||
|
this.lastReceived = Date.now();
|
||||||
|
|
||||||
|
this.setupWebSocketListeners();
|
||||||
|
this.client.connect();
|
||||||
|
this.resetTimeout();
|
||||||
|
}
|
||||||
|
|
||||||
|
resetTimeout() {
|
||||||
|
clearTimeout(this.connectionTimeout);
|
||||||
|
this.connectionTimeout = setTimeout(() => {
|
||||||
|
console.log("No data received in 14 seconds, reconnecting...");
|
||||||
|
this.reconnectWebSocket();
|
||||||
|
}, 14999);
|
||||||
|
}
|
||||||
|
|
||||||
|
reconnectWebSocket() {
|
||||||
|
if (this.client) {
|
||||||
|
this.client.close();
|
||||||
|
}
|
||||||
|
this.client = new Client(new BrowserSocketFactory());
|
||||||
|
this.setupWebSocketListeners();
|
||||||
|
this.client.connect();
|
||||||
|
this.resetTimeout();
|
||||||
|
}
|
||||||
|
|
||||||
|
setupWebSocketListeners() {
|
||||||
|
this.client.removeAllListeners?.("data");
|
||||||
|
this.client.removeAllListeners?.("error");
|
||||||
|
this.client.removeAllListeners?.("close");
|
||||||
|
|
||||||
|
this.client.on("data", (data) => {
|
||||||
|
this.lastReceived = Date.now();
|
||||||
|
this.resetTimeout();
|
||||||
|
|
||||||
|
this.dispatchEvent(new CustomEvent("strike", { detail: data }));
|
||||||
|
});
|
||||||
|
|
||||||
|
this.client.on("error", (err) => {
|
||||||
|
console.error("WebSocket error:", err);
|
||||||
|
this.reconnectWebSocket();
|
||||||
|
});
|
||||||
|
|
||||||
|
this.client.on("close", () => {
|
||||||
|
console.log("WebSocket closed, attempting to reconnect...");
|
||||||
|
this.reconnectWebSocket();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue