Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace Radioplayer button with an in-page player #356

Draft
wants to merge 18 commits into
base: development
Choose a base branch
from
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
2 changes: 2 additions & 0 deletions config.toml.example
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@
odName = "On Tap"

publicMyRadioAPIKey = "DFm1QGGyDZXHvGjjKYxv72ItpZe5oPiNvqTKEJLC2CmPYvdbYQ591DNKhpXwb1U9NVIgBuQ4XOBdSAKbaGzliqHm7pu4H4PxmO7mrH4JvKV6dBZx5n32obnEE2pE9vWC"
liveAudioUrl = "https://audio.ury.org.uk/live-high"
icecastStatusUrl = "https://audio.ury.org.uk/status-json.xsl"

[pageContext.indexCountdown]
enabled = true
Expand Down
5 changes: 3 additions & 2 deletions controllers/index.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,15 +86,16 @@ func (ic *IndexController) Post(w http.ResponseWriter, r *http.Request) {
if err != nil {
// Set prompt if send fails
data.MsgBoxError = true
// Indicate to the client that this was an error
w.WriteHeader(400)
}

ic.render(w, data)

}

func (ic *IndexController) render(w http.ResponseWriter, data RenderData) {
// Render page
err := utils.RenderTemplate(w, ic.config.PageContext, data, "index.tmpl", "elements/current_and_next.tmpl", "elements/banner.tmpl", "elements/message_box.tmpl", "elements/index_countdown.tmpl")
err := utils.RenderTemplate(w, ic.config.PageContext, data, "index.tmpl", "elements/current_and_next.tmpl", "elements/banner.tmpl", "elements/message_box.tmpl", "elements/index_countdown.tmpl", "elements/live_player.tmpl")
if err != nil {
log.Println(err)
return
Expand Down
2 changes: 1 addition & 1 deletion controllers/people.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ func (pc *PeopleController) Get(w http.ResponseWriter, r *http.Request) {
CurrentAndNext: currentAndNext,
}

err = utils.RenderTemplate(w, pc.config.PageContext, data, "people.tmpl", "elements/current_and_next.tmpl")
err = utils.RenderTemplate(w, pc.config.PageContext, data, "people.tmpl", "elements/current_and_next.tmpl", "elements/live_player.tmpl")
if err != nil {
log.Println(err)
return
Expand Down
2 changes: 1 addition & 1 deletion controllers/schedule_week.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ func (sc *ScheduleWeekController) makeAndRenderWeek(w http.ResponseWriter, year,
Subtypes: subtypes,
}

err = utils.RenderTemplate(w, sc.config.PageContext, data, "schedule_week.tmpl", "elements/current_and_next.tmpl")
err = utils.RenderTemplate(w, sc.config.PageContext, data, "schedule_week.tmpl", "elements/current_and_next.tmpl", "elements/live_player.tmpl")
if err != nil {
log.Println(err)
return
Expand Down
10 changes: 5 additions & 5 deletions public/js/currentAndNext.js
Original file line number Diff line number Diff line change
Expand Up @@ -101,15 +101,15 @@ function success(data) {
' title="Show currently on air: ' +
data.payload.current.title +
'">' +
'<h2 class="font-weight-bold">Now</h2>' +
'<h2 class="font-weight-bold">Live now</h2>' +
makeContent(data.payload.current) +
'</a>',
)
$('#studiomessage *').attr('disabled', false)
} else {
$('.current-and-next-now').replaceWith(
'<div class="current-and-next-now p-2 pt-3 px-3 p-sm-3 p-lg-4 " title="View the show now on air.">' +
'<h2 class="font-weight-bold">Now</h2>' +
'<h2 class="font-weight-bold">Live now</h2>' +
makeContent(data.payload.current) +
'</a>',
)
Expand All @@ -121,7 +121,7 @@ function success(data) {
// There is no next show (e.g. we're off air)
$('.current-and-next-next').replaceWith(
'<div class="current-and-next-next p-2 pt-3 px-3 p-sm-3 p-lg-4 " title="View the show up next.">' +
'<h2 class="font-weight-bold">Next</h2>' +
'<h2 class="font-weight-bold">Up next</h2>' +
'<div class="h3 show-title ellipsis">There\'s nothing up next yet.</div>' +
'</a>',
)
Expand All @@ -132,14 +132,14 @@ function success(data) {
' title="Show on air next: ' +
data.payload.next.title +
'.">' +
'<h2 class="font-weight-bold">Next</h2>' +
'<h2 class="font-weight-bold">Up next</h2>' +
makeContent(data.payload.next) +
'</a>',
)
} else {
$('.current-and-next-next').replaceWith(
'<div class="current-and-next-next p-2 pt-3 px-3 p-sm-3 p-lg-4 " title="View the show up next.">' +
'<h2 class="font-weight-bold">Next</h2>' +
'<h2 class="font-weight-bold">Up next</h2>' +
makeContent(data.payload.next) +
'</a>',
)
Expand Down
164 changes: 164 additions & 0 deletions public/js/live-player.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
export function makePlayer(config) {
const { idPrefix, audioUrl, icecastStatusUrl } = config;
let player = new Audio();
player.preload = 'none';
const playPause = document.getElementById(`${idPrefix}-play`);
const volume = document.getElementById(`${idPrefix}-volume`);
const currentTrackTitle = document.getElementById(`${idPrefix}-track-title`);
const currentTrackArtist = document.getElementById(`${idPrefix}-track-artist`);
const currentTrackArtistContainer = document.getElementById(`${idPrefix}-track-artist-container`);
const closeButton = document.getElementById(`${idPrefix}-close`);

closeButton.addEventListener('click', () => {
playbackControls.pause();
document.querySelector('.current-and-next-player').classList.add('closed');
document.querySelectorAll('.listen-btn').forEach((ele) => ele.style.display = '');
});

function updateButton() {
if (player.paused) {
playPause.innerHTML = '<i class="fa fa-play"></i>';
} else {
playPause.innerHTML = '<i class="fa fa-stop"></i>';
}
}

let playbackError = false;

function markLoading() {
playPause.innerHTML = '<span class="player-load-dots" title="loading"><span>&bull;</span><span>&bull;</span><span>&bull;</span></span>';
}

function markError() {
playbackError = true;
playPause.disabled = true;
playPause.innerHTML = '<i class="fa fa-exclamation-triangle"></i>';
}

function setNowPlaying(title, artist) {
currentTrackTitle.innerText = title;
currentTrackArtist.innerText = artist;
currentTrackArtistContainer.style.display = 'inline';
if (artist === null) {
currentTrackTitle.innerText = "University Radio York"
currentTrackArtistContainer.style.display = 'none';
}
}

let nowPlayingUpdate = null;

function fetchNowPlaying() {
fetch(icecastStatusUrl)
.then((resp) => {
if (!resp.ok) {
console.error('failed to fetch current track, has the icecastStatus been added to config?', resp.status, resp.statusText);
nowPlayingUpdate = setTimeout(fetchNowPlaying, 10_000);
return;
} else {
return resp.json();
}
})
.then((resp) => {
const stream = resp.icestats.source.filter((s) => s.listenurl.indexOf('/live-high-ogg') !== -1)[0];
const { artist, title } = stream;

setNowPlaying(title, artist);

// Update every 10s
nowPlayingUpdate = setTimeout(fetchNowPlaying, 10_000);
}).catch((e) => {
console.error('failed to fetch now playing, has the icecastStatus been added to config?', e);
});
}

const playbackControls = {
play() {
if (playbackError) {
console.log('playback error, has the audioUrl been set in config?');
return;
}
if (!nowPlayingUpdate) {
fetchNowPlaying();
}

if (!this.playing) {
player.src = audioUrl;
player.play();
}
},

pause() {
if (playbackError) {
return;
}
if (nowPlayingUpdate) {
clearTimeout(nowPlayingUpdate);
nowPlayingUpdate = null;
}

player.src = null;
player.srcObject = null;

updateButton();
},

setVolume(level) {
player.volume = level;
},

get playing() {
return player.src !== null && !player.paused;
}
};

player.addEventListener('waiting', () => {
if (playbackError) return;
markLoading();
})

player.addEventListener('pause', () => {
if (playbackError) return;
updateButton();
});

player.addEventListener('play', () => {
if (playbackError) return;
updateButton();
});

player.addEventListener('playing', () => {
if (playbackError) return;
updateButton();
});

player.addEventListener('ended', () => {
if (playbackError) return;
player.load();
});

player.addEventListener('error', (ev) => {
console.log(ev);
markError();
});

playPause.addEventListener('click', () => {
if (player.paused) {
playbackControls.play();
} else {
playbackControls.pause();
}
});

playbackControls.setVolume(parseInt(volume.value) / 11.0);
volume.addEventListener('input', () => {
playbackControls.setVolume(parseInt(volume.value) / 11.0);
});

window.onbeforeunload = () => {
if (playbackControls.playing) {
return '';
}
};

return playbackControls;
}
17 changes: 16 additions & 1 deletion sass/elements/_currentAndNext.scss
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
.current-next {
background: url("/images/bg-banner-1.jpg") center center no-repeat;
background: url("/images/bg-banner-1.jpg") center no-repeat;
background-size: cover;
color: white;
box-sizing: content-box;
Expand Down Expand Up @@ -75,4 +75,19 @@
background: $current-next-next-bg;
}

.current-and-next-player {
transition: max-height 500ms ease;
overflow: hidden;
max-height: 256px;

&.closed {
transition: max-height 500ms ease;
max-height: 0;
@include media-breakpoint-down(sm) {
// silly hack since the closed player has a height of 1px,
// even though i tell it that it can have a max height of 0
background-color: red;
}
}
}
}
1 change: 1 addition & 0 deletions sass/elements/_elements.scss
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@
@import "aprilFools";
@import "show";
@import "faq";
@import "livePlayer";
Loading