let leRadio = [ { "name": "Radio Onda Rossa", "website": "https://www.ondarossa.info"}, { "name": "Radio Spore", "website": "https://radiospore.oziosi.org" }, { "name": "Radio Gramma", "website": "https://test.radiogramma.org" }, ] let playlist = [] let audio = document.querySelector("#radio"); /* Avoids "mixed content" problems, hoping for the best */ function httpsIze(url) { if(location.protocol === 'https:' && url.startsWith('http:')) { return url.replace('http:', 'https:') } return url } class Player { constructor(audioEl) { this.audioEl = audioEl } changeStreamURLs(urls) { this.audioEl.pause() this.audioEl.innerHTML = '' urls.forEach((url) => { let src = document.createElement('source') src.setAttribute('src', url) this.audioEl.appendChild(src) }) this.audioEl.load() this.audioEl.play() } } function downloadPlaylist() { let m3u = "#EXTM3U\n" m3u = playlist.reduce((data, track) => { data += `#EXTINF:${track.itunes.duration},${track.itunes.name} \n` data += `${track.enclosure}\n` return data }, m3u) console.log(m3u) const blob = new Blob([m3u], { 'type': 'audio/x-mpegurl'}); const m3uFile = window.URL.createObjectURL(blob); var a = document.createElement("a"); a.style = "display: none"; document.body.appendChild(a); url = window.URL.createObjectURL(blob); a.href = url; a.download = "playlist.m3u"; a.click(); window.URL.revokeObjectURL(url); } async function main() { let radio = null let player = new Player(audio) async function deployRadio(website) { radio = await radiomanifest.get(httpsIze(website)) document.querySelector('#radio-name').textContent = 'Loading ...' document.querySelector('#program-name').textContent = 'Loading ...' let urls = await radio.getStreaming().pickURLs() urls = urls.map(httpsIze) player.changeStreamURLs(urls) document.querySelector('#radio-name').textContent = radio.getName() let showName = '' try { const show = radio.getShowAtTime() if (show !== null) { showName = show.getName() } } catch { true; } document.querySelector('#program-name').textContent = showName setupProgrammi() } const playButton = document.querySelector("#play") const nextButton = document.querySelector("#next") const prevButton = document.querySelector("#prev") const contents = document.querySelector("#contents") const contentsButton = document.querySelector("#contents-button") const volumeOn = document.querySelector("#volume-on") const volumeOff = document.querySelector("#volume-off") const showContentsEl = document.querySelector("#programmi-content") const showListEl = document.querySelector("#programmi-lista") let currentStatus async function playPauseRadio() { try { if(audio.paused) { await audio.play(); } else { await audio.pause(); } } catch(err) { console.log(err); } } function onVolumeChange(e) { if(e.target.value == 0) { volumeOn.classList.add("hidden"); volumeOff.classList.remove("hidden") } else { volumeOff.classList.add("hidden"); volumeOn.classList.remove("hidden") } audio.volume = e.target.value; } function setupTabs() { for(let el of document.querySelectorAll("#menu > input")){ console.log(el) el.addEventListener('change', (e) => { for(let ce of document.querySelectorAll("#menu > input")) { var selector = "#"+ce.id.split('-').slice(1).join('-') if(ce.checked) { document.querySelector(selector).classList.remove("hidden") } else { document.querySelector(selector).classList.add("hidden") } } }) } } function setupPlayer() { playButton.addEventListener("click", playPauseRadio, false); volumeOff.addEventListener("click", (e) => { volume.disabled = false; e.target.classList.add("hidden"); volumeOn.classList.remove("hidden"); audio.volume = volume.value; }); volumeOn.addEventListener("click", (e) => { volume.disabled = true; e.target.classList.add("hidden"); volumeOff.classList.remove("hidden"); audio.volume = 0; }); volume.addEventListener('change', onVolumeChange); contentsButton.addEventListener("click", (e) => { contents.hidden = !contents.hidden; e.target.classList.toggle("arrow-up"); }) let showBackToLive = () => { document.querySelector(".is-live").classList.add("hidden"); document.querySelector(".back-to-live").classList.remove("hidden"); } prevButton.addEventListener("click",(e) => { audio.currentTime -= 15; showBackToLive() }, false) nextButton.addEventListener("click",(e) => { audio.currentTime += 15; showBackToLive() }, false) audio.addEventListener('pause', (e) => { showBackToLive() }) document.querySelector(".back-to-live").addEventListener('click', (e) => { document.querySelector(".is-live").classList.remove("hidden") e.target.classList.add("hidden") audio.currentTime = audio.duration audio.play() }) } function setupRadios() { for(let r of leRadio) { let el = document.createElement("span") el.dataset['website'] = r.website el.textContent = r.name; el.addEventListener('click', async (e) => { console.log('radio selected', r.website) await deployRadio(r.website) }) document.querySelector("#other-radios").appendChild(el) } } function setupShowButtons() { let scrollFwd = (el) => { let scrollAmount = 0; let timer = setInterval( () => { el.scrollLeft += 10; scrollAmount += 10; if(scrollAmount >= 100){ window.clearInterval(timer); } }, 25); } let scrollBack = (el) => { let scrollAmount = 0; let timer = setInterval( () => { el.scrollLeft -= 10; scrollAmount -= 10; if(scrollAmount <= -100){ window.clearInterval(timer); } }, 25); } document.getElementById("prev-show").addEventListener("click", (e) => { scrollBack(showListEl) }) document.getElementById("next-show").addEventListener("click", (e) => { scrollFwd(showListEl) }) document.getElementById("next-show-card").addEventListener("click", (e) => { scrollFwd(showContentsEl.querySelector("div.content-box:not(.hidden)")) }) document.getElementById("prev-show-card").addEventListener("click", (e) => { scrollBack(showContentsEl.querySelector("div.content-box:not(.hidden)")) }) } async function setupProgrammi() { console.log('programmi', radio) if(radio === null) return; const programmi = radio.getShows(); if(programmi === null || programmi === undefined) return; document.querySelectorAll('#programmi-lista > span').forEach((el) => { el.remove() }) for(let p of programmi) { let el = document.createElement("span") el.innerHTML = p.getName(); showListEl.appendChild(el) el.addEventListener('click', (e) => { console.log("Hai clickato su", p.getName()) document.querySelectorAll("#programmi-content > .content-box").forEach((el) => { el.remove() }) document.querySelectorAll("#programmi > .show-content > .arrow").forEach((el) => { el.classList.remove("hidden") }) fetch(httpsIze(p.getFeed())) .then(res => res.text()) .then(res => new window.DOMParser().parseFromString(res, "text/xml")) .then(xml => { // XXX: we'd need a proper podcast-parsing library here let data = Array.from(xml.getElementsByTagName("item")). map(item => Array.from(item.childNodes) .reduce((data, node) => { if(node.localName) { if(node.prefix){ if(!data[node.prefix]) { data[node.prefix] = {} } data[node.prefix][node.localName] = node.textContent } else { let val = node.textContent if(node.localName === 'enclosure') { val = node.getAttribute('url', '') } data[node.localName] = val // if(localName == "pubDate") { // data[node.localName] = new Date(data[node.localName]) // } }} return data; }, {})) console.log(data) let programma = document.createElement("div") programma.setAttribute("id", p.name.replaceAll(/[\W_]+/g," ").replaceAll(' ', '-')); programma.classList.add("content-box"); document.getElementById("programmi-content").append(programma); for(let s of data) { let template = document.querySelector("#show-card-template"); let puntata = template.content.cloneNode(true); let keywords = '' if(s['itunes'] && s.itunes.keywords) { s['itunes']['keywords'].split(',').map((k) => `${k}`).join('') } puntata.querySelector(".title").textContent = s.title; puntata.querySelector(".description").textContent = s.describtion ? s.description.substr(0, 150) : ""; puntata.querySelector(".play-pause").addEventListener('click', (e) => { console.log(httpsIze(s.enclosure)) player.changeStreamURLs([httpsIze(s.enclosure)]) document.querySelector("#radio-name").textContent = p.getName(); document.querySelector("#program-name").textContent = s.title; }) puntata.querySelector(".add-to-playlist").addEventListener('click', (e) => { console.log('playlist?', s, s.enclosure) playlist.push(s) }) programma.appendChild(puntata) } }) }) } } document.querySelector('#programmi').classList.add('hidden') setupPlayer(); setupRadios(); setupTabs(); setupShowButtons(); await deployRadio(leRadio[0].website) } main()