Files
qyouradio/Player.qml
Dark Steveneq 18ad69ba5d
Some checks failed
Build / build-linux (push) Failing after 17s
Build / build-windows (push) Has been cancelled
Begin implementing UI design, implement metadata fetching
2025-10-14 21:02:58 +02:00

124 lines
3.7 KiB
QML

import QtQuick 6.8
import QtMultimedia 6.8
pragma Singleton
Item {
readonly property string streamURLPrefix: "https://youradio.nonamesoft.xyz/youradio/api/"
readonly property string metadataURL: "https://youradio.nonamesoft.xyz/youradio/api/status-json.xsl"
readonly property var slugLookup: ({
"autoradio": 0,
"live": 1,
"bassboosted": 2
})
property var streams: ([
{
name: "Autoradio",
slug: "autoradio",
title: "",
listeners: 0
},
{
name: "Live Mix",
slug: "live",
title: "",
listeners: 0
},
{
name: "Deep Bass",
slug: "bassboosted",
title: "",
listeners: 0
}
])
property var failedConnAttempts: 0
property alias playing: player.playing
property alias volume: output.volume
readonly property var loading: player.mediaStatus == Qt.LoadingMedia
property var currentIndex: null
property var currentStream: null
function startPlaying(index) {
if ((playing && index == currentIndex) || index < 0 || index >= streams.length) {
return;
}
if (playing) {
player.stop();
}
print("Starting playing stream no. " + index);
currentIndex = index;
currentStream = streams[index];
player.source = streamURLPrefix + currentStream.slug;
player.play();
}
function stopPlaying() {
if (!playing) {
return;
}
print("Stopping playback");
currentIndex = null;
currentStream = null;
player.source = "";
player.stop()
}
MediaPlayer {
id: player
source: ""
audioOutput: AudioOutput {
id: output
volume: 0.4
}
onErrorOccurred: function(error, errorString) {
const index = currentIndex
currentIndex = null
currentIndex = index;
}
}
Timer {
interval: 10000
repeat: true
running: true
triggeredOnStart: true
onTriggered: function() {
const xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState == XMLHttpRequest.DONE) {
parent.failedConnAttempts = 0;
// try {
const object = JSON.parse(xhr.responseText.toString()).icestats;
object.source.forEach(station => {
const index = parent.slugLookup[station.server_name];
if (index == null) {
console.warn("Unknown slug encountered in metadata: " + station.server_name);
return
}
parent.streams[index].title = station.title;
parent.streams[index].listeners = station.listeners;
if (index == parent.currentIndex) {
parent.currentStream.title = station.title;
parent.currentStream.listeners = station.listeners;
}
});
// } catch {
// console.error("Failed deserializing metadata response");
// }
}
}
xhr.open("GET", parent.metadataURL);
xhr.timeout = 10000;
xhr.ontimeout = function() {
console.log("Metadata request timed out after 10 seconds");
parent.failedConnAttempts++;
}
xhr.send();
}
}
}