261 lines
8.8 KiB
JavaScript
261 lines
8.8 KiB
JavaScript
// Apple Music Overlay Module
|
|
// This module connects to a local Cider instance to display Apple Music playback information.
|
|
// Initial sources were taken from https://github.com/nuttylmao/nutty.gg
|
|
|
|
;(function() {
|
|
let visibilityDefault = 5;
|
|
let visibilityDuration = visibilityDefault;
|
|
let animationSpeed = 0.5;
|
|
|
|
const moduleUrl = window.getModuleUrl();
|
|
loadCSSModule('overlay-applemusic-css', moduleUrl + '/css/apple-music.css');
|
|
loadModuleResources([
|
|
{ type:'css', url:'https://cdn.jsdelivr.net/npm/@xz/fonts@1/serve/metropolis.min.css', id:'xz-fonts' },
|
|
{ type:'js', url:'https://cdn.socket.io/4.7.5/socket.io.min.js', id:'socket-io', crossorigin:'anonymous' },
|
|
{ type:'js', url:'https://cdnjs.cloudflare.com/ajax/libs/gsap/1.18.0/TweenMax.min.js', id:'tweenmax' }
|
|
]).then(() => {
|
|
initModule();
|
|
let outer = document.getElementById('musicWidgetContainer');
|
|
let maxWidth = outer.clientWidth+50;
|
|
window.addEventListener("resize", resize);
|
|
resize();
|
|
connectws();
|
|
|
|
function initModule() {
|
|
const container = document.getElementById('mainContainer') || document.body;
|
|
|
|
// Crée le conteneur principal
|
|
if (!document.getElementById('musicWidgetContainer')) {
|
|
const widget = document.createElement('div');
|
|
widget.id = 'musicWidgetContainer';
|
|
|
|
// Album art box
|
|
const artBox = document.createElement('div');
|
|
artBox.id = 'albumArtBox';
|
|
const albumArt = document.createElement('img');
|
|
albumArt.id = 'albumArt';
|
|
albumArt.src = ''; // placeholder
|
|
const albumArtBack = document.createElement('img');
|
|
albumArtBack.id = 'albumArtBack';
|
|
albumArtBack.src = ''; // placeholder
|
|
artBox.append(albumArt, albumArtBack);
|
|
|
|
// Song info box
|
|
const infoBox = document.createElement('div');
|
|
infoBox.id = 'songInfoBox';
|
|
|
|
const songInfo = document.createElement('div');
|
|
songInfo.id = 'songInfo';
|
|
const innerBox = document.createElement('div');
|
|
innerBox.id = 'IAmRunningOutOfNamesForTheseBoxes';
|
|
|
|
const songLabel = document.createElement('div');
|
|
songLabel.id = 'songLabel';
|
|
songLabel.innerText = '-/-';
|
|
const artistLabel = document.createElement('div');
|
|
artistLabel.id = 'artistLabel';
|
|
artistLabel.innerText = '-/-';
|
|
const albumLabel = document.createElement('div');
|
|
albumLabel.id = 'albumLabel';
|
|
albumLabel.innerText = '-/-';
|
|
|
|
const times = document.createElement('div');
|
|
times.id = 'times';
|
|
const progressTime = document.createElement('div');
|
|
progressTime.id = 'progressTime';
|
|
progressTime.innerText = '0:00';
|
|
const duration = document.createElement('div');
|
|
duration.id = 'duration';
|
|
duration.innerText = '0:00';
|
|
times.append(progressTime, duration);
|
|
|
|
const progressBg = document.createElement('div');
|
|
progressBg.id = 'progressBg';
|
|
const progressBar = document.createElement('div');
|
|
progressBar.id = 'progressBar';
|
|
progressBg.appendChild(progressBar);
|
|
|
|
innerBox.append(songLabel, artistLabel, albumLabel, times, progressBg);
|
|
songInfo.appendChild(innerBox);
|
|
|
|
const backgroundArt = document.createElement('div');
|
|
backgroundArt.id = 'backgroundArt';
|
|
const backgroundImage = document.createElement('img');
|
|
backgroundImage.id = 'backgroundImage';
|
|
backgroundImage.src = '';
|
|
const backgroundImageBack = document.createElement('img');
|
|
backgroundImageBack.id = 'backgroundImageBack';
|
|
backgroundImageBack.src = '';
|
|
backgroundArt.append(backgroundImage, backgroundImageBack);
|
|
|
|
infoBox.append(songInfo, backgroundArt);
|
|
|
|
widget.append(artBox, infoBox);
|
|
container.appendChild(widget);
|
|
}
|
|
}
|
|
|
|
if (window.SBdispatcher) {
|
|
SBdispatcher.on('musicPlaying', data => {
|
|
visibilityDuration = data.param1 || visibilityDefault;
|
|
showSongInfo();
|
|
});
|
|
}
|
|
|
|
function connectws() {
|
|
if ("WebSocket" in window) {
|
|
const CiderApp = io("http://localhost:10767/", {
|
|
transports: ['websocket']
|
|
});
|
|
|
|
CiderApp.on("disconnect", (event) => {
|
|
SetConnectionStatus(false);
|
|
setTimeout(connectws, 5000);
|
|
});
|
|
|
|
CiderApp.on("connect", (event) => {
|
|
SetConnectionStatus(true);
|
|
});
|
|
|
|
// Set up websocket artwork/information handling
|
|
CiderApp.on("API:Playback", ({ data, type }) => {
|
|
switch (type) {
|
|
// Song changes
|
|
case ("playbackStatus.nowPlayingItemDidChange"):
|
|
UpdateSongInfo(data);
|
|
break;
|
|
|
|
// Progress bar moves
|
|
case ("playbackStatus.playbackTimeDidChange"):
|
|
UpdateProgressBar(data);
|
|
break;
|
|
|
|
// Pause/unpause
|
|
case ("playbackStatus.playbackStateDidChange"):
|
|
UpdatePlaybackState(data);
|
|
break;
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
function showSongInfo() {
|
|
setTimeout(() => {
|
|
SetVisibility(true);
|
|
}, animationSpeed * 500);
|
|
|
|
if (visibilityDuration > 0) {
|
|
setTimeout(() => {
|
|
SetVisibility(false);
|
|
}, visibilityDuration * 1000);
|
|
}
|
|
}
|
|
|
|
function UpdateSongInfo(data) {
|
|
// Set the user's info
|
|
let albumArtUrl = data.artwork.url;
|
|
albumArtUrl = albumArtUrl.replace("{w}", data.artwork.width);
|
|
albumArtUrl = albumArtUrl.replace("{h}", data.artwork.height);
|
|
|
|
UpdateAlbumArt(document.getElementById("albumArt"), albumArtUrl);
|
|
UpdateAlbumArt(document.getElementById("backgroundImage"), albumArtUrl);
|
|
|
|
setTimeout(() => {
|
|
UpdateTextLabel(document.getElementById("songLabel"), data.name);
|
|
UpdateTextLabel(document.getElementById("artistLabel"), data.artistName);
|
|
}, animationSpeed * 500);
|
|
|
|
setTimeout(() => {
|
|
document.getElementById("albumArtBack").src = albumArtUrl;
|
|
document.getElementById("backgroundImageBack").src = albumArtUrl;
|
|
}, 2 * animationSpeed * 500);
|
|
|
|
showSongInfo()
|
|
|
|
}
|
|
|
|
function UpdateTextLabel(div, text) {
|
|
if (div.innerHTML != text) {
|
|
div.setAttribute("class", "text-fade");
|
|
setTimeout(() => {
|
|
div.innerHTML = text;
|
|
div.setAttribute("class", ".text-show");
|
|
}, animationSpeed * 250);
|
|
}
|
|
}
|
|
|
|
function UpdateAlbumArt(div, imgsrc) {
|
|
if (div.src != imgsrc) {
|
|
div.setAttribute("class", "text-fade");
|
|
setTimeout(() => {
|
|
div.src = imgsrc;
|
|
div.setAttribute("class", "text-show");
|
|
}, animationSpeed * 500);
|
|
}
|
|
}
|
|
|
|
function UpdateProgressBar(data) {
|
|
const progress = ((data.currentPlaybackTime / data.currentPlaybackDuration) * 100);
|
|
const progressTime = ConvertSecondsToMinutesSoThatItLooksBetterOnTheOverlay(data.currentPlaybackTime);
|
|
const duration = ConvertSecondsToMinutesSoThatItLooksBetterOnTheOverlay(data.currentPlaybackTimeRemaining);
|
|
document.getElementById("progressBar").style.width = `${progress}%`;
|
|
document.getElementById("progressTime").innerHTML = progressTime;
|
|
document.getElementById("duration").innerHTML = `-${duration}`;
|
|
}
|
|
|
|
function UpdatePlaybackState(data) {
|
|
console.log(data);
|
|
switch (data.state) {
|
|
case ("paused"):
|
|
case ("stopped"):
|
|
SetVisibility(false);
|
|
break;
|
|
case ("playing"):
|
|
UpdateSongInfo(data.attributes);
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
function ConvertSecondsToMinutesSoThatItLooksBetterOnTheOverlay(time) {
|
|
const minutes = Math.floor(time / 60);
|
|
const seconds = Math.trunc(time - minutes * 60);
|
|
|
|
return `${minutes}:${('0' + seconds).slice(-2)}`;
|
|
}
|
|
|
|
function SetVisibility(isVisible) {
|
|
widgetVisibility = isVisible;
|
|
|
|
const musicWidgetContainer = document.getElementById("musicWidgetContainer");
|
|
|
|
if (isVisible) {
|
|
var tl = new TimelineMax();
|
|
tl
|
|
.to(musicWidgetContainer, animationSpeed, { bottom: "50%", ease: Power1.easeInOut }, 'label')
|
|
.to(musicWidgetContainer, animationSpeed, { opacity: 1, ease: Power1.easeInOut }, 'label')
|
|
}
|
|
else {
|
|
var tl = new TimelineMax();
|
|
tl
|
|
.to(musicWidgetContainer, animationSpeed, { bottom: "45%", ease: Power1.easeInOut }, 'label')
|
|
.to(musicWidgetContainer, animationSpeed, { opacity: 0, ease: Power1.easeInOut }, 'label')
|
|
}
|
|
}
|
|
|
|
function SetConnectionStatus(connected) {
|
|
if (connected) {
|
|
console.log("Connected to Cider!");
|
|
}
|
|
else {
|
|
console.log("Not connected to Cider...");
|
|
}
|
|
}
|
|
|
|
function resize() {
|
|
const scale = window.innerWidth / maxWidth;
|
|
outer.style.transform = 'translate(0%, 0%) scale(' + scale + ')';
|
|
}
|
|
}).catch(err => console.error(err));
|
|
|
|
})(); |