<!DOCTYPE html>
<html>
<head>
  <!-- Edit Settings and store this file on LMS server - rename file at will
       Debian:  /usr/share/squeeeboxserver/HTML/Default/html 
       Windows: ???
       Version: 0.1.2 - 2021-21-01
  -->      
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <script>
    //-- Settings: ----------------------------------------------------------------------------------
    var clientID = "00:04:2e:1a:4e:a1"; // ususally but not always player's MAC address
    var serverAd = "http://192.168.1.253:9000/"; // ip address & port to your LMS server
    var interval = 3040;  // how frequently we ask server for updates, 3000 milliseconds = 3 second
    //-- End settings -------------------------------------------------------------------------------
    var xhttp = new XMLHttpRequest();
    var request = "{\"id\":1,\"method\":\"slim.request\",\"params\":[\"" + clientID + "\",[\"status\",\"-\",1,\"tags:oraculyB\"]]}"; //tags are like keywords to what servel will include in response
    var songid = "", curPos = "", duration = "", durationStr = "", mode = "stoppet", id = "";
    var ssaver = 0;    // screen saver active = 1
    //var serverstatus = "{\"id\":1,\"method\":\"slim.request\",\"params\":[\"\",[\"serverstatus\",0,999]]}"; //for future use
    
    function TSH(str) {
        https://stackoverflow.com/questions/7616461/generate-a-hash-from-string-in-javascript
        var h = 9;
        for (var i=0;i<str.length;i++) {
            h = Math.imul(h^str.charCodeAt(i), 9**9);    
        }
        return h^h >>> 9;
    }
    function actScreenSaver(){
        // here we can add code for loading screen saver photos
        if (mode == "stoppet") {clearScreen(); ssaver = 1;}
    }
    function addSecond() {
        if (mode == "spiller" && interval > 1000) {
            if (duration == "" || curPos < duration) {curPos += 1;}
            updatePosition()
        } 
    }
    function updatePosition() {
        if (ssaver == 0) {
            var str;
            if (duration == 0 || duration == "") {
                str = myTime(curPos);
            } else {
                str = myTime(curPos) + durationStr + myTime(duration);
            }
            document.getElementById("ptime").innerHTML = str;
        }
    }
    function myTime(seconds){
        // this function are liftet strait off the Default skin
        var remaining;
        if (seconds < 0) {
            remaining = true;
            seconds = Math.abs(seconds);
        }
        
        var hours = Math.floor(seconds / 3600);
        var minutes = Math.floor((seconds - hours*3600) / 60);
        seconds = Math.floor(seconds % 60);
        var formattedTime = (hours ? hours + ':' : '');
        formattedTime += (minutes ? (minutes < 10 && hours ? '0' : '') + minutes : '0') + ':';
        formattedTime += (seconds ? (seconds < 10 ? '0' : '') + seconds : '00');
        return (remaining ? '-' : '') + formattedTime;
    }
    function loadCoverArt() {
        // in attempt to fool cash on client side we add # + songid to src string
        var myimg = document.getElementById('cover');
        myimg.src = serverAd + "music/current/cover.jpg?player=" + clientID + "#" + songid;
        /* note: this work around are done due to server side url using coverid tag might 
        //       end up static for stream where cover art are updated but not the coverid
        //       ip:port/music/coverid/cover.jpg */
        /* debug: */
            var div = document.getElementById("cover");
            var rect = div.getBoundingClientRect();
            console.log("cover art size in px: ",'\n'," left: " + rect.left, '\n'," top: " + rect.top,'\n'," witch: " + rect.width,'\n'," height: " + rect.height);
        // */
    }
    function clearScreen(){
        var allP = document.getElementsByTagName("P");
        var i=0; var max=0;
        for (i=0, max=allP.length; i < max; i++) {
            allP[i].innerHTML = "";
            //allP[i].style.visibility = "hidden";
        }
    }
    function loaded() {
        loadCoverArt();
        clearScreen();
    }
    function postlms() {
        xhttp.open("POST", serverAd + "jsonrpc.js", true);
        xhttp.send(request);
        xhttp.overrideMimeType("text/plain")
        //xhttp.onloadstart = function(){document.getElementById("pconnection").innerHTML = "Loading...";} // flicker gets tedious
        xhttp.onerror   = function(){document.getElementById("pconnection").innerHTML = "Error";}
        xhttp.ontimeout = function(){document.getElementById("pconnection").innerHTML = "Connection timeout";}
        xhttp.onreadystatechange = function(){
            if (this.readyState == 4 && this.status == 200){
                var myObj = JSON.parse(this.responseText);
//console.log(myObj); // for debugging
                id = myObj.result.playlist_loop[0].id;
                  if (typeof(id) == 'undefined') {id="";}
                duration = myObj.result.duration;
                  if (typeof(duration) == 'undefined' || duration == 0) {
                    duration=""; 
                    durationStr = "";
                  } else {
                    durationStr = " | ";
                  }
                mode         = myObj.result.mode;
                  if (typeof(mode) == 'undefined') {mode="stop";}
                  if (mode=="stop") {mode="stoppet";} 
                  if (mode=="play") {mode="spiller"}
                var time     = myObj.result.time;
                  if (typeof(time) == 'undefined') {time="";}
                var artist   = myObj.result.playlist_loop[0].artist;
                  if (typeof(artist) == 'undefined') {artist="";}
                var title    = myObj.result.playlist_loop[0].title;
                  if (typeof(title) == 'undefined') {title="";}
                var album    = myObj.result.playlist_loop[0].album;
                  if (typeof(album) == 'undefined') {album="";} else {album = "ALBUM: " + album;}
                var bitrate  = myObj.result.playlist_loop[0].bitrate;
                  if (typeof(bitrate) == 'undefined') {bitrate="";}
                var type     = myObj.result.playlist_loop[0].type;
                  if (typeof(type) == 'undefined') {type="";}
                var year     = myObj.result.playlist_loop[0].year;
                  if (typeof(year) == 'undefined' || year<1) {year="";} else {year = "UTGIVELSESÅR: " + year;}
                var url      = myObj.result.playlist_loop[0].url;
                  if (typeof(url) == 'undefined') {url="";}
                var tmp      = url.split(":"); 
                var source   = tmp[0]; // first part of song's url used to identify source
                curPos = time;         // also updated from 1 second ticker
                
                if (mode == "spiller") {ssaver = 0;}
                if (ssaver == 0) {
                    // for some radio streams the song id tag is static even when song and cover change 
                    // hence the need for a unique identifier build form multiple datafields
                    if (songid != TSH(artist+title+id)){
                        songid = TSH(artist+title+id);
                        loadCoverArt();
                    }
                    document.getElementById("partist").innerHTML = artist;
                    document.getElementById("ptitle").innerHTML = title;
                    document.getElementById("palbum").innerHTML = album;
                    document.getElementById("pyear").innerHTML = year;
                    updatePosition() // song position
                    document.getElementById("pmode").innerHTML = myObj.result.mode.toUpperCase();
                    document.getElementById("psource").innerHTML = source.toUpperCase();
                    document.getElementById("pmode").innerHTML = mode.toUpperCase();
                    document.getElementById("pbitrate").innerHTML = bitrate + " " + type.toUpperCase();
                    document.getElementById("pconnection").innerHTML = "";
                }
            }
        }
    }
    // sadly these intervall timers seem to be disabled on 2017 Samsung TV 
    var si = setInterval(postlms, interval);    // pull JSON
    var ti = setInterval(addSecond, 1000);      // trigger second counter
    var ss = setInterval(actScreenSaver, 120000);// 
  </script>
  <style>
    * {
        box-sizing: border-box;
    }
    html {
        height: 100%;
        background-color: SlateGray;
        -webkit-background-size: cover;
        -moz-background-size: cover;
        -o-background-size: cover;
        background-size: cover;
        background: SlateGray;
        background-repeat:no-repeat;
        background: -webkit-linear-gradient( to left top, SlateGray, Black);
        background: -moz-linear-gradient( to left top, SlateGray, Black);
        background: -ms-linear-gradient( to left top, SlateGray, Black);
        background: -o-linear-gradient( to left top, SlateGray, Black);
        background: linear-gradient( to left top, SlateGray, Black);
    }
    img {
        text-align: center;
        position: absolute;
        margin: auto;
        top: 0;
        right: 0;
        bottom: 0;
        left: 0;
        height: 98%;
        transform:rotate(0deg);
        z-index: -1;
    }
    p {
        color: white;
        white-space: pre-wrap;
        overflow-wrap: break-word;
        overflow: visible;
        position: absolute;
        width: 20vw;
        font-size: 1.2vw;
    }
    #partist {
        position: relative;
        left: 1.2vw;
        font-size: 2.2vw;
    }
    #ptitle{
        position: relative;
        left: 1.2vw;
        font-size: 1.8vw;
        text-overflow: ellipsis;   
    }
    #palbum {
        position: relative;
        margin-top: 10vh;
        left: 1.2vw;
        text-overflow: ellipsis;  
    }
    #pyear {
        position: relative;
        left: 1.2vw;
    }
    #ptime {
        bottom: 0vh;
        text-align: center;
        font-size: 3.6vw;
    }
    
    #psource {
        position: absolute;
        top: 1vh;
        right:2vw;
        text-align: right;
        font-size: 2.2vw;
    }
    #pmode {
        position: absolute;
        top: 10vh;
        right:2vw;
        text-align: right;
    }
    #pconnection {
        position: absolute;
        bottom: 8vh;
        right:1vw;
        text-align: right;
    }
    #pbitrate {
        position: absolute;
        right:1vw;
        bottom: 3vh;
        text-align: right;
    }
  </style>
</head>
<body onload="loaded()" >
        <p id="partist">Artist</p>
        <p id="ptitle">Track Name</p>
        <p id="palbum">Album</p>
        <p id="pyear">Year</p>
        <p id="ptime">0:00 | 0:00</p>
        <img id="cover" alt="Album Cover Art" src="">
        <p id="psource">Source</p>
        <p id="pbitrate">bitrate type</p>
        <p id="pconnection">connection status</p>
        <p id="pmode">Mode</p>
</body>
</html>