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 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.3 } 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.replace(/\[[a-zA-Z0-9]{11}\]/, ""); parent.streams[index].listeners = station.listeners; if (index == parent.currentIndex) { parent.currentStream = parent.streams[index]; } }); // } 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(); } } }