var selected = ""; var shows = []; 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; var currentShows = []; 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; if (checkNew(resp[i].listenurl) && !first) { addMsg("Ha comenzado una nueva transmisión: " + resp[i].server_name); } currentShows.push(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]; shows = currentShows; 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 currentSong = 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 += '
' + currentSong + '
'; 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 checkNew(mount) { var isNew = true; for (var i = -1; ++i < shows.length;) { if (mount == shows[i]) { isNew = false; break; } } if (isNew) { shows.push(mount); } return isNew; } 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 show = document.getElementById("current_server").value; if (!msg) { return; } if (chatConnected) { sendMsg("MSG:" + escapeColon(show) + ":" + escapeColon(msg)); addMsg(msg, show, 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 currentShow = document.getElementById("current_server").value; var style = document.createElement("style"); style.id = "chat-filter"; style.textContent = '[data-stream] { display: none; }'; style.textContent += '[data-stream^="' + currentShow + '"] { 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(); });