Add SPDX license identifiers to all source files

This commit is contained in:
Sebastian Palencsar
2026-05-27 07:11:33 +02:00
parent 721900083c
commit 9c9b250e5e
20 changed files with 206 additions and 161 deletions

View File

@@ -1,195 +1,183 @@
// Copyright (c) 2026 Sebastian Palencsar
// SPDX-License-Identifier: GPL-3.0-or-later
#include "bearplayer.h" #include "bearplayer.h"
#include <QUrl>
#include <QDebug> #include <QDebug>
#include <QMediaMetaData> #include <QMediaMetaData>
#include <QUrl>
BearPlayer::BearPlayer(QObject *parent) : QObject(parent) {
m_audioOutput = new QAudioOutput(this);
m_mediaPlayer = new QMediaPlayer(this);
m_mediaPlayer->setAudioOutput(m_audioOutput);
m_coverArtFetcher = new CoverArtFetcher(this);
connect(m_coverArtFetcher, &CoverArtFetcher::coverUrlReady, this,
&BearPlayer::onCoverUrlReady);
BearPlayer::BearPlayer(QObject *parent) m_icyReader = new IcyReader(this);
: QObject(parent) connect(m_icyReader, &IcyReader::metaDataReceived, this,
{ &BearPlayer::onIcyMetaDataReceived);
m_audioOutput = new QAudioOutput(this);
m_mediaPlayer = new QMediaPlayer(this);
m_mediaPlayer->setAudioOutput(m_audioOutput);
m_coverArtFetcher = new CoverArtFetcher(this); connect(m_mediaPlayer, &QMediaPlayer::playbackStateChanged, this,
connect(m_coverArtFetcher, &CoverArtFetcher::coverUrlReady, this, &BearPlayer::onCoverUrlReady); &BearPlayer::onPlaybackStateChanged);
connect(m_mediaPlayer, &QMediaPlayer::mediaStatusChanged, this,
&BearPlayer::onMediaStatusChanged);
connect(m_mediaPlayer, &QMediaPlayer::metaDataChanged, this,
&BearPlayer::onMetaDataChanged);
m_icyReader = new IcyReader(this); m_retryTimer.setSingleShot(true);
connect(m_icyReader, &IcyReader::metaDataReceived, this, &BearPlayer::onIcyMetaDataReceived); m_retryTimer.setInterval(1200);
connect(&m_retryTimer, &QTimer::timeout, this, [this]() {
connect(m_mediaPlayer, &QMediaPlayer::playbackStateChanged, if (m_lastUrl.isEmpty() || m_playing || m_retryAttempts >= 2) {
this, &BearPlayer::onPlaybackStateChanged); return;
connect(m_mediaPlayer, &QMediaPlayer::mediaStatusChanged,
this, &BearPlayer::onMediaStatusChanged);
connect(m_mediaPlayer, &QMediaPlayer::metaDataChanged,
this, &BearPlayer::onMetaDataChanged);
m_retryTimer.setSingleShot(true);
m_retryTimer.setInterval(1200);
connect(&m_retryTimer, &QTimer::timeout, this, [this]() {
if (m_lastUrl.isEmpty() || m_playing || m_retryAttempts >= 2) {
return;
}
++m_retryAttempts;
m_mediaPlayer->setSource(QUrl(m_lastUrl));
m_mediaPlayer->play();
qDebug() << "Retry stream" << m_retryAttempts << m_lastName;
});
}
BearPlayer::~BearPlayer()
{
stop();
}
void BearPlayer::playUrl(const QString &url, const QString &name)
{
if (url.isEmpty()) {
return;
} }
++m_retryAttempts;
m_currentStationName = name; m_mediaPlayer->setSource(QUrl(m_lastUrl));
m_lastName = name;
m_lastUrl = url;
m_retryAttempts = 0;
emit currentStationChanged(m_currentStationName);
clearTrackInfo();
m_mediaPlayer->setSource(QUrl(url));
m_mediaPlayer->play(); m_mediaPlayer->play();
m_icyReader->start(url); qDebug() << "Retry stream" << m_retryAttempts << m_lastName;
});
qDebug() << "Playing:" << name << url;
} }
void BearPlayer::stop() BearPlayer::~BearPlayer() { stop(); }
{
m_mediaPlayer->stop(); void BearPlayer::playUrl(const QString &url, const QString &name) {
m_icyReader->stop(); if (url.isEmpty()) {
m_currentStationName.clear(); return;
m_lastName.clear(); }
m_lastUrl.clear();
m_retryAttempts = 0; m_currentStationName = name;
emit currentStationChanged(QString()); m_lastName = name;
clearTrackInfo(); m_lastUrl = url;
m_retryAttempts = 0;
emit currentStationChanged(m_currentStationName);
clearTrackInfo();
m_mediaPlayer->setSource(QUrl(url));
m_mediaPlayer->play();
m_icyReader->start(url);
qDebug() << "Playing:" << name << url;
} }
void BearPlayer::togglePlayPause() void BearPlayer::stop() {
{ m_mediaPlayer->stop();
if (m_playing) { m_icyReader->stop();
m_mediaPlayer->pause(); m_currentStationName.clear();
} else { m_lastName.clear();
m_mediaPlayer->play(); m_lastUrl.clear();
} m_retryAttempts = 0;
emit currentStationChanged(QString());
clearTrackInfo();
} }
void BearPlayer::setVolume(qreal vol) void BearPlayer::togglePlayPause() {
{ if (m_playing) {
m_audioOutput->setVolume(qBound(0.0, vol, 1.0)); m_mediaPlayer->pause();
emit volumeChanged(m_audioOutput->volume()); } else {
m_mediaPlayer->play();
}
} }
void BearPlayer::onPlaybackStateChanged(QMediaPlayer::PlaybackState state) void BearPlayer::setVolume(qreal vol) {
{ m_audioOutput->setVolume(qBound(0.0, vol, 1.0));
m_playing = (state == QMediaPlayer::PlayingState); emit volumeChanged(m_audioOutput->volume());
}
void BearPlayer::onPlaybackStateChanged(QMediaPlayer::PlaybackState state) {
m_playing = (state == QMediaPlayer::PlayingState);
emit playingChanged(m_playing);
if (state == QMediaPlayer::StoppedState) {
scheduleRetry();
}
}
void BearPlayer::onMediaStatusChanged(QMediaPlayer::MediaStatus status) {
if (status == QMediaPlayer::InvalidMedia) {
m_playing = false;
emit playingChanged(m_playing); emit playingChanged(m_playing);
scheduleRetry();
if (state == QMediaPlayer::StoppedState) { }
scheduleRetry();
}
} }
void BearPlayer::onMediaStatusChanged(QMediaPlayer::MediaStatus status) void BearPlayer::scheduleRetry() {
{ if (m_lastUrl.isEmpty() || m_retryAttempts >= 2 || m_playing) {
if (status == QMediaPlayer::InvalidMedia) { return;
m_playing = false; }
emit playingChanged(m_playing); if (!m_retryTimer.isActive()) {
scheduleRetry(); m_retryTimer.start();
} }
} }
void BearPlayer::scheduleRetry() void BearPlayer::onMetaDataChanged() {
{ QMediaMetaData meta = m_mediaPlayer->metaData();
if (m_lastUrl.isEmpty() || m_retryAttempts >= 2 || m_playing) {
return; QString artist = meta.stringValue(QMediaMetaData::ContributingArtist);
} if (artist.isEmpty()) {
if (!m_retryTimer.isActive()) { artist = meta.stringValue(QMediaMetaData::Author);
m_retryTimer.start(); }
}
QString title = meta.stringValue(QMediaMetaData::Title);
// Ignore completely empty metadata from QMediaPlayer so we don't overwrite
// IcyReader
if (artist.isEmpty() && title.isEmpty()) {
return;
}
if (m_currentTrackArtist == artist && m_currentTrackTitle == title) {
return;
}
m_currentTrackArtist = artist;
m_currentTrackTitle = title;
m_currentCoverArtUrl.clear();
m_coverArtFetcher->fetch(artist, title);
emit trackInfoChanged();
} }
void BearPlayer::onMetaDataChanged() void BearPlayer::onCoverUrlReady(const QString &url) {
{ if (m_currentCoverArtUrl != url) {
QMediaMetaData meta = m_mediaPlayer->metaData(); m_currentCoverArtUrl = url;
QString artist = meta.stringValue(QMediaMetaData::ContributingArtist);
if (artist.isEmpty()) {
artist = meta.stringValue(QMediaMetaData::Author);
}
QString title = meta.stringValue(QMediaMetaData::Title);
// Ignore completely empty metadata from QMediaPlayer so we don't overwrite IcyReader
if (artist.isEmpty() && title.isEmpty()) {
return;
}
if (m_currentTrackArtist == artist && m_currentTrackTitle == title) {
return;
}
m_currentTrackArtist = artist;
m_currentTrackTitle = title;
m_currentCoverArtUrl.clear();
m_coverArtFetcher->fetch(artist, title);
emit trackInfoChanged(); emit trackInfoChanged();
}
} }
void BearPlayer::onCoverUrlReady(const QString &url) void BearPlayer::onIcyMetaDataReceived(const QString &artist,
{ const QString &title) {
if (m_currentCoverArtUrl != url) { if (m_currentTrackArtist == artist && m_currentTrackTitle == title) {
m_currentCoverArtUrl = url; return;
emit trackInfoChanged(); }
}
m_currentTrackArtist = artist;
m_currentTrackTitle = title;
m_currentCoverArtUrl.clear();
m_coverArtFetcher->fetch(artist, title);
emit trackInfoChanged();
} }
void BearPlayer::onIcyMetaDataReceived(const QString &artist, const QString &title) QString BearPlayer::currentNowPlaying() const {
{ if (!m_currentTrackArtist.isEmpty() && !m_currentTrackTitle.isEmpty()) {
if (m_currentTrackArtist == artist && m_currentTrackTitle == title) { return m_currentTrackArtist + QStringLiteral(" - ") + m_currentTrackTitle;
return; }
} if (!m_currentTrackTitle.isEmpty()) {
return m_currentTrackTitle;
m_currentTrackArtist = artist; }
m_currentTrackTitle = title; if (!m_currentTrackArtist.isEmpty()) {
m_currentCoverArtUrl.clear(); return m_currentTrackArtist;
m_coverArtFetcher->fetch(artist, title); }
emit trackInfoChanged(); return QString();
} }
QString BearPlayer::currentNowPlaying() const void BearPlayer::clearTrackInfo() {
{ if (m_currentTrackArtist.isEmpty() && m_currentTrackTitle.isEmpty()) {
if (!m_currentTrackArtist.isEmpty() && !m_currentTrackTitle.isEmpty()) { return;
return m_currentTrackArtist + QStringLiteral(" - ") + m_currentTrackTitle; }
} m_currentTrackArtist.clear();
if (!m_currentTrackTitle.isEmpty()) { m_currentTrackTitle.clear();
return m_currentTrackTitle; m_currentCoverArtUrl.clear();
} m_coverArtFetcher->fetch(QString(), QString());
if (!m_currentTrackArtist.isEmpty()) { emit trackInfoChanged();
return m_currentTrackArtist;
}
return QString();
}
void BearPlayer::clearTrackInfo()
{
if (m_currentTrackArtist.isEmpty() && m_currentTrackTitle.isEmpty()) {
return;
}
m_currentTrackArtist.clear();
m_currentTrackTitle.clear();
m_currentCoverArtUrl.clear();
m_coverArtFetcher->fetch(QString(), QString());
emit trackInfoChanged();
} }

