orchard/oldshit/resources/web-remote/index.js
2021-12-04 00:04:04 -06:00

619 lines
No EOL
20 KiB
JavaScript

var socket;
Vue.component('footer-player', {
template: '#footer-player'
});
// vue instance
var app = new Vue({
el: '#app',
data: {
screen: "player",
player: {
currentMediaItem: {},
songActions: false,
lyrics: {},
lyricsMediaItem: {},
lyricsDebug: {
current: 0,
start: 0,
end: 0
},
queue: {},
lowerPanelState: "controls",
userInteraction: false
},
queue: {
temp: []
},
artistPage: {
data: {},
editorsNotes: false
},
albumPage: {
data: {},
editorsNotes: false
},
search: {
query: "",
results: [],
state: 0,
tab: "all",
searchType: "applemusic",
trackSelect: false,
selected: {},
queue: {},
lastPage: "search",
lastY: 0
},
lastPage: "player",
connectedState: 0,
url: window.location.hostname,
mode: "default",
// url: "localhost",
},
methods: {
searchScroll(e) {
this.search.lastY = e.target.scrollTop;
},
musicKitAPI(method, id, params) {
socket.send(
JSON.stringify({
action: "musickit-api",
method: method,
id: id,
params: params
})
)
},
resetPlayerUI() {
this.player.lowerPanelState = "controls";
},
musicAppVariant() {
if (navigator.userAgent.match(/Android/i)) {
return "Apple Music";
} else if (navigator.userAgent.match(/iPhone|iPad|iPod/i)) {
return "Music";
} else {
if (navigator.userAgent.indexOf('Mac') > 0) {
return 'Music';
} else if (navigator.userAgent.indexOf('Win') > 0) {
return 'Apple Music Electron';
} else {
return 'Apple Music Electron';
}
}
},
checkOrientation() {
// check orientation of device
if (window.innerHeight > window.innerWidth) {
return 'portrait'
} else {
return 'landscape';
}
},
checkPlatformMD() {
// check if platfom is desktop or mobile
if (navigator.userAgent.match(/Android/i)) {
return "mobile";
} else if (navigator.userAgent.match(/iPhone|iPad|iPod/i)) {
return "mobile";
} else {
if (navigator.userAgent.indexOf('Mac') > 0) {
return 'desktop';
} else if (navigator.userAgent.indexOf('Win') > 0) {
return 'desktop';
} else {
return 'desktop';
}
}
},
checkPlatform() {
if (navigator.userAgent.match(/Android/i)) {
return "android";
} else if (navigator.userAgent.match(/iPhone|iPad|iPod/i)) {
return "ios";
} else {
if (navigator.userAgent.indexOf('Mac') > 0) {
return 'mac';
} else if (navigator.userAgent.indexOf('Win') > 0) {
return 'win';
} else {
return 'linux';
}
}
},
artworkPlaying() {
if (this.player.currentMediaItem.status) {
return
} else {
return ["paused"]
}
},
setAutoplay(value) {
socket.send(JSON.stringify({
"action": "set-autoplay",
"autoplay": value
}));
this.getCurrentMediaItem()
if (value) {
setTimeout(() => {
this.getQueue()
}, 1000)
} else {
this.getQueue()
}
},
seekTo(time, adjust = true) {
if (adjust) {
time = parseInt(time / 1000)
}
socket.send(JSON.stringify({
action: "seek",
time: time
}));
},
setVolume(volume) {
socket.send(JSON.stringify({
action: "volume",
volume: volume
}));
},
getQueue() {
socket.send(JSON.stringify({
action: "get-queue"
}))
},
play() {
socket.send(JSON.stringify({
action: "play"
}))
},
pause() {
socket.send(JSON.stringify({
action: "pause"
}))
},
next() {
socket.send(JSON.stringify({
action: "next"
}))
},
previous() {
socket.send(JSON.stringify({
action: "previous"
}))
},
searchArtist() {
this.search.query = this.player.currentMediaItem.artistName;
this.screen = "search";
this.searchQuery();
},
trackSelect(song) {
this.search.selected = song;
this.search.trackSelect = true
},
clearSelectedTrack() {
this.search.selected = {}
this.search.trackSelect = false
},
getArtworkColor(hex) {
return `#${hex}`
},
playMediaItemById(id, kind = "song") {
socket.send(JSON.stringify({
action: "play-mediaitem",
id: id,
kind: kind
}))
this.screen = "player";
},
playNext(type, id) {
socket.send(JSON.stringify({
action: "play-next",
type: type,
id: id
}))
},
playLater(type, id) {
socket.send(JSON.stringify({
action: "play-later",
type: type,
id: id
}))
},
searchQuery() {
if (this.search.query.length == 0) {
this.search.state = 0;
return;
}
this.search.state = 1;
var actionType = "search"
if (this.search.searchType == "library") {
actionType = "library-search"
}
socket.send(JSON.stringify({
"action": actionType,
"term": this.search.query,
"limit": 20
}))
},
quickSearch() {
var search = prompt("Search for a song", "")
if (search == null || search == "") {
return
}
socket.send(JSON.stringify({
action: "quick-play",
term: search
}))
},
parseTime(value) {
var minutes = Math.floor(value / 60000);
var seconds = ((value % 60000) / 1000).toFixed(0);
return minutes + ":" + (seconds < 10 ? '0' : '') + seconds;
},
parseTimeDecimal(value) {
var minutes = Math.floor(value / 60000);
var seconds = ((value % 60000) / 1000).toFixed(0);
return minutes + "." + (seconds < 10 ? '0' : '') + seconds;
},
hmsToSecondsOnly(str) {
var p = str.split(':'),
s = 0,
m = 1;
while (p.length > 0) {
s += m * parseInt(p.pop(), 10);
m *= 60;
}
return s;
},
getCurrentTime() {
return parseFloat(this.hmsToSecondsOnly(this.parseTime(this.player.currentMediaItem.durationInMillis - this.player.currentMediaItem.remainingTime)));
},
percentage(partial, full) {
return (100 * partial) / full
},
getLyricBGStyle(start, end) {
var currentTime = this.getCurrentTime();
var duration = this.player.currentMediaItem.durationInMillis
var start2 = this.hmsToSecondsOnly(start)
var end2 = this.hmsToSecondsOnly(end)
var currentProgress = ((100 * (currentTime)) / (end2))
// check if currenttime is between start and end
this.player.lyricsDebug.start = start2
this.player.lyricsDebug.end = end2
this.player.lyricsDebug.current = currentTime
if (currentTime >= start2 && currentTime <= end2) {
return {
"--bgSpeed": `${(end2 - start2)}s`
}
} else {
return {}
}
},
getLyricClass(start, end) {
var currentTime = this.getCurrentTime();
// check if currenttime is between start and end
if (currentTime >= start && currentTime <= end) {
setTimeout(() => {
if (document.querySelector(".lyric-line.active")) {
document.querySelector(".lyric-line.active").scrollIntoView({
behavior: "smooth",
block: "center"
})
}
}, 200)
return "active"
} else {
return ""
}
},
getAlbumArtUrl(size = 600) {
if (this.player.currentMediaItem.artwork) {
return `url("${this.player.currentMediaItem.artwork.url.replace('{w}', size).replace('{h}', size)}")`;
} else {
return "";
}
},
getAlbumArtUrlList(url, size = 64) {
return `url("${url.replace('{w}', size).replace('{h}', size)}")`;
},
searchTabClass(tab) {
if (tab == this.search.tab) {
return "active";
}
},
searchTypeClass(type) {
if (type == this.search.searchType) {
return "active";
}
},
getQueuePositionClass(position) {
if (this.player.queue["_position"] == position) {
return ["playing", "passed"]
} else if (this.player.queue["_position"] > position) {
return ["passed"]
}
},
showSearch(reset = false) {
if(reset) {
this.search.lastPage = "search"
}
switch(this.search.lastPage) {
case "search":
this.screen = "search"
break;
case "album":
this.screen = "album-page"
break;
case "artist":
this.screen = "artist-page"
break;
case "playlist":
this.screen = "playlist-page"
break;
}
},
showArtistByName(name) {
this.musicKitAPI("search", name, {types: "artists"})
},
showAlbum(id) {
this.search.lastPage = "album"
this.screen = "album-page"
this.musicKitAPI("album", id, {})
},
showArtist(id) {
this.search.lastPage = "artist"
this.screen = "artist-page"
this.musicKitAPI("artist", id, {include: "songs,playlists,albums"})
},
showQueue() {
this.queue.temp = this.player["queue"]["_queueItems"]
this.screen = "queue"
this.getQueue()
},
queueMove(evt) {
console.log(evt)
console.log(`new: ${evt.moved.newIndex} old: ${evt.moved.oldIndex}`)
this.queue.temp.splice(evt.moved.newIndex, 0, this.queue.temp.splice(evt.moved.oldIndex, 1)[0])
socket.send(JSON.stringify({
action: "queue-move",
from: evt.moved.oldIndex,
to: evt.moved.newIndex
}))
this.getQueue()
return true
},
repeat() {
socket.send(JSON.stringify({
action: "repeat"
}))
this.getCurrentMediaItem()
},
shuffle() {
socket.send(JSON.stringify({
action: "shuffle"
}))
this.getCurrentMediaItem()
},
setShuffle(val) {
socket.send(JSON.stringify({
action: "set-shuffle",
shuffle: val
}))
this.getCurrentMediaItem()
},
getMediaPalette(data) {
var palette = {
'--bgColor': `#${data['artwork']['bgColor']}`,
'--textColor1': `#${data['artwork']['textColor1']}`,
'--textColor2': `#${data['artwork']['textColor2']}`,
'--textColor3': `#${data['artwork']['textColor3']}`,
'--textColor4': `#${data['artwork']['textColor4']}`
}
return palette
},
playAlbum(id, shuffle = false) {
if(shuffle) {
this.setShuffle(true)
}else{
this.setShuffle(false)
}
this.playMediaItemById(id, 'album');
},
getLyrics() {
socket.send(JSON.stringify({
action: "get-lyrics",
}))
},
showLyrics() {
this.getLyrics()
this.screen = "lyrics"
},
showLyricsInline() {
this.getLyrics()
this.player.lowerPanelState = "lyrics"
},
parseLyrics() {
var xml = this.stringToXml(this.player.lyricsMediaItem.ttml)
var json = xmlToJson(xml);
this.player.lyrics = json
},
stringToXml(st) {
// string to xml
var xml = (new DOMParser()).parseFromString(st, "text/xml");
return xml;
},
canShowSearchTab(tab) {
if (tab == this.search.tab || this.search.tab == "all") {
return true;
} else {
return false;
}
},
getCurrentMediaItem() {
socket.send(JSON.stringify({
action: "get-currentmediaitem"
}))
},
setStreamerOverlay() {
document.body.classList.add("streamer-overlay")
},
setMode(mode) {
switch(mode) {
default:
this.screen = "player"
break;
case "miniplayer":
this.screen = "miniplayer"
break;
}
},
connect() {
let self = this;
this.connectedState = 0;
if (this.url === "") {
this.url = prompt("Host IP", "localhost")
}
socket = new WebSocket(`ws://${this.url}:26369`);
socket.onopen = (e) => {
console.log(e);
console.log('connected');
app.connectedState = 1;
if(getParameterByName("mode")) {
self.setMode(getParameterByName("mode"))
}else{
self.setMode("default")
}
self.clearSelectedTrack()
}
socket.onclose = (e) => {
console.log(e);
console.log('disconnected');
app.connectedState = 2;
}
socket.onerror = (e) => {
console.log(e);
console.log('error');
app.connectedState = 2;
}
socket.onmessage = (e) => {
const response = JSON.parse(e.data);
switch (response.type) {
default:
console.log(response);
break;
case "musickitapi.search":
self.showArtist(response.data["artists"][0]["id"]);
break;
case "musickitapi.album":
if(self.screen == "album-page") {
self.albumPage.data = response.data
}
break;
case "musickitapi.artist":
if(self.screen == "artist-page") {
self.artistPage.data = response.data
}
break;
case "queue":
self.player.queue = response.data;
self.queue.temp = response.data["_queueItems"];
self.$forceUpdate()
break;
case "lyrics":
self.player.lyrics = response.data;
self.$forceUpdate()
break;
case "searchResultsLibrary":
self.search.results = response.data;
self.search.state = 2;
break;
case "searchResults":
self.search.results = response.data;
self.search.state = 2;
break;
case "playbackStateUpdate":
if (!self.player.userInteraction) {
self.updatePlaybackState(response.data)
}
break;
}
// console.log(e.data);
}
},
updatePlaybackState(mediaitem) {
var lyricsDisplayed = this.screen == "lyrics" || this.player.lowerPanelState == "lyrics"
if (this.player.currentMediaItem["isrc"] != mediaitem["isrc"]) {
if (lyricsDisplayed) {
this.getLyrics()
}
if (this.screen == "queue") {
this.getQueue()
}
}
this.player.currentMediaItem = mediaitem
}
},
});
function getParameterByName(name, url) {
if (!url) url = window.location.href;
name = name.replace(/[\[\]]/g, '\\$&');
var regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)'),
results = regex.exec(url);
if (!results) return null;
if (!results[2]) return '';
return decodeURIComponent(results[2].replace(/\+/g, ' '));
}
function xmlToJson(xml) {
// Create the return object
var obj = {};
if (xml.nodeType == 1) { // element
// do attributes
if (xml.attributes.length > 0) {
obj["@attributes"] = {};
for (var j = 0; j < xml.attributes.length; j++) {
var attribute = xml.attributes.item(j);
obj["@attributes"][attribute.nodeName] = attribute.nodeValue;
}
}
} else if (xml.nodeType == 3) { // text
obj = xml.nodeValue;
}
// do children
if (xml.hasChildNodes()) {
for (var i = 0; i < xml.childNodes.length; i++) {
var item = xml.childNodes.item(i);
var nodeName = item.nodeName;
if (typeof (obj[nodeName]) == "undefined") {
obj[nodeName] = xmlToJson(item);
} else {
if (typeof (obj[nodeName].push) == "undefined") {
var old = obj[nodeName];
obj[nodeName] = [];
obj[nodeName].push(old);
}
obj[nodeName].push(xmlToJson(item));
}
}
}
return obj;
};
window.onresize = function () {
app.resetPlayerUI()
}
app.connect()