ircradio/ircradio/templates/index.html

235 lines
7.8 KiB
HTML

{% extends "base.html" %}
{% block content %}
{% set radio_default = settings.radio_stations['wow'] %}
<!-- Page Content -->
<div class="container">
<div class="row">
{% for rs in radio_stations %}
<div class="col-md-4 col-sm-6 col-xl-3">
<div data-radio="{{ rs.id }}" class="card box-shadow mb-4">
<div class="card-header">
<h5 class="my-0 font-weight-normal">{{ rs.title }}</h5>
</div>
<img class="img_header card-img-top" src="{{ url_for('static', filename=rs.image) }}" alt="">
<div class="card-body text-center">
<h5 class="title_str card-title pricing-card-title text-muted">|</h5>
<ul class="list-unstyled mt-3 mb-4">
<li class="listeners_str">0 listeners</li>
<li class="progress_str text-muted">00:00 / 00:00</li>
</ul>
<button data-playing="false" data-url="{{ "http://" + settings.icecast2_hostname + "/" + rs.mount_point }}" data-radio="{{ rs.id }}" type="button" class="btn btn-play btn-block btn-outline-primary mb-2">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="btn_audio_icon bi bi-play" viewBox="0 0 16 16">
<path d="M10.804 8 5 4.633v6.734L10.804 8zm.792-.696a.802.802 0 0 1 0 1.392l-6.363 3.692C4.713 12.69 4 12.345 4 11.692V4.308c0-.653.713-.998 1.233-.696l6.363 3.692z"></path>
</svg>
<span>Play</span>
</button>
{% if logged_in %}
{% if rs.id == radio_default.id %}
<div class="btnMeta mb-2" data-url="{{ url_for('api_tune', radio_id=rs.id) }}">
<button data-playing="false" data-radio="{{ rs.id }}" type="button" class="btn btn-block btn-outline-primary">
<span>Tune</span>
</button>
</div>
<div class="btnMeta mb-2" data-url="{{ url_for('api_boo', radio_id=rs.id) }}">
<button data-playing="false" data-radio="{{ rs.id }}" type="button" class="btn btn-block btn-outline-primary">
<span>Boo</span>
</button>
</div>
{% endif %}
<div class="btnMeta mb-2" data-url="{{ url_for('api_skip', radio_id=rs.id) }}">
<button data-playing="false" data-radio="{{ rs.id }}" type="button" class="btn btn-block btn-outline-primary">
<span>Skip</span>
</button>
</div>
{% endif %}
<small class="footer d-block text-muted mt-3">{{ rs.description | safe }}</small>
</div>
</div>
</div>
{% endfor %}
<div class="audio d-none">
{% for rs in radio_stations %}
<audio data-url="{{ rs.stream_url }}" id="player_{{ rs.id }}" controls preload="none">
<source src="{{ rs.stream_url }}" type="audio/ogg">
</audio>
{% endfor %}
</div>
</div>
{% include 'footer.html' %}
</div>
<script>
var radio_default_images = {
{% for rs in radio_stations %}
"{{ rs.id }}": "{{ url_for('static', filename=rs.image) }}",
{% endfor %}
}
</script>
<script src="static/index.js"></script>
<script>
var radio_data = null;
// jquery selection caches
var audio_np = null;
// lookup, to keep order
let radio_station_ids = [{% for rs in radio_stations %}'{{ rs.id }}',{% endfor %}];
var sel_radio_cards = {};
var url_icecast = '{{ settings.icecast2_hostname }}';
var url_album_art = '/assets/art/';
var ws_url = '{{ url_for('ws', _external=True) }}';
var icon_play = `
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="btn_audio_icon bi bi-play" viewBox="0 0 16 16">
<path d="M10.804 8 5 4.633v6.734L10.804 8zm.792-.696a.802.802 0 0 1 0 1.392l-6.363 3.692C4.713 12.69 4 12.345 4 11.692V4.308c0-.653.713-.998 1.233-.696l6.363 3.692z"></path>
</svg>
`;
var icon_stop = `
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="btn_audio_icon bi bi-stop" viewBox="0 0 16 16">
<path d="M3.5 5A1.5 1.5 0 0 1 5 3.5h6A1.5 1.5 0 0 1 12.5 5v6a1.5 1.5 0 0 1-1.5 1.5H5A1.5 1.5 0 0 1 3.5 11V5zM5 4.5a.5.5 0 0 0-.5.5v6a.5.5 0 0 0 .5.5h6a.5.5 0 0 0 .5-.5V5a.5.5 0 0 0-.5-.5H5z"></path>
</svg>
`;
function stopRadio(radio_id) {
let radio = document.getElementById("player_" + radio_id);
radio.pause();
radio.src = radio.src; // trick to force disconnect from radio
}
function playRadio(radio_id) {
let radio = document.getElementById("player_" + radio_id);
let sel = $(radio);
radio.src = sel.attr('data-url');
radio.play();
}
function listeners_str(amount){
if(amount >= 2 || amount === 0) return `${amount} listeners`;
return `${amount} listener`;
}
function btnPlayChangeText(radio_id, text) {
sel_radio_cards[radio_id].find('.btn-play span').text(text);
}
function resetAll() {
for (let radio_id of radio_station_ids) {
stopRadio(radio_id);
btnPlayChangeActive(radio_id, false);
btnPlayChangeText(radio_id, 'Play');
}
}
function btnPlayChangeActive(radio_id, active) {
let _sel = sel_radio_cards[radio_id].find('.btn-play');
_sel.find('.btn_audio_icon').remove();
if(active) {
_sel.addClass('btn-primary');
_sel.attr('data-playing', 'true');
_sel.prepend(icon_stop);
} else {
_sel.removeClass('btn-primary');
_sel.attr('data-playing', 'false');
_sel.prepend(icon_play);
}
}
function labelSetListeners(radio_id) {
if(!radio_data.hasOwnProperty(radio_id)) return;
let listeners = radio_data[radio_id].listeners;
sel_radio_cards[radio_id].find('.listeners_str').text(listeners_str(listeners));
}
function btnPlay(event) {
let playing = $(event.currentTarget).attr('data-playing');
let url = $(event.currentTarget).attr('data-url');
let uid = $(event.currentTarget).attr('data-radio');
resetAll();
if(playing === "true" && audio_np !== null && audio_np.uid === uid) {
stopRadio(uid);
return;
}
playRadio(uid);
audio_np = {'url': url, 'uid': uid}
radio_data[uid].listeners += 1;
labelSetListeners(uid);
btnPlayChangeActive(uid, true);
btnPlayChangeText(uid, 'Pause');
}
$(document).ready(() => {
for (let radio_station_id of radio_station_ids) {
let _sel = $("div[data-radio=" + radio_station_id + "]");
_sel.find('.btn-play').on('click', btnPlay); // playBtn click handler
sel_radio_cards[radio_station_id] = _sel;
}
function onData(data) {
let blob = JSON.parse(data);
radio_data = blob;
for (let radio_station of radio_station_ids) {
if(!blob.hasOwnProperty(radio_station)) continue;
let rs = blob[radio_station];
if(rs.song !== null) {
let song = rs.song;
console.log(song.album_art);
if(song.hasOwnProperty('image') && song.image !== null) {
sel_radio_cards[rs.id].find('.img_header').attr('src', `${url_album_art}/${song.image}`);
}
sel_radio_cards[rs.id].find('.title_str').text(song.title);
labelSetListeners(rs.id, rs.listeners);
sel_radio_cards[rs.id].find('.progress_str').text(song.progress_str);
}
}
}
// btnMeta: skip, boo, tune
$(document).on('click', '.btnMeta', async (ev) => {
let sel = $(ev.currentTarget);
let url = sel.attr('data-url');
fetch(url).then((response) => {
if (response.ok) {
return response.json();
}
throw new Error('Something went wrong');
})
.then((responseJson) => {
if(responseJson.hasOwnProperty('msg')) {
let msg = responseJson['msg'];
alert(msg);
}
})
.catch((error) => {
alert(error);
});
});
ws_connect(ws_url, onData);
});
</script>
{% endblock %}