View File

@@ -1,3 +1,6 @@
// Copyright (c) 2026 Sebastian Palencsar
// SPDX-License-Identifier: GPL-3.0-or-later
#ifndef BEARPLAYER_H #ifndef BEARPLAYER_H
#define BEARPLAYER_H #define BEARPLAYER_H

View File

@@ -1,3 +1,6 @@
// Copyright (c) 2026 Sebastian Palencsar
// SPDX-License-Identifier: GPL-3.0-or-later
#include "bearwavecontroladaptor.h" #include "bearwavecontroladaptor.h"
#include "radiobackend.h" #include "radiobackend.h"

View File

@@ -1,3 +1,6 @@
// Copyright (c) 2026 Sebastian Palencsar
// SPDX-License-Identifier: GPL-3.0-or-later
#ifndef BEARWAVECONTROLADAPTOR_H #ifndef BEARWAVECONTROLADAPTOR_H
#define BEARWAVECONTROLADAPTOR_H #define BEARWAVECONTROLADAPTOR_H

View File

@@ -1,3 +1,6 @@
// Copyright (c) 2026 Sebastian Palencsar
// SPDX-License-Identifier: GPL-3.0-or-later
#include "coverartfetcher.h" #include "coverartfetcher.h"
#include <QUrlQuery> #include <QUrlQuery>
#include <QJsonDocument> #include <QJsonDocument>

