service/mpris: hack around more non-compliant players
Mpris is currently winning the competition for least compliant clients.
This commit is contained in:
parent
1eabf5b3c3
commit
d1a172751d
2 changed files with 36 additions and 2 deletions
|
@ -1,5 +1,6 @@
|
|||
#include "player.hpp"
|
||||
|
||||
#include <qtimer.h>
|
||||
#include <qcontainerfwd.h>
|
||||
#include <qdatetime.h>
|
||||
#include <qdbusconnection.h>
|
||||
|
@ -317,11 +318,24 @@ void MprisPlayer::onMetadataChanged() {
|
|||
}
|
||||
}
|
||||
|
||||
// Some players (Jellyfin) specify xesam:url or mpris:trackid
|
||||
// and DON'T ACTUALLY CHANGE THEM WHEN THE TRACK CHANGES.
|
||||
auto titleVariant = this->bpMetadata.value().value("xesam:title");
|
||||
if (titleVariant.isValid() && titleVariant.canConvert<QString>()) {
|
||||
auto title = titleVariant.toString();
|
||||
|
||||
if (title != this->mTrackTitle) {
|
||||
this->mTrackTitle = title;
|
||||
trackChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
Qt::beginPropertyUpdateGroup();
|
||||
|
||||
if (trackChanged) {
|
||||
emit this->trackChanged();
|
||||
this->bUniqueId = this->bUniqueId + 1;
|
||||
this->trackChangedBeforeState = true;
|
||||
|
||||
// Some players don't seem to send position updates or seeks on track change.
|
||||
this->pPosition.requestUpdate();
|
||||
|
@ -386,6 +400,23 @@ void MprisPlayer::setPlaying(bool playing) {
|
|||
this->togglePlaying();
|
||||
}
|
||||
|
||||
void MprisPlayer::onPlaybackStatusUpdated() {
|
||||
// Insurance - have not yet seen a player where this particular check is required that doesn't
|
||||
// require the late query below.
|
||||
this->pPosition.requestUpdate();
|
||||
|
||||
// For exceptionally bad players that update playback timestamps at an indeterminate time AFTER
|
||||
// updating playback state. (Youtube)
|
||||
QTimer::singleShot(100, this, [&]() { this->pPosition.requestUpdate(); });
|
||||
|
||||
// For exceptionally bad players that don't update length (or other metadata) until a new track actually
|
||||
// starts playing, and then don't trigger a metadata update when they do. (Jellyfin)
|
||||
if (this->trackChangedBeforeState) {
|
||||
this->trackChangedBeforeState = false;
|
||||
this->pMetadata.requestUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
bool MprisPlayer::loopSupported() const { return this->pLoopStatus.exists(); }
|
||||
|
||||
void MprisPlayer::setLoopState(MprisLoopState::Enum loopState) {
|
||||
|
|
|
@ -242,7 +242,7 @@ public:
|
|||
/// Equivalent to calling @@play() if not playing or @@pause() if playing.
|
||||
///
|
||||
/// May only be called if @@canTogglePlaying is true, which is equivalent to
|
||||
/// @@canPlay or @@canPause() depending on the current playback state.
|
||||
/// @@canPlay or @@canPause depending on the current playback state.
|
||||
Q_INVOKABLE void togglePlaying();
|
||||
|
||||
[[nodiscard]] bool isValid() const;
|
||||
|
@ -391,6 +391,7 @@ private slots:
|
|||
private:
|
||||
void onMetadataChanged();
|
||||
void onPositionUpdated();
|
||||
void onPlaybackStatusUpdated();
|
||||
// call instead of setting bpPosition
|
||||
void setPosition(qlonglong position);
|
||||
void requestPositionUpdate() { this->pPosition.requestUpdate(); };
|
||||
|
@ -462,7 +463,7 @@ private:
|
|||
QS_DBUS_PROPERTY_BINDING(MprisPlayer, qlonglong, pPosition, bpPosition, onPositionUpdated, playerProperties, "Position", false);
|
||||
QS_DBUS_PROPERTY_BINDING(MprisPlayer, pVolume, bVolume, playerProperties, "Volume", false);
|
||||
QS_DBUS_PROPERTY_BINDING(MprisPlayer, pMetadata, bpMetadata, playerProperties, "Metadata");
|
||||
QS_DBUS_PROPERTY_BINDING(MprisPlayer, pPlaybackStatus, bpPlaybackStatus, playerProperties, "PlaybackStatus");
|
||||
QS_DBUS_PROPERTY_BINDING(MprisPlayer, void, pPlaybackStatus, bpPlaybackStatus, onPlaybackStatusUpdated, playerProperties, "PlaybackStatus", true);
|
||||
QS_DBUS_PROPERTY_BINDING(MprisPlayer, pLoopStatus, bpLoopStatus, playerProperties, "LoopStatus", false);
|
||||
QS_DBUS_PROPERTY_BINDING(MprisPlayer, pRate, bRate, playerProperties, "Rate", false);
|
||||
QS_DBUS_PROPERTY_BINDING(MprisPlayer, pMinRate, bMinRate, playerProperties, "MinimumRate", false);
|
||||
|
@ -477,6 +478,8 @@ private:
|
|||
DBusMprisPlayer* player = nullptr;
|
||||
QString mTrackId;
|
||||
QString mTrackUrl;
|
||||
QString mTrackTitle;
|
||||
bool trackChangedBeforeState = false;
|
||||
};
|
||||
|
||||
} // namespace qs::service::mpris
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue