diff --git a/css/style.css b/css/style.css index 4f2b754..c09cedf 100644 --- a/css/style.css +++ b/css/style.css @@ -117,20 +117,7 @@ p a:link { } /* -------------------------------------------------------------------------- */ -/* Stream Player */ - -.player { - grid-area: player; - display: flex; - flex-direction: column; - justify-content: space-between; - margin: 0 auto; - width: 60%; -} - -.player > div { - margin-bottom: 1em; -} +/* Stream Page */ .metadata { grid-area: metadata; @@ -147,42 +134,83 @@ p a:link { width: 100%; } -.player-main { - line-height: 1em; - display: flex; - justify-content: space-between; - align-items: center; -} - -.player-public { - line-height: 1em; - display: flex; - justify-content: space-between; - align-items: center; -} - .location { margin-left: auto; } +select { + background-color: red; + color: white; + border: none; + font-family: inherit; + font-size: inherit; +} + #trackName, #showName { overflow-wrap: anywhere; } -/* chat widget */ -.theme--minimal { +/* -------------------------------------------------------------------------- */ +/* Player Widget */ + +.audio-player { + height: 50px; + width: 400px; + background: red; + border: solid; + border-width: 2px; + border-radius: 3px; color: white; + font-size: 0.75em; + display: grid; + margin: 0 auto; + margin-bottom: 1em; +} + +.audio-player .controls { + display: flex; + width: 400px; + padding-right: 0.5em; +} +.audio-player .controls > * { + display: flex; + align-items: center; +} + +.audio-player .controls .volume-container { + cursor: pointer; + position: relative; + z-index: 2; +} +.audio-player .controls .volume-container .volume-slider { + position: absolute; + left: 3em; + z-index: -1; + width: 0; + height: 15px; + background: #444; + transition: 0.25s; +} + +.audio-player .controls .volume-container .volume-slider .volume-percentage { + background: white; + height: 100%; width: 100%; } -.big-icon { - font-size: 3em; - margin-right: 0.5em; +.audio-player .controls .volume-container:hover .volume-slider { + width: 18em; } -.hidden { - display: none; - opacity: 0; +span#name { + flex: 1; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +#station-select { + margin-left: auto; } /* -------------------------------------------------------------------------- */ diff --git a/js/play.js b/js/play.js index e7ec908..7b71e94 100644 --- a/js/play.js +++ b/js/play.js @@ -1,10 +1,23 @@ -var audio = document.getElementById('player-main') -var audioPublic = document.getElementById('player-public') +let audio = document.getElementById('player-main') +let stationSelect = document.getElementById('station-select') -var playButton = $('.play-button') -var pauseButton = $('.pause-button') -var playButtonPublic = $('.play-button-public') -var pauseButtonPublic = $('.pause-button-public') +let playButton = $('.play-button') +let pauseButton = $('.pause-button') + +const toggle = (src) => + src === "1" + ? "https://kchungradio.out.airtime.pro/kchungradio_a" + : "http://s9.voscast.com:7376/;" + +const selectStream = (s) => { + if (audio.paused) { + return audio.load() + } + audio.src = toggle(s) + audio.addEventListener('canplay', () => audio.play()) + audio.load() +} +// showInfoEl.innerText = stationSelect.value ? getAirtimeInfo(resp) : geffinInfo playButton.click(function(event) { event.preventDefault() @@ -16,24 +29,10 @@ pauseButton.click(function(event) { pause() }) -playButtonPublic.click(function(event) { - event.preventDefault() - playPublic() -}) - -pauseButtonPublic.click(function(event) { - event.preventDefault() - pausePublic() -}) - function play() { playButton.toggleClass('hidden') pauseButton.toggleClass('hidden') - if (playButtonPublic.hasClass('hidden')) { - pausePublic() - } - audio.volume = 1.0 audio.play() } @@ -44,22 +43,3 @@ function pause() { audio.pause() } - -function playPublic() { - playButtonPublic.toggleClass('hidden') - pauseButtonPublic.toggleClass('hidden') - - if (playButton.hasClass('hidden')) { - pause() - } - - audioPublic.volume = 1.0 - audioPublic.play() -} - -function pausePublic() { - playButtonPublic.toggleClass('hidden') - pauseButtonPublic.toggleClass('hidden') - - audioPublic.pause() -} diff --git a/js/player.js b/js/player.js new file mode 100644 index 0000000..9a7e642 --- /dev/null +++ b/js/player.js @@ -0,0 +1,90 @@ +// KCHUNG Stream Player Widget + +//------------------------------------------------------------------------------ +// Data + +const audioPlayer = document.querySelector(".audio-player"); +const audio = new Audio("https://kchungradio.out.airtime.pro/kchungradio_a"); + +const stationSelect = document.getElementById('station-select') +const volumeSlider = audioPlayer.querySelector(".controls .volume-slider"); +const playButton = audioPlayer.querySelector(".controls .toggle-play"); + +//------------------------------------------------------------------------------ +// Callbacks + +const setFullVolume = () => audio.volume = 1.0; + +const adjustVolume = (e) => { + const sliderWidth = window.getComputedStyle(volumeSlider).width; + const newVolume = e.offsetX / parseInt(sliderWidth); + audio.volume = newVolume; + audioPlayer.querySelector(".controls .volume-percentage").style.width = newVolume * 100 + '%'; +} + +const togglePlayback = () => + audio.paused + ? (playButton.classList.replace("la-play", "la-pause"), audio.play()) + : (playButton.classList.replace("la-pause", "la-play"), audio.pause()) + +const toggleMute = () => { + const volumeEl = audioPlayer.querySelector(".volume-container .volume"); + audio.muted = !audio.muted; + audio.muted + ? volumeEl.classList.replace("la-volume-up", "la-volume-off") + : volumeEl.classList.replace("la-volume-off", "la-volume-up") +} + +const updateShowInfo = async () => { + const liveInfoUrl = 'https://kchungradio.airtime.pro/api/live-info-v2' + const showInfoEl = document.getElementById('name') + + const getAirtimeInfo = (resp) => { + let track = resp?.tracks?.current?.metadata?.filepath; + let show = resp?.shows?.current?.name + return track ? track : show ? show : "" + } + + const geffinInfo = "Live from KCHUNG Public" + const response = await fetch(liveInfoUrl) + const data = await response.json() + showInfoEl.innerText = stationSelect.value === "1" ? getAirtimeInfo(data) : geffinInfo +} + +const toggleStream = async (e) => { + const toggle = (src) => + src === "1" + ? "https://kchungradio.out.airtime.pro/kchungradio_a" + : "http://s9.voscast.com:7376/;" + + const newStream = toggle(e.srcElement.value) + + if (audio.paused) return audio.load() + audio.src = newStream + audio.addEventListener('canplay', () => audio.play()) + audio.load() +} + +//------------------------------------------------------------------------------ +// Event Listeners + +// Initialize the show info on page load +window.addEventListener("load", updateShowInfo); + +// Reset volume when loading the stream +audio.addEventListener("loadeddata", setFullVolume); + +// Change the volume when user clicks the volume slider +volumeSlider.addEventListener('click', adjustVolume) + +// Pause or Play the stream when user clicks the play/pause button. +playButton.addEventListener("click", togglePlayback); + +// Toggle mute when user clicks on volume icon +audioPlayer.querySelector(".volume-button").addEventListener("click", toggleMute); + +// Periodically refresh the show info +// stationSelect.addEventListener("change", updateShowInfo) + +// Toggle between streams on changes to the select element +stationSelect.addEventListener("change", (e) => toggleStream(e).then(updateShowInfo)); diff --git a/js/stream.js b/js/stream.js index 67972cc..a4959cb 100644 --- a/js/stream.js +++ b/js/stream.js @@ -1,40 +1,26 @@ +// this runs after the DOM has loaded ;(function() { - var liveInfoUrl = 'https://kchungradio.airtime.pro/api/live-info-v2' + let liveInfoUrl = 'https://kchungradio.airtime.pro/api/live-info-v2' // Visit URL below to understand SHOUTcast's metadata html response format // TODO: Figure out how to pull this info without getting a CORS error // var publicInfoUrl = 'http://s9.voscast.com:7376/7.html' - var showNameEl = document.getElementById('showName') - var trackNameEl = document.getElementById('trackName') + let showInfoEl = document.getElementById('name') + //let selectEl = document.getElementById('station-select') - var playButton = $('.play-button') - var playButtonPublic = $('.play-button-public') + let getAirtimeInfo = (resp) => { + let track = resp?.tracks.current.metadata.filepath; + let show = resp?.shows.current.name + return track ? track : show ? show : "" + } - $.get(liveInfoUrl, function(liveInfo) { - var showNameText - var trackNameText + let geffinInfo = "Live from KCHUNG Public" + let playButton = $('.play-button') + let playButtonPublic = $('.play-button-public') - if ( - liveInfo && - liveInfo.tracks && - liveInfo.tracks.current && - liveInfo.tracks.current.metadata && - liveInfo.tracks.current.metadata.filepath - ) { - trackNameText = liveInfo.tracks.current.metadata.filepath - trackNameEl.innerText = trackNameText - showNameEl.innerText = '' - } else if ( - liveInfo && - liveInfo.shows && - liveInfo.shows.current && - liveInfo.shows.current.name - ) { - showNameText = liveInfo.shows.current.name - showNameEl.innerText = showNameText - trackNameEl.innerText = '' - } + $.get(liveInfoUrl, function(resp) { + //console.log(selectEl.value) + //showInfoEl.innerText = selectEl.value === "1" ? getAirtimeInfo(resp) : geffinInfo + showInfoEl.innerText = getAirtimeInfo(resp) }) - // this runs after the DOM has loaded - // $(function() {}) })() diff --git a/stream/index.html b/stream/index.html index c05a13a..64d0098 100644 --- a/stream/index.html +++ b/stream/index.html @@ -4,7 +4,7 @@ KCHUNG Radio 1630AM - + @@ -46,54 +46,36 @@ -
-
-
-
-
- - - - -
-
-
-
-
- chinatown +
+
+
+
- -
-
-
-
-
-
- - - - +
+
+
-
-
Live from the Geffen Contemporary MOCA
+ +
+
- moca geffen
+ +
+
-
-
-
+
+
- - - - - +