View File

@@ -1,3 +1,6 @@
// Copyright (c) 2026 Sebastian Palencsar
// SPDX-License-Identifier: GPL-3.0-or-later
#ifndef COVERARTFETCHER_H #ifndef COVERARTFETCHER_H
#define COVERARTFETCHER_H #define COVERARTFETCHER_H

View File

@@ -1,3 +1,6 @@
// Copyright (c) 2026 Sebastian Palencsar
// SPDX-License-Identifier: GPL-3.0-or-later
#include "icyreader.h" #include "icyreader.h"
#include <QNetworkRequest> #include <QNetworkRequest>
#include <QDebug> #include <QDebug>

View File

@@ -1,3 +1,6 @@
// Copyright (c) 2026 Sebastian Palencsar
// SPDX-License-Identifier: GPL-3.0-or-later
#ifndef ICYREADER_H #ifndef ICYREADER_H
#define ICYREADER_H #define ICYREADER_H

View File

@@ -1,3 +1,6 @@
// Copyright (c) 2026 Sebastian Palencsar
// SPDX-License-Identifier: GPL-3.0-or-later
#include <QApplication> #include <QApplication>
#include <QDBusConnection> #include <QDBusConnection>
#include <QIcon> #include <QIcon>

View File

@@ -1,3 +1,6 @@
// Copyright (c) 2026 Sebastian Palencsar
// SPDX-License-Identifier: GPL-3.0-or-later
#include "mprisadaptor.h" #include "mprisadaptor.h"
#include "radiobackend.h" #include "radiobackend.h"

