summaryrefslogblamecommitdiff
path: root/bairadio.js
blob: 104e2f3ef4f5a300987e96201e2f4493a1eeda0e (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12
                  
 


                             






                                                       







                                                                         


                                    





                                                              





                                                       
      


                                          
                                

                                                                                        
 
                                                       

                           

                                            
                                                 








                                                                                                 


                           
                               
      


                                                                    
                                                    
                                                                               


                                        
                                                                         
       


                                                           

                                         
                                                            


                                                   
                                


                       
                                               
              
                                     
       










                                                                           

                                                                              
       
 
                                  



                                                           
       



                                                                      

















                                                    
                         

                
                                             

                                       






                                                         

     
 



                      
                                                   

                                                        

                                                              
  


                             
                              
                                                
                               




                                                                                                                                                                                                                                             





                                                                
                                                

                     
                                          
          
                  
                                         


























                                                                   
                           


                                                      
                                  
                                     


                                                                        
   
                                   


              
                         
                     
                           





                                                          
                                           














                                                                                  


                           
                                                                      
                                             
                         
                            























                                                                                              
                                          
                                 
                                                               



                                                                 








                                                     
                                  
                                                               
                       

                      

                                                                   
                    


















                                                      
                                         

                               
                         
                                                 
 
                                           
                                                                      
                                                                 




                                                



                                            




                                     

















                                                                                
                                                          
                                                                          
                                                                                



                                                                                 

                                                         




                                                         
   





















                                                                                  

               
                       
                            

            
var selected = "";

function update(first) {
  var first = first || false;
  
  var req = new XMLHttpRequest();
  var url = "https://bienvenidoainternet.org:8443";
  req.open("GET", url+"/status-json.xsl", true);
  req.send();
  req.onreadystatechange = function() {
    if (this.readyState === 4 && this.status === 200) {
      var resp = JSON.parse(req.response);
      
      var status = document.getElementById("status");
      var artist = document.getElementById("artist");
      var title = document.getElementById("title");
      var bitrate = document.getElementById("bitrate");
      var audio_samplerate = document.getElementById("audio_samplerate");
      var listeners = document.getElementById("listeners");
      
      if (resp.icestats.source) {
        resp = resp.icestats.source;
      } else {
        artist.textContent = "";
        title.textContent = "";
        bitrate.textContent = "--";
        audio_samplerate.textContent = "--";
        listeners.textContent = "0";
        status.textContent = "*** La radio está OFFLINE ***";
        var o = document.createElement("option");
        o.textContent = "Nadie está transmitiendo...";
        sel.appendChild(o);
        selected = "";
        return;
      }
      
      if (!resp.length) { resp = [resp]; }
      
      if (first || !selected) {
        status.textContent = "";
        selected = resp[0].listenurl.replace("http://bienvenidoainternet.org:8000", "");
      }

      var sel = document.getElementById("server_name");
      sel.textContent = "";

      var selectedPos = 0;
      for (var i = -1; ++i < resp.length;) {
        var o = document.createElement("option");
        resp[i].listenurl = resp[i].listenurl.replace("http://bienvenidoainternet.org:8000", "");
        o.value = resp[i].listenurl;
        o.textContent = resp[i].server_name;
        if (resp[i].server_description) {
          o.textContent += ": " + resp[i].server_description;
        }
        if (resp[i].listenurl == selected) {
          o.defaultSelected = true;
          selectedPos = i;
        }
        sel.appendChild(o);
      }
      resp = resp[selectedPos];
      
      var currentListen = document.getElementById("current_server");
      currentListen.value = resp.server_name;
      
      var audio = document.getElementById("stream");
      resp.listenurl = "https://bienvenidoainternet.org:8443" + resp.listenurl;
      if (audio.src != resp.listenurl) {
        audio.src = resp.listenurl;
        if (!first) { playPause(); }
        if (document.getElementById("chat-filter")) { filterChat(true); }
      }

      var current = artist.textContent + title.textContent;
            
      if (resp.artist) {
        resp.artist = resp.artist.trim();
        if (artist.textContent.slice(0,-3) != resp.artist) {
          artist.textContent = resp.artist + " - ";
        }
      } else {
        artist.textContent = "";
      }

      if (resp.title) {
        resp.title = String(resp.title).trim();
      } else {
        resp.title = "(Sin título)";
      }
      if (title.textContent != resp.title) {
        var history = document.getElementById("history");
        history.innerHTML += '<div class="pastsong">' + current + '</div>';
        history.scrollTop = history.scrollHeight;
        
        title.textContent = resp.title;
        document.title = resp.title + " @ Radio B.a.I.";
        
        checkLong();
      }

      if (resp["ice-bitrate"] && bitrate.textContent != resp["ice-bitrate"]) {
        bitrate.textContent = resp["ice-bitrate"];
      }

      if (resp.audio_samplerate) {
        var khz = Math.round(resp.audio_samplerate / 1000);
        if (audio_samplerate.textContent != khz) {
          audio_samplerate.textContent = khz;
        }
      }

      if (resp.listeners && listeners.textContent != resp.listeners) {
        listeners.textContent = resp.listeners;
      }
    }
  }
}

function startVisualization() {
  var ctx = new AudioContext();  
  var audio = document.getElementById("stream");
  var src = ctx.createMediaElementSource(audio);
  var anal = ctx.createAnalyser();
  src.connect(anal);
  src.connect(ctx.destination);
  var freq = new Uint8Array(anal.frequencyBinCount);
  
  function renderVis() {
    requestAnimationFrame(renderVis);
    anal.getByteFrequencyData(freq);
    
    var vis = document.getElementById("vis");
    vis.textContent = "";
    var div = 3;
    
    var svgns = "http://www.w3.org/2000/svg";
    for (var i = 0; i < 900; i += 20) {
      var h = (freq[i] / div);
      var rect = document.createElementNS(svgns, "rect");
      rect.setAttributeNS(null, "x", (i / 10));
      rect.setAttributeNS(null, "y", ((255 / div) - h));
      rect.setAttributeNS(null, "height", h);
      rect.setAttributeNS(null, "width", "1");
      rect.setAttributeNS(null, "class", "bar");
      vis.appendChild(rect);
    }
  }

  renderVis();
}

function checkLong() {
  var cont = document.getElementById("nowplaying");
  var strip = document.getElementById("nowplaying-txt");
  
  var marquee = document.getElementById("marquee-style");
  if (marquee) { marquee.parentElement.removeChild(marquee); }
  
  var ws = strip.clientWidth;
  var wc = cont.clientWidth
  if (ws > wc) {
    var travel = ws - (wc-10);
    var style = document.createElement("style");
    style.id = "marquee-style";
    var dur = Math.round(travel/10);
    if (dur < 3) { dur++; }
    style.textContent = "#nowplaying-txt {\n -webkit-animation: marquee " + dur + "s linear infinite;\n animation: marquee " + dur + "s linear infinite;\n}\n";
    style.textContent += "@-webkit-keyframes marquee {\n 10% { transform: translateX(0); }\n 45% { transform: translateX(-" + travel + "px); }\n 55% { transform: translateX(-" + travel + "px); }\n 90% { transform: translateX(0); }\n}\n";
    style.textContent += "@keyframes marquee {\n 10% { transform: translateX(0); }\n 45% { transform: translateX(-" + travel + "px); }\n 55% { transform: translateX(-" + travel + "px); }\n 90% { transform: translateX(0); }\n}";
    document.getElementsByTagName("head")[0].appendChild(style);
  }
}

function playPause() {
  var radio = document.getElementById("stream");
  var stat = document.getElementById("control");
  if (radio.paused) {
    radio.play();
    stat.setAttribute("class", "playing");
  } else {
    radio.pause();
    stat.setAttribute("class", "paused");
  }
}

function changeVolume(e) {
  var mousepos = e.x;
  document.addEventListener("mousemove", setVolume);
  document.addEventListener("mouseup", function() {
    document.removeEventListener("mousemove", setVolume);
  });
  
  function setVolume(e) {
    var audio = document.getElementById("stream");
    var dx = mousepos - e.x;
    mousepos = e.x;

    var vol = document.getElementById("volume");
    var newvol = Math.round(parseInt(vol.textContent) + (dx * -1));
    if (newvol < 0) { newvol = 0; }
    else if (newvol > 100) { newvol = 100; }
    
    vol.textContent = (newvol < 10) ? ("0" + newvol) : newvol;
    audio.volume = newvol / 100;
    
    removeSel();
  }
}

function collapsePanel(e) {
  var box = this.parentElement.parentElement;
  var cont = box.getElementsByClassName("content")[0];
  if (box.classList.contains("collapse")) {
    cont.removeAttribute("style");
    box.classList.remove("collapse");
  } else {
    box.classList.add("collapse");
    cont.style.width = (box.clientWidth - this.clientWidth - 14) + "px";
  }
  box.scrollTop = box.scrollHeight;
  removeSel();
}

function resizePanel(e) {
  var mousepos = e.y;
  var id = this.dataset.id;
  document.addEventListener("mousemove", calcResize);
  document.addEventListener("mouseup", function() {
    document.removeEventListener("mousemove", calcResize);
  });
  
  function calcResize(e) {
    var chat = document.getElementById(id);
    var dx = mousepos - e.y;
    mousepos = e.y;
    chat.style.height = (parseInt(getComputedStyle(chat, "").height) - dx) + "px";
    chat.scrollTop = chat.scrollHeight;
    removeSel();
  }
}

function removeSel() {
  if (document.selection) { document.selection.empty(); }
  else { window.getSelection().removeAllRanges(); }
}

var chatConnected = false;
var antiFlood = false;
const chatFloodTime = 1100;

function connect() {
  sock = new WebSocket("wss://radio.bienvenidoainternet.org/daemon/");
  sock.addEventListener("open", function(e) {
    chatConnected = true;
    sock.send("HISTORY:10");
    enableChat();
  });
  sock.addEventListener("message", function(e) {
    interpretNewMsg(e.data);
  });
  sock.addEventListener("close", function(e) {
    addMsg("Desconectado del chat. " + (e.reason ? "Razón: "+e.reason : "Código: "+e.code));
    document.getElementById("chat-count").textContent = "";
    chatConnected = false;
  });
  
  document.getElementById("msg_send").addEventListener("click", checkSend);
}

function enableChat() {
  antiFlood = false;
  document.getElementById("msg_send").disabled = false;
}

function interpretNewMsg(info) {
  console.log("<<< " + info);
  var arg = info.split(":");
  
  if (arg[0] == "MSG") {
    addMsg(unescapeColon(arg[2]), arg[1]);
  } else if (arg[0] == "COUNT") {
    document.getElementById("chat-count").textContent = arg[1];
  } else if (arg[0] == "HMSG") {
    addMsg(unescapeColon(arg[3]), unescapeColon(arg[2]), arg[1]);
  } else if (arg[0] == "HISTORY_OK") {
    addMsg("Conectado al chat.");
  }
}

function checkSend(e) {
  e.preventDefault();
  if (!chatConnected) return;
  if (antiFlood) return;
  
  var msgField = document.getElementById("msg_type");
  var msg = msgField.value.trim();
  var stream = document.getElementById("current_server").value;
  if (!msg) { return; }
  
  if (chatConnected) {
    sendMsg("MSG:" + escapeColon(stream) + ":" + escapeColon(msg));
    addMsg(msg, stream, false, true);
  } else { return; }
  
  msgField.value = "";
  antiFlood = true;
  document.getElementById("msg_send").disabled = true;
  setTimeout(enableChat, chatFloodTime);
}

function escapeColon(msg) {
  return msg ? msg.replace(/:/g, "%3A") : "";
}
function unescapeColon(msg) {
  return msg ? msg.replace(/%3A/g, ":") : "";
}

function sendMsg(msg) {
  console.log(">>> " + msg);
  sock.send(msg);
}

function addMsg(msg, stream, time, own) {
  var time = time || false;
  var stream = stream || false;
  var own = own || false;
  var chat = document.getElementById("chat-all");

  var line = document.createElement("div");
  line.className = (own ? "msg own" : (time ? "msg history" : "msg"));
  var presentTime = (time ? new Date(Number(time)) : new Date());
  var hh = presentTime.getHours();
  hh = (hh < 10) ? ("0" + hh) : hh;
  var mm = presentTime.getMinutes();
  mm = (mm < 10) ? ("0" + mm) : mm;
  line.textContent = "[" + hh + ":" + mm + "] ";
  if (stream) {
    line.textContent += "(" + stream + ") ";
    line.dataset.stream = stream;
  }
  line.textContent += msg;

  chat.appendChild(line);
  chat.scrollTop = chat.scrollHeight;
}

function filterChat(enable) {
  var filter = document.getElementById("chat-filter");
  if (filter) { filter.parentElement.removeChild(filter); }
  
  if (enable) {
    var current = document.getElementById("current_server").value;
    var style = document.createElement("style");
    style.id = "chat-filter";
    style.textContent = '[data-stream] { display: none; }';
    style.textContent += '[data-stream^="' + current + '"] { display: block; }';
    document.getElementsByTagName("head")[0].appendChild(style);
  }
  
  var chat = document.getElementById("chat-all"); 
  chat.scrollTop = chat.scrollHeight;
}

document.addEventListener("DOMContentLoaded", function() {
  document.getElementById("control").addEventListener("click", playPause);
  document.getElementById("volume").addEventListener("mousedown", changeVolume);
  document.getElementById("server_name").addEventListener("change", function(e) {
    selected = this.value;
  });
  
  var boxt = document.getElementsByClassName("boxtitle");
  for (var i = -1; ++i < boxt.length;) {
    boxt[i].addEventListener("click", collapsePanel);
  }
  var resize = document.getElementsByClassName("resize");
  for (var i = -1; ++i < resize.length;) {
    resize[i].addEventListener("mousedown", resizePanel);
  }
  
  document.getElementById("show_own").addEventListener("click", function(e) {
    if (document.body.hasAttribute("class")) {
      document.body.removeAttribute("class");
      this.className = "btn toggle-off";
    } else {
      document.body.className = "show-own";
      this.className = "btn toggle-on";
    }
  });
  document.getElementById("stream_filter").addEventListener("click", function(e) {
    if (document.getElementById("chat-filter")) {
      filterChat(false);
      this.className = "btn toggle-off";
    } else {
      filterChat(true);
      this.className = "btn toggle-on";
    }
  });
  document.getElementById("clear_chat").addEventListener("click", function(e) {
    document.getElementById("chat-all").textContent = "";
  });

  update(true);
  startVisualization();
  setInterval(update, 2000);
  connect();
});