diff --git a/.gitignore b/.gitignore index 14c5dc1..d9ab11c 100755 --- a/.gitignore +++ b/.gitignore @@ -85,6 +85,7 @@ CMakeLists.txt.user* .vs/ out/ +.cache .direnv dist CMakePresets.json diff --git a/.vscode/settings.json b/.vscode/settings.json index 308e47e..29fcdb9 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,4 +1,5 @@ { + "C_Cpp.workspaceParsingPriority": "medium", "files.associations": { "flake.lock": "json", "qobject": "cpp", diff --git a/Main.qml b/Main.qml index ff8fdb6..38df636 100755 --- a/Main.qml +++ b/Main.qml @@ -11,6 +11,10 @@ ApplicationWindow { height: 800 title: qsTr("QYouRadio") + Component.onCompleted: function() { + console.log(Player.stations) + } + ColumnLayout { anchors.fill: parent @@ -45,21 +49,21 @@ ApplicationWindow { clip: true NumberAnimation { - running: Player.currentIndex != null + running: Player.playing && tabbar.currentIndex != Player.currentIndex && nowplaying_root.anchors.bottomMargin >= 42 target: nowplaying_root property: "anchors.bottomMargin" from: 42 to: 0 - duration: 160 + duration: 145 } NumberAnimation { - running: Player.currentIndex == null + running: !Player.playing || (tabbar.currentIndex == Player.currentIndex && nowplaying_root.anchors.bottomMargin < 42) target: nowplaying_root property: "anchors.bottomMargin" from: 0 to: 42 - duration: 160 + duration: 145 } Label { @@ -69,7 +73,7 @@ ApplicationWindow { anchors.topMargin: 1 anchors.leftMargin: 4 anchors.rightMargin: 4 - text: (Player.loading ? "Loading " : "Playing ") + (Player.currentIndex != null ? qsTr(Player.currentStream.name) : "") + text: (Player.loading ? "Loading " : "Playing ") + qsTr(Player.currentStation.name) heading: "h5" } @@ -81,7 +85,7 @@ ApplicationWindow { anchors.bottomMargin: 1 anchors.leftMargin: 4 // anchors.rightMargin: 4 - text: (Player.currentIndex != null ? qsTr(Player.currentStream.title) : "") + text: qsTr(Player.currentStation.songTitle) heading: "h3" @@ -124,7 +128,6 @@ ApplicationWindow { } } - SwipeView { Layout.fillWidth: true Layout.fillHeight: true @@ -134,7 +137,8 @@ ApplicationWindow { currentIndex: tabbar.currentIndex Loader { - active: tabbar.currentIndex == 0 + // active: tabbar.currentIndex == 0 + active: true asynchronous: true visible: status == Loader.Ready sourceComponent: ViewPlayer { @@ -142,7 +146,8 @@ ApplicationWindow { } } Loader { - active: tabbar.currentIndex == 1 + // active: tabbar.currentIndex == 1 + active: true asynchronous: true visible: status == Loader.Ready sourceComponent: ViewPlayer { @@ -150,18 +155,47 @@ ApplicationWindow { } } Loader { - active: tabbar.currentIndex == 2 + // active: tabbar.currentIndex == 2 + active: true asynchronous: true visible: status == Loader.Ready sourceComponent: ViewPlayer { index: 2 } } + + Component.onCompleted: contentItem.highlightMoveDuration = 160; } - YouAds { + RowLayout { Layout.fillWidth: false Layout.alignment: Qt.AlignHCenter + Layout.topMargin: 30 + Layout.bottomMargin: 30 + width: 220 + + Button { + Layout.rightMargin: 5 + text: Player.loading ? "Loading" : (Player.playing ? "Pause" : "Play") + + onClicked: function() { + if (Player.playing) { + Player.stopPlaying(); + } else { + Player.startPlaying(tabbar.currentIndex); + } + } + } + + Slider { + Layout.fillWidth: true + Layout.leftMargin: 5 + from: 0.1 + to: 1.1 + stepSize: 0.05 + value: Player.volume + 0.1 + onMoved: Player.volume = value - 0.1 + } } } } diff --git a/ViewPlayer.qml b/ViewPlayer.qml index a034c48..5559012 100644 --- a/ViewPlayer.qml +++ b/ViewPlayer.qml @@ -5,7 +5,6 @@ import QtQuick.Layouts 6.8 import QYRComponents 1.0 ColumnLayout { - Layout.alignment: Qt.AlignVCenter Layout.fillWidth: true property var index: null @@ -13,62 +12,40 @@ ColumnLayout { Label { Layout.fillWidth: true Layout.bottomMargin: 20 - text: index != null ? Player.streams[index].name : "Invalid station" + text: qsTr(Player.stations[index].name) + font.bold: true heading: "h2" horizontalAlignment: Text.AlignHCenter } - Label { - Layout.fillWidth: true - text: "Title: " + (index != null ? Player.streams[index].title : "") - heading: "h3" - horizontalAlignment: Text.AlignHCenter - } - - Label { - Layout.fillWidth: true - text: "Listeners: " + (index != null ? Player.streams[index].listeners : 0) - heading: "h3" - horizontalAlignment: Text.AlignHCenter - } - - Label { - Layout.topMargin: 20 - text: (Player.currentIndex != null && Player.currentIndex != parent.index) ? qsTr("Another station is currently playing") : "" - heading: "h2" - horizontalAlignment: Text.AlignHCenter - } - - RowLayout { - Layout.fillWidth: false - Layout.alignment: Qt.AlignHCenter - width: 220 - - Button { - Layout.rightMargin: 5 - text: Player.loading ? "Loading" : (Player.playing ? "Pause" : "Play") - - onClicked: function() { - if (Player.playing) { - Player.stopPlaying(); - } else { - Player.startPlaying(parent.parent.index); - } - } - } - - Slider { - Layout.fillWidth: true - Layout.leftMargin: 5 - from: 0.1 - to: 1.1 - stepSize: 0.05 - value: Player.volume + 0.1 - onMoved: Player.volume = value - 0.1 - } - } - Item { Layout.fillHeight: true } -} \ No newline at end of file + + Label { + Layout.fillWidth: true + text: Player.stations[index].songTitle + font.pixelSize: 72 + horizontalAlignment: Text.AlignHCenter + } + + Label { + Layout.fillWidth: true + text: "Listening: " + Player.stations[index].listeners + heading: "h2" + horizontalAlignment: Text.AlignHCenter + } + + Item { + Layout.fillHeight: true + } + + Label { + Layout.fillWidth: true + Layout.topMargin: 20 + visible: (Player.currentIndex > -1 && Player.currentIndex != parent.index) + text: qsTr("Another station is currently playing") + heading: "h2" + horizontalAlignment: Text.AlignHCenter + } +} diff --git a/player.cpp b/player.cpp index fdf153c..d4a3906 100644 --- a/player.cpp +++ b/player.cpp @@ -2,8 +2,11 @@ // Public Player::Player(QObject *parent) : QObject(parent), - player(this), - output(this) + player(this), output(this), timer(this), m_currentIndex(0), m_stations({ + Station{"Autoradio", "autoradio", "", 0}, + Station{"Live Mix", "live", "", 0}, + Station{"Bass Boosted", "bassboosted", "", 0} + }) { QObject::connect(&this->player, &QMediaPlayer::playbackStateChanged, this, [this] () { qDebug("Player::Player()->Lambda: Playing got changed!"); @@ -15,9 +18,19 @@ Player::Player(QObject *parent) : QObject(parent), emit this->volumeChanged(); }); - this->output.setVolume(0.3); + this->timer.start(metadataFetchTimeout); + QObject::connect(&this->timer, &QTimer::timeout, this, [this] () { + qDebug("Player::Player()->Lambda: Timer triggered!"); + if (this->m_currentIndex > -1) + { + emit this->currentStationChanged(); + } + emit this->stationsChanged(); + }); + + this->output.setVolume(0.2); this->player.setAudioOutput(&this->output); - + qDebug("Player::Player(): Constructed"); } @@ -42,11 +55,30 @@ void Player::setVolume(float newVolume) this->output.setVolume(newVolume); } +const QList Player::stations() const +{ + return this->m_stations; +} + +const int Player::currentIndex() const +{ + return this->m_currentIndex; +} + +const Station* Player::currentStation() const +{ + if (this->m_currentIndex < 0 || this->m_currentIndex >= this->m_stations.length()) + { + qWarning("Player::currentStation(): Tried accessing out of bounds."); + return nullptr; + } + return &this->m_stations[this->m_currentIndex]; +} // Public slots void Player::startPlaying(u_int8_t index) { - if (index < 0 || index >= maxStations) + if (index < 0 || index >= this->m_stations.length()) { qWarning("Player::startPlaying(): Tried accessing out of bounds."); return; @@ -54,19 +86,28 @@ void Player::startPlaying(u_int8_t index) if (this->playing()) { this->stopPlaying(); } - this->player.setSource(QUrl(streamPrefix + stations[index].slug)); + this->m_currentIndex = index; + emit this->currentIndexChanged(); + emit this->currentStationChanged(); + + this->player.setSource(QUrl("https://youradio.nonamesoft.xyz/youradio/api/" + this->m_stations[index].m_slug)); this->player.play(); qDebug("Player::startPlaying(): Starting playing"); } void Player::stopPlaying() { - if (this->playing()) + if (!this->playing()) { qWarning("Player::stopPlaying(): Prevented redundant stopPlaying() call."); return; } this->player.stop(); this->player.setSource(QUrl("")); + + this->m_currentIndex = -1; + emit this->currentIndexChanged(); + emit this->currentStationChanged(); + qDebug("Player::stopPlaying(): Stopping playback..."); -} \ No newline at end of file +} diff --git a/player.h b/player.h index 72daca1..44ad67d 100644 --- a/player.h +++ b/player.h @@ -3,25 +3,27 @@ #include #include #include +#include +#include #include +constexpr int metadataFetchTimeout = 10000; constexpr std::string_view metadataEndpoint = "https://youradio.nonamesoft.xyz/youradio/api/status-json.xsl"; -constexpr std::string_view streamPrefix = "https://youradio.nonamesoft.xyz/youradio/api/"; struct Station { - const char name[16]; - const char slug[16]; - QString* songTitle; - u_int8_t listeners; -}; + Q_GADGET -constexpr u_int8_t maxStations = 3; + Q_PROPERTY(QString name MEMBER m_name); + Q_PROPERTY(QString slug MEMBER m_slug); + Q_PROPERTY(QString songTitle MEMBER m_songTitle); + Q_PROPERTY(int listeners MEMBER m_listeners); -const Station stations[maxStations] = { - { "Autoradio", "autoradio" , nullptr, 0 }, - { "Live Mix", "livemix" , nullptr, 0 }, - { "Deep Bass", "bassboosted", nullptr, 0 } +public: + QString m_name; + QString m_slug; + QString m_songTitle; + int m_listeners; }; class Player : public QObject @@ -30,17 +32,26 @@ class Player : public QObject QML_SINGLETON QML_ELEMENT - Q_PROPERTY(bool playing READ playing NOTIFY playingChanged) - Q_PROPERTY(float volume READ volume WRITE setVolume NOTIFY volumeChanged) - + Q_PROPERTY(bool playing READ playing NOTIFY playingChanged FINAL) + Q_PROPERTY(float volume READ volume WRITE setVolume NOTIFY volumeChanged FINAL) + Q_PROPERTY(const QList stations READ stations NOTIFY stationsChanged FINAL) + Q_PROPERTY(int currentIndex READ currentIndex NOTIFY currentIndexChanged FINAL) + Q_PROPERTY(const Station* currentStation READ currentStation NOTIFY currentStationChanged FINAL) + public: Player(QObject *parent = nullptr); ~Player(); bool playing() const; + float volume() const; void setVolume(float newVolume); + const QList stations() const; + + const int currentIndex() const; + const Station* currentStation() const; + public slots: void startPlaying(u_int8_t index); void stopPlaying(); @@ -48,8 +59,15 @@ public slots: signals: void playingChanged(); void volumeChanged(); + void stationsChanged(); + void currentIndexChanged(); + void currentStationChanged(); private: QMediaPlayer player; QAudioOutput output; + QTimer timer; + + int m_currentIndex; + QList m_stations; };