View File

@@ -1,3 +1,6 @@
// Copyright (c) 2026 Sebastian Palencsar
// SPDX-License-Identifier: GPL-3.0-or-later
#ifndef MPRISADAPTOR_H #ifndef MPRISADAPTOR_H
#define MPRISADAPTOR_H #define MPRISADAPTOR_H

View File

@@ -1,3 +1,6 @@
// Copyright (c) 2026 Sebastian Palencsar
// SPDX-License-Identifier: GPL-3.0-or-later
#include "notificationmanager.h" #include "notificationmanager.h"
#include "radiobackend.h" #include "radiobackend.h"
#include "bearplayer.h" #include "bearplayer.h"

View File

@@ -1,3 +1,6 @@
// Copyright (c) 2026 Sebastian Palencsar
// SPDX-License-Identifier: GPL-3.0-or-later
#ifndef NOTIFICATIONMANAGER_H #ifndef NOTIFICATIONMANAGER_H
#define NOTIFICATIONMANAGER_H #define NOTIFICATIONMANAGER_H

View File

@@ -1,3 +1,6 @@
// Copyright (c) 2026 Sebastian Palencsar
// SPDX-License-Identifier: GPL-3.0-or-later
import QtQuick 2.15 import QtQuick 2.15
import QtQuick.Controls 2.15 import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15 import QtQuick.Layouts 1.15

View File

@@ -1,3 +1,6 @@
// Copyright (c) 2026 Sebastian Palencsar
// SPDX-License-Identifier: GPL-3.0-or-later
#include "radiobackend.h" #include "radiobackend.h"
#include <QDebug> #include <QDebug>

View File

@@ -1,3 +1,6 @@
// Copyright (c) 2026 Sebastian Palencsar
// SPDX-License-Identifier: GPL-3.0-or-later
#ifndef RADIOBACKEND_H #ifndef RADIOBACKEND_H
#define RADIOBACKEND_H #define RADIOBACKEND_H

View File

@@ -1,3 +1,6 @@
// Copyright (c) 2026 Sebastian Palencsar
// SPDX-License-Identifier: GPL-3.0-or-later
#include "radiobrowser.h" #include "radiobrowser.h"
#include <QJsonDocument> #include <QJsonDocument>

View File

@@ -1,3 +1,6 @@
// Copyright (c) 2026 Sebastian Palencsar
// SPDX-License-Identifier: GPL-3.0-or-later
#ifndef RADIOBROWSER_H #ifndef RADIOBROWSER_H
#define RADIOBROWSER_H #define RADIOBROWSER_H

View File

@@ -1,3 +1,6 @@
// Copyright (c) 2026 Sebastian Palencsar
// SPDX-License-Identifier: GPL-3.0-or-later
#include "radiostation.h" #include "radiostation.h"
#include <QJsonObject> #include <QJsonObject>

View File

@@ -1,3 +1,6 @@
// Copyright (c) 2026 Sebastian Palencsar
// SPDX-License-Identifier: GPL-3.0-or-later
#ifndef RADIOSTATION_H #ifndef RADIOSTATION_H
#define RADIOSTATION_H #define RADIOSTATION_H