Skip to content

Instantly share code, notes, and snippets.

@brunchboy

brunchboy/overlay.html

Last active Sep 22, 2020
Embed
What would you like to do?
Simpler OBS overlay template for Beat Link Trigger
<html>
<head>
<title>OBS Overlay</title>
<link rel="stylesheet" type="text/css" href="styles.css">
<script>
/** How often to check for changes when no player is playing. */
const idleInterval = 500;
/** Keeps track of the previous player state, so we can look for changes. */
var lastState;
/**
* Check whether there is any player currently playing a track.
*
* @param state the player parameters object returned by params.json.
* @return true if at least one player is playing something.
*/
function isAnyPlayerPlaying(state) {
return state && Object.values(state.players).find(player => player["is-playing"]) !== undefined;
}
/**
* Calculate how long to wait before next performing an action, depending on player state.
* If no player is active, return whichever is larger of idleInterval and activeInterval.
* Otherwise return interval.
*
* @param activeInterval how many milliseconds to wait if at least one player is playing.
* @return the number of milliseconds after which an activity should reschedule itself.
*/
function nextInterval(activeInterval) {
if (isAnyPlayerPlaying(lastState)) {
return activeInterval;
}
return (idleInterval > activeInterval)? idleInterval : activeInterval;
}
/**
* Reloads the master playuer artwork at the speciried interval. If no player is playing, then
* idleInterval will be used instead, unless the specified interval is already longer.
*
* @param interval the number of milliseconds that should elapse between reloads.
*/
function refreshArt(interval) {
const element = document.getElementById('art');
const refresher = function() {
fetch('params.json')
.then(response => {
if (response.status == 200) {
response.json()
.then(state => {
if (state.master && state.master.number) {
element.src = '/artwork/' + state.master.number + '?icons=true';
}
setTimeout(refresher, nextInterval(interval));
})
} else {
console.error('Problem updating OBS overlay parameters', response);
setTimeout(refresher, 5000);
}
})
.catch(error => {
// TODO: Show something on the page itself.
console.error('Problem communicating with OBS overlay server', error);
setTimeout(refresher, 30000);
});
}
setTimeout(refresher, nextInterval(interval));
}
/**
* Given an old and new value for a text element on the page,
* if they differ, updates the corresponding DOM element to contain
* the new text.
*
* @param id the DOM id of the element to be updated.
* @param current what the new value for this element should be.
* @param last the previous value of the element.
*/
function updateIfChanged(id, current, last) {
if (current !== last) {
document.getElementById(id).textContent = current;
}
}
/**
* Compares the most recently received server state with the previous one, and updates
* any page text elements whose values need to be be changed.
*
* @param state the new server state object.
*/
function applyChanges(state) {
const lastPlayer = lastState && lastState.master
const track = state.master.track;
const lastTrack = lastPlayer && lastPlayer.track;
updateIfChanged('artist', track && track.artist, lastTrack && lastTrack.artist);
updateIfChanged('title', track && track.title, lastTrack && lastTrack.title);
}
/**
* Periodically determines the current player state, and updates the page appropriately.
*
* @param interval how often the should be updated, in milliseconds, when a player is active.
*/
function updateState(interval) {
const updater = function() {
fetch('params.json')
.then(response => {
if (response.status == 200) {
response.json()
.then(state => {
applyChanges(state);
lastState = state;
setTimeout(updater, nextInterval(interval));
})
} else {
console.error('Problem updating OBS overlay parameters', response);
setTimeout(updater, 5000);
}})
.catch(error => {
// TODO: Show something on the page itself.
console.error('Problem communicating with OBS overlay server', error);
setTimeout(updater, 30000);
});
}
updater();
}
updateState(66);
</script>
</head>
<body>
<p>
<img id="art" src="artwork/{{master.number}}?icons=true" width="80" height="80" align="left">
<script>refreshArt(1000);</script>
<span id="title" style="font-size:30px" style="font-family:Titillium Web">{{master.track.title}}</span>
<br>
<span id="artist" style="font-size:20px" style="font-family:Titillium Web">{{master.track.artist}}.</span>
</p>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment