Refactor the MPRIS2 MediaPlayer2.Player implementation

Changed most items to refer to the underlying AudioManager methods and
signals.
WIP: Still need to check the ProgressOnTaskBar stuff.
This commit is contained in:
Bart De Vries 2021-04-13 14:34:01 +02:00
parent 7c4658db2d
commit 60330608ac
2 changed files with 119 additions and 179 deletions

View File

@ -29,29 +29,46 @@ MediaPlayer2Player::MediaPlayer2Player(AudioManager *audioPlayer, bool showProgr
QStringLiteral("Update"))), QStringLiteral("Update"))),
mShowProgressOnTaskBar(showProgressOnTaskBar) mShowProgressOnTaskBar(showProgressOnTaskBar)
{ {
// Signals from AudioManager which are directly forwarded
connect(m_audioPlayer, &AudioManager::sourceChanged, connect(m_audioPlayer, &AudioManager::sourceChanged,
this, &MediaPlayer2Player::playerSourceChanged, Qt::QueuedConnection); this, &MediaPlayer2Player::playerSourceChanged, Qt::QueuedConnection);
connect(m_audioPlayer, &AudioManager::playbackRateChanged,
this, &MediaPlayer2Player::rateChanged);
// TODO: implement this in AudioManager, such that it can be forwarded
//connect(m_audioPlayer, &AudioManager::minimumRateChanged,
// this, &MediaPlayer2Player::mimimumRateChanged);
//connect(m_audioPlayer, &AudioManager::maximumRateChanged,
// this, &MediaPlayer2Player::maximumRateChanged);
connect(m_audioPlayer, &AudioManager::canSkipForwardChanged,
this, &MediaPlayer2Player::canGoNextChanged);
connect(m_audioPlayer, &AudioManager::canSkipBackwardChanged,
this, &MediaPlayer2Player::canGoPreviousChanged);
connect(m_audioPlayer, &AudioManager::canPlayChanged, connect(m_audioPlayer, &AudioManager::canPlayChanged,
this, &MediaPlayer2Player::playControlEnabledChanged); this, &MediaPlayer2Player::canPlayChanged);
connect(m_audioPlayer, &AudioManager::sourceChanged, connect(m_audioPlayer, &AudioManager::canPauseChanged,
this, &MediaPlayer2Player::skipBackwardControlEnabledChanged); this, &MediaPlayer2Player::canPauseChanged);
connect(m_audioPlayer, &AudioManager::sourceChanged, connect(m_audioPlayer, &AudioManager::seekableChanged,
this, &MediaPlayer2Player::skipForwardControlEnabledChanged); this, &MediaPlayer2Player::canSeekChanged);
// Signals which are semi-wrapped signals from AudioManager
connect(m_audioPlayer, &AudioManager::playbackStateChanged, connect(m_audioPlayer, &AudioManager::playbackStateChanged,
this, &MediaPlayer2Player::playerPlaybackStateChanged); this, &MediaPlayer2Player::playerPlaybackStateChanged);
connect(m_audioPlayer, &AudioManager::seekableChanged,
this, &MediaPlayer2Player::playerIsSeekableChanged);
connect(m_audioPlayer, &AudioManager::positionChanged,
this, &MediaPlayer2Player::audioPositionChanged);
connect(m_audioPlayer, &AudioManager::seek,
this, &MediaPlayer2Player::playerSeeked);
connect(m_audioPlayer, &AudioManager::durationChanged,
this, &MediaPlayer2Player::audioDurationChanged);
connect(m_audioPlayer, &AudioManager::volumeChanged, connect(m_audioPlayer, &AudioManager::volumeChanged,
this, &MediaPlayer2Player::playerVolumeChanged); this, &MediaPlayer2Player::playerVolumeChanged);
connect(m_audioPlayer, &AudioManager::positionChanged,
this, &MediaPlayer2Player::audioPositionChanged);
// Custom signals not directly connected to AudioManager
// 1. Metadata
connect(m_audioPlayer, &AudioManager::durationChanged,
this, &MediaPlayer2Player::audioDurationChanged);
// old signal connections
connect(m_audioPlayer, &AudioManager::positionChanged,
this, &MediaPlayer2Player::playerSeeked);
m_volume = m_audioPlayer->volume() / 100; m_volume = m_audioPlayer->volume() / 100;
m_canPlay = m_audioPlayer->canPlay();
signalPropertiesChange(QStringLiteral("Volume"), Volume()); signalPropertiesChange(QStringLiteral("Volume"), Volume());
m_mediaPlayerPresent = 1; m_mediaPlayerPresent = 1;
@ -75,99 +92,78 @@ QString MediaPlayer2Player::PlaybackStatus() const
result = QStringLiteral("Paused"); result = QStringLiteral("Paused");
} }
if (mShowProgressOnTaskBar) {
QVariantMap parameters;
if (m_audioPlayer->playbackState() == QMediaPlayer::StoppedState || m_audioPlayer->duration() == 0) {
parameters.insert(QStringLiteral("progress-visible"), false);
parameters.insert(QStringLiteral("progress"), 0);
} else {
parameters.insert(QStringLiteral("progress-visible"), true);
parameters.insert(QStringLiteral("progress"), qRound(static_cast<double>(m_position / m_audioPlayer->duration())) / 1000.0);
}
mProgressIndicatorSignal.setArguments({QStringLiteral("application://org.kde.alligator.desktop"), parameters});
QDBusConnection::sessionBus().send(mProgressIndicatorSignal);
}
return result; return result;
} }
bool MediaPlayer2Player::CanGoNext() const bool MediaPlayer2Player::CanGoNext() const
{ {
return m_canGoNext; if (m_audioPlayer)
return m_audioPlayer->canSkipForward();
else
return false;
} }
void MediaPlayer2Player::Next() void MediaPlayer2Player::Next()
{ {
emit next(); if (m_audioPlayer)
if (m_audioPlayer) {
m_audioPlayer->skipForward(); m_audioPlayer->skipForward();
}
} }
bool MediaPlayer2Player::CanGoPrevious() const bool MediaPlayer2Player::CanGoPrevious() const
{ {
return m_canGoPrevious; if (m_audioPlayer)
return m_audioPlayer->canSkipBackward();
else
return false;
} }
void MediaPlayer2Player::Previous() void MediaPlayer2Player::Previous()
{ {
emit previous(); if (m_audioPlayer)
if (m_audioPlayer) {
m_audioPlayer->skipBackward(); m_audioPlayer->skipBackward();
}
} }
bool MediaPlayer2Player::CanPause() const bool MediaPlayer2Player::CanPause() const
{ {
return m_canPlay; if (m_audioPlayer)
return m_audioPlayer->canPause();
else
return false;
} }
void MediaPlayer2Player::Pause() void MediaPlayer2Player::Pause()
{ {
if (m_audioPlayer) { if (m_audioPlayer)
m_audioPlayer->pause(); m_audioPlayer->pause();
}
} }
void MediaPlayer2Player::PlayPause() void MediaPlayer2Player::PlayPause()
{ {
emit playPause(); if (m_audioPlayer)
m_audioPlayer->playPause();
if (m_audioPlayer) {
if (m_audioPlayer->playbackState() == QMediaPlayer::State::PausedState)
m_audioPlayer->play();
else if (m_audioPlayer->playbackState() == QMediaPlayer::State::PlayingState)
m_audioPlayer->pause();
}
} }
void MediaPlayer2Player::Stop() void MediaPlayer2Player::Stop()
{ {
emit stop();
// we actually don't really want to stop, because that would reset the player // we actually don't really want to stop, because that would reset the player
// position, so we pause instead // position, so we pause instead
if (m_audioPlayer) { if (m_audioPlayer)
m_audioPlayer->pause(); m_audioPlayer->pause();
}
} }
bool MediaPlayer2Player::CanPlay() const bool MediaPlayer2Player::CanPlay() const
{ {
return m_canPlay; if (m_audioPlayer)
return m_audioPlayer->canPlay();
else
return false;
} }
void MediaPlayer2Player::Play() void MediaPlayer2Player::Play()
{ {
if (m_audioPlayer) { if (m_audioPlayer)
m_audioPlayer->play(); m_audioPlayer->play();
}
} }
double MediaPlayer2Player::Volume() const double MediaPlayer2Player::Volume() const
@ -192,33 +188,12 @@ QVariantMap MediaPlayer2Player::Metadata() const
qlonglong MediaPlayer2Player::Position() const qlonglong MediaPlayer2Player::Position() const
{ {
return m_position; return qlonglong(m_audioPlayer->position()) * 1000;
}
void MediaPlayer2Player::setPropertyPosition(int newPositionInMs)
{
m_position = qlonglong(newPositionInMs) * 1000;
/* only send new progress when it has advanced more than 1 %
* to limit DBus traffic
*/
const auto incrementalProgress = static_cast<double>(newPositionInMs - mPreviousProgressPosition) / m_audioPlayer->duration();
if (mShowProgressOnTaskBar && (incrementalProgress > 0.01 || incrementalProgress < 0))
{
mPreviousProgressPosition = newPositionInMs;
QVariantMap parameters;
parameters.insert(QStringLiteral("progress-visible"), true);
parameters.insert(QStringLiteral("progress"), static_cast<double>(newPositionInMs) / m_audioPlayer->duration());
mProgressIndicatorSignal.setArguments({QStringLiteral("application://org.kde.alligator.desktop"), parameters});
QDBusConnection::sessionBus().send(mProgressIndicatorSignal);
}
} }
double MediaPlayer2Player::Rate() const double MediaPlayer2Player::Rate() const
{ {
return m_rate; return m_audioPlayer->playbackRate();
} }
void MediaPlayer2Player::setRate(double newRate) void MediaPlayer2Player::setRate(double newRate)
@ -226,10 +201,7 @@ void MediaPlayer2Player::setRate(double newRate)
if (newRate <= 0.0001 && newRate >= -0.0001) { if (newRate <= 0.0001 && newRate >= -0.0001) {
Pause(); Pause();
} else { } else {
m_rate = qBound(MinimumRate(), newRate, MaximumRate()); m_audioPlayer->setPlaybackRate(qBound(MinimumRate(), newRate, MaximumRate()));
emit rateChanged(m_rate);
signalPropertiesChange(QStringLiteral("Rate"), Rate());
} }
} }
@ -245,7 +217,7 @@ double MediaPlayer2Player::MaximumRate() const
bool MediaPlayer2Player::CanSeek() const bool MediaPlayer2Player::CanSeek() const
{ {
return m_playerIsSeekableChanged; return m_audioPlayer->seekable();
} }
bool MediaPlayer2Player::CanControl() const bool MediaPlayer2Player::CanControl() const
@ -255,7 +227,7 @@ bool MediaPlayer2Player::CanControl() const
void MediaPlayer2Player::Seek(qlonglong Offset) void MediaPlayer2Player::Seek(qlonglong Offset)
{ {
if (mediaPlayerPresent()) { if (m_audioPlayer) {
auto offset = (m_position + Offset) / 1000; auto offset = (m_position + Offset) / 1000;
m_audioPlayer->seek(int(offset)); m_audioPlayer->seek(int(offset));
} }
@ -263,9 +235,13 @@ void MediaPlayer2Player::Seek(qlonglong Offset)
void MediaPlayer2Player::SetPosition(const QDBusObjectPath &trackId, qlonglong pos) void MediaPlayer2Player::SetPosition(const QDBusObjectPath &trackId, qlonglong pos)
{ {
if (trackId.path() == m_currentTrackId) { if (m_audioPlayer) {
if (m_audioPlayer->entry()) {
if (trackId.path() == m_audioPlayer->entry()->id()) {
m_audioPlayer->seek(int(pos / 1000)); m_audioPlayer->seek(int(pos / 1000));
} }
}
}
} }
void MediaPlayer2Player::OpenUri(const QString &uri) void MediaPlayer2Player::OpenUri(const QString &uri)
@ -279,47 +255,11 @@ void MediaPlayer2Player::playerSourceChanged()
setCurrentTrack(DataManager::instance().getQueue().indexOf(m_audioPlayer->entry()->id())); setCurrentTrack(DataManager::instance().getQueue().indexOf(m_audioPlayer->entry()->id()));
} }
void MediaPlayer2Player::playControlEnabledChanged()
{
m_canPlay = m_audioPlayer->canPlay();
signalPropertiesChange(QStringLiteral("CanPause"), CanPause());
signalPropertiesChange(QStringLiteral("CanPlay"), CanPlay());
emit canPauseChanged();
emit canPlayChanged();
}
void MediaPlayer2Player::skipBackwardControlEnabledChanged()
{
m_canGoPrevious = (DataManager::instance().getQueue().indexOf(m_audioPlayer->entry()->id()) > 0);
signalPropertiesChange(QStringLiteral("CanGoPrevious"), CanGoPrevious());
emit canGoPreviousChanged();
}
void MediaPlayer2Player::skipForwardControlEnabledChanged()
{
m_canGoNext = (DataManager::instance().getQueue().indexOf(m_audioPlayer->entry()->id()) < DataManager::instance().getQueue().count());
signalPropertiesChange(QStringLiteral("CanGoNext"), CanGoNext());
emit canGoNextChanged();
}
void MediaPlayer2Player::playerPlaybackStateChanged() void MediaPlayer2Player::playerPlaybackStateChanged()
{ {
signalPropertiesChange(QStringLiteral("PlaybackStatus"), PlaybackStatus()); signalPropertiesChange(QStringLiteral("PlaybackStatus"), PlaybackStatus());
emit playbackStatusChanged(); emit playbackStatusChanged();
playerIsSeekableChanged();
}
void MediaPlayer2Player::playerIsSeekableChanged()
{
m_playerIsSeekableChanged = m_audioPlayer->seekable();
signalPropertiesChange(QStringLiteral("CanSeek"), CanSeek());
emit canSeekChanged();
} }
void MediaPlayer2Player::audioPositionChanged() void MediaPlayer2Player::audioPositionChanged()
@ -337,10 +277,7 @@ void MediaPlayer2Player::audioDurationChanged()
m_metadata = getMetadataOfCurrentTrack(); m_metadata = getMetadataOfCurrentTrack();
signalPropertiesChange(QStringLiteral("Metadata"), Metadata()); signalPropertiesChange(QStringLiteral("Metadata"), Metadata());
skipBackwardControlEnabledChanged();
skipForwardControlEnabledChanged();
playerPlaybackStateChanged(); playerPlaybackStateChanged();
playerIsSeekableChanged();
setPropertyPosition(static_cast<int>(m_audioPlayer->position())); setPropertyPosition(static_cast<int>(m_audioPlayer->position()));
} }
@ -402,6 +339,59 @@ int MediaPlayer2Player::mediaPlayerPresent() const
return m_mediaPlayerPresent; return m_mediaPlayerPresent;
} }
void MediaPlayer2Player::setMediaPlayerPresent(int status)
{
if (m_mediaPlayerPresent != status) {
m_mediaPlayerPresent = status;
emit mediaPlayerPresentChanged();
signalPropertiesChange(QStringLiteral("CanGoNext"), CanGoNext());
signalPropertiesChange(QStringLiteral("CanGoPrevious"), CanGoPrevious());
signalPropertiesChange(QStringLiteral("CanPause"), CanPause());
signalPropertiesChange(QStringLiteral("CanPlay"), CanPlay());
emit canGoNextChanged();
emit canGoPreviousChanged();
emit canPauseChanged();
emit canPlayChanged();
}
}
void MediaPlayer2Player::setPropertyPosition(int newPositionInMs)
{
m_position = qlonglong(newPositionInMs) * 1000;
/* only send new progress when it has advanced more than 1 %
* to limit DBus traffic
*/
const auto incrementalProgress = static_cast<double>(newPositionInMs - mPreviousProgressPosition) / m_audioPlayer->duration();
if (mShowProgressOnTaskBar && (incrementalProgress > 0.01 || incrementalProgress < 0))
{
mPreviousProgressPosition = newPositionInMs;
QVariantMap parameters;
parameters.insert(QStringLiteral("progress-visible"), true);
parameters.insert(QStringLiteral("progress"), static_cast<double>(newPositionInMs) / m_audioPlayer->duration());
mProgressIndicatorSignal.setArguments({QStringLiteral("application://org.kde.alligator.desktop"), parameters});
QDBusConnection::sessionBus().send(mProgressIndicatorSignal);
}
}
void MediaPlayer2Player::signalPropertiesChange(const QString &property, const QVariant &value)
{
QVariantMap properties;
properties[property] = value;
const int ifaceIndex = metaObject()->indexOfClassInfo("D-Bus Interface");
QDBusMessage msg = QDBusMessage::createSignal(QStringLiteral("/org/mpris/MediaPlayer2"),
QStringLiteral("org.freedesktop.DBus.Properties"), QStringLiteral("PropertiesChanged"));
msg << QLatin1String(metaObject()->classInfo(ifaceIndex).value());
msg << properties;
msg << QStringList();
QDBusConnection::sessionBus().send(msg);
}
bool MediaPlayer2Player::showProgressOnTaskBar() const bool MediaPlayer2Player::showProgressOnTaskBar() const
{ {
return mShowProgressOnTaskBar; return mShowProgressOnTaskBar;
@ -425,35 +415,3 @@ void MediaPlayer2Player::setShowProgressOnTaskBar(bool value)
QDBusConnection::sessionBus().send(mProgressIndicatorSignal); QDBusConnection::sessionBus().send(mProgressIndicatorSignal);
} }
void MediaPlayer2Player::setMediaPlayerPresent(int status)
{
if (m_mediaPlayerPresent != status) {
m_mediaPlayerPresent = status;
emit mediaPlayerPresentChanged();
signalPropertiesChange(QStringLiteral("CanGoNext"), CanGoNext());
signalPropertiesChange(QStringLiteral("CanGoPrevious"), CanGoPrevious());
signalPropertiesChange(QStringLiteral("CanPause"), CanPause());
signalPropertiesChange(QStringLiteral("CanPlay"), CanPlay());
emit canGoNextChanged();
emit canGoPreviousChanged();
emit canPauseChanged();
emit canPlayChanged();
}
}
void MediaPlayer2Player::signalPropertiesChange(const QString &property, const QVariant &value)
{
QVariantMap properties;
properties[property] = value;
const int ifaceIndex = metaObject()->indexOfClassInfo("D-Bus Interface");
QDBusMessage msg = QDBusMessage::createSignal(QStringLiteral("/org/mpris/MediaPlayer2"),
QStringLiteral("org.freedesktop.DBus.Properties"), QStringLiteral("PropertiesChanged"));
msg << QLatin1String(metaObject()->classInfo(ifaceIndex).value());
msg << properties;
msg << QStringList();
QDBusConnection::sessionBus().send(msg);
}

View File

@ -32,6 +32,7 @@ class MediaPlayer2Player : public QDBusAbstractAdaptor
Q_PROPERTY(bool CanPause READ CanPause NOTIFY canPauseChanged) Q_PROPERTY(bool CanPause READ CanPause NOTIFY canPauseChanged)
Q_PROPERTY(bool CanControl READ CanControl NOTIFY canControlChanged) Q_PROPERTY(bool CanControl READ CanControl NOTIFY canControlChanged)
Q_PROPERTY(bool CanSeek READ CanSeek NOTIFY canSeekChanged) Q_PROPERTY(bool CanSeek READ CanSeek NOTIFY canSeekChanged)
Q_PROPERTY(int currentTrack READ currentTrack WRITE setCurrentTrack NOTIFY currentTrackChanged) Q_PROPERTY(int currentTrack READ currentTrack WRITE setCurrentTrack NOTIFY currentTrackChanged)
Q_PROPERTY(int mediaPlayerPresent READ mediaPlayerPresent WRITE setMediaPlayerPresent NOTIFY mediaPlayerPresentChanged) Q_PROPERTY(int mediaPlayerPresent READ mediaPlayerPresent WRITE setMediaPlayerPresent NOTIFY mediaPlayerPresentChanged)
@ -56,7 +57,6 @@ public:
bool CanControl() const; bool CanControl() const;
int currentTrack() const; int currentTrack() const;
int mediaPlayerPresent() const; int mediaPlayerPresent() const;
bool showProgressOnTaskBar() const; bool showProgressOnTaskBar() const;
void setShowProgressOnTaskBar(bool value); void setShowProgressOnTaskBar(bool value);
@ -94,23 +94,10 @@ public Q_SLOTS:
private Q_SLOTS: private Q_SLOTS:
void playerSourceChanged(); void playerSourceChanged();
void playControlEnabledChanged();
void skipBackwardControlEnabledChanged();
void skipForwardControlEnabledChanged();
void playerPlaybackStateChanged(); void playerPlaybackStateChanged();
void playerIsSeekableChanged();
void audioPositionChanged(); void audioPositionChanged();
void playerSeeked(qint64 position); void playerSeeked(qint64 position);
void audioDurationChanged(); void audioDurationChanged();
void playerVolumeChanged(); void playerVolumeChanged();
private: private:
@ -127,14 +114,9 @@ private:
QVariantMap m_metadata; QVariantMap m_metadata;
QString m_currentTrack; QString m_currentTrack;
QString m_currentTrackId; QString m_currentTrackId;
double m_rate = 1.0;
double m_volume = 0.0; double m_volume = 0.0;
int m_mediaPlayerPresent = 0; int m_mediaPlayerPresent = 0;
bool m_canPlay = false;
bool m_canGoNext = false;
bool m_canGoPrevious = false;
qlonglong m_position = 0; qlonglong m_position = 0;
bool m_playerIsSeekableChanged = false;
AudioManager *m_audioPlayer = nullptr; AudioManager *m_audioPlayer = nullptr;
mutable QDBusMessage mProgressIndicatorSignal; mutable QDBusMessage mProgressIndicatorSignal;
int mPreviousProgressPosition = 0; int mPreviousProgressPosition = 0;