Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 64 additions & 36 deletions css/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
}

/* -------------------------------------------------------------------------- */
Expand Down
58 changes: 19 additions & 39 deletions js/play.js
Original file line number Diff line number Diff line change
@@ -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()
Expand All @@ -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()
}
Expand All @@ -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()
}
90 changes: 90 additions & 0 deletions js/player.js
Original file line number Diff line number Diff line change
@@ -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));
46 changes: 16 additions & 30 deletions js/stream.js
Original file line number Diff line number Diff line change
@@ -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() {})
})()
Loading