Skip to content

Commit dca75b7

Browse files
committed
service/mpris: clarify trackinfo emit order and use QBindings
1 parent 8450543 commit dca75b7

File tree

5 files changed

+79
-67
lines changed

5 files changed

+79
-67
lines changed

src/core/util.hpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
#include <qlatin1stringview.h>
66
#include <qobject.h>
7+
#include <qproperty.h>
78
#include <qtclasshelpermacros.h>
89
#include <qtmetamacros.h>
910

@@ -258,3 +259,12 @@ template <auto member, auto destroyedSlot, auto changedSignal = nullptr>
258259
bool setSimpleObjectHandle(auto* parent, auto* value) {
259260
return SimpleObjectHandleOps<member, destroyedSlot, changedSignal>::setObject(parent, value);
260261
}
262+
263+
// NOLINTBEGIN
264+
#define QS_TRIVIAL_GETTER(Type, member, getter) \
265+
[[nodiscard]] Type getter() { return this->member; }
266+
267+
#define QS_BINDABLE_GETTER(Type, member, getter, bindable) \
268+
[[nodiscard]] Type getter() { return this->member.value(); } \
269+
[[nodiscard]] QBindable<Type> bindable() { return &this->member; }
270+
// NOLINTEND

src/services/mpris/player.cpp

Lines changed: 23 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <qlogging.h>
88
#include <qloggingcategory.h>
99
#include <qobject.h>
10+
#include <qproperty.h>
1011
#include <qstring.h>
1112
#include <qtmetamacros.h>
1213
#include <qtypes.h>
@@ -256,19 +257,13 @@ void MprisPlayer::setVolume(qreal volume) {
256257
this->pVolume.write();
257258
}
258259

259-
const QVariantMap& MprisPlayer::metadata() const { return this->pMetadata.get(); }
260-
261260
void MprisPlayer::onMetadataChanged() {
262-
emit this->metadataChanged();
263-
264261
auto lengthVariant = this->pMetadata.get().value("mpris:length");
265262
qlonglong length = -1;
266263
if (lengthVariant.isValid() && lengthVariant.canConvert<qlonglong>()) {
267264
length = lengthVariant.value<qlonglong>();
268265
}
269266

270-
auto lengthChanged = this->setLength(length);
271-
272267
auto trackChanged = false;
273268

274269
QString trackId;
@@ -297,47 +292,43 @@ void MprisPlayer::onMetadataChanged() {
297292
}
298293
}
299294

295+
if (trackChanged) {
296+
emit this->trackChanged();
297+
}
298+
299+
Qt::beginPropertyUpdateGroup();
300+
301+
this->bMetadata = this->pMetadata.get();
302+
300303
auto trackTitle = this->pMetadata.get().value("xesam:title").toString();
301-
auto trackTitleChanged = this->setTrackTitle(trackTitle.isNull() ? "Unknown Track" : trackTitle);
304+
this->bTrackTitle = trackTitle.isNull() ? "Unknown Track" : trackTitle;
302305

303-
auto trackArtists = this->pMetadata.get().value("xesam:artist").value<QVector<QString>>();
304-
auto trackArtistsChanged = this->setTrackArtists(trackArtists.join(", "));
306+
auto trackArtist = this->pMetadata.get().value("xesam:artist").value<QVector<QString>>();
307+
this->bTrackArtist = trackArtist.join(", ");
305308

306309
auto trackAlbum = this->pMetadata.get().value("xesam:album").toString();
307-
auto trackAlbumChanged = this->setTrackAlbum(trackAlbum.isNull() ? "Unknown Album" : trackAlbum);
310+
this->bTrackAlbum = trackAlbum.isNull() ? "Unknown Album" : trackAlbum;
308311

309-
auto trackAlbumArtist = this->pMetadata.get().value("xesam:albumArtist").toString();
310-
auto trackAlbumArtistChanged = this->setTrackAlbumArtist(trackAlbumArtist);
311-
312-
auto trackArtUrl = this->pMetadata.get().value("mpris:artUrl").toString();
313-
auto trackArtUrlChanged = this->setTrackArtUrl(trackArtUrl);
312+
this->bTrackAlbumArtist = this->pMetadata.get().value("xesam:albumArtist").toString();
313+
this->bTrackArtUrl = this->pMetadata.get().value("mpris:artUrl").toString();
314314

315315
if (trackChanged) {
316-
this->mUniqueId++;
316+
emit this->trackChanged();
317+
this->bUniqueId = this->bUniqueId + 1;
318+
317319
// Some players don't seem to send position updates or seeks on track change.
318320
this->pPosition.update();
319-
emit this->trackChanged();
320321
}
321322

322-
DropEmitter::call(
323-
trackTitleChanged,
324-
trackArtistsChanged,
325-
trackAlbumChanged,
326-
trackAlbumArtistChanged,
327-
trackArtUrlChanged,
328-
lengthChanged
329-
);
323+
Qt::endPropertyUpdateGroup();
324+
325+
this->setLength(length);
326+
327+
emit this->postTrackChanged();
330328
}
331329

332-
DEFINE_MEMBER_GET(MprisPlayer, uniqueId);
333330
DEFINE_MEMBER_SET(MprisPlayer, length, setLength);
334331

335-
DEFINE_MEMBER_GETSET(MprisPlayer, trackTitle, setTrackTitle);
336-
DEFINE_MEMBER_GETSET(MprisPlayer, trackArtists, setTrackArtists);
337-
DEFINE_MEMBER_GETSET(MprisPlayer, trackAlbum, setTrackAlbum);
338-
DEFINE_MEMBER_GETSET(MprisPlayer, trackAlbumArtist, setTrackAlbumArtist);
339-
DEFINE_MEMBER_GETSET(MprisPlayer, trackArtUrl, setTrackArtUrl);
340-
341332
MprisPlaybackState::Enum MprisPlayer::playbackState() const { return this->mPlaybackState; }
342333

343334
void MprisPlayer::setPlaybackState(MprisPlaybackState::Enum playbackState) {

src/services/mpris/player.hpp

Lines changed: 42 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
#include <qcontainerfwd.h>
44
#include <qobject.h>
5+
#include <qproperty.h>
56
#include <qqmlintegration.h>
67
#include <qtmetamacros.h>
78
#include <qtypes.h>
@@ -125,25 +126,27 @@ class MprisPlayer: public QObject {
125126
/// A map of common properties is available [here](https://www.freedesktop.org/wiki/Specifications/mpris-spec/metadata).
126127
/// Do not count on any of them actually being present.
127128
///
128-
/// Note that the @@trackTitle, @@trackAlbum, @@trackAlbumArtist, @@trackArtists and @@trackArtUrl
129+
/// Note that the @@trackTitle, @@trackAlbum, @@trackAlbumArtist, @@trackArtist and @@trackArtUrl
129130
/// properties have extra logic to guard against bad players sending weird metadata, and should
130131
/// be used over grabbing the properties directly from the metadata.
131-
Q_PROPERTY(QVariantMap metadata READ metadata NOTIFY metadataChanged);
132+
Q_PROPERTY(QVariantMap metadata READ metadata NOTIFY metadataChanged BINDABLE bindableMetadata);
132133
/// An opaque identifier for the current track unique within the current player.
133134
///
134135
/// > [!WARNING] This is NOT `mpris:trackid` as that is sometimes missing or nonunique
135136
/// > in some players.
136-
Q_PROPERTY(quint32 uniqueId READ uniqueId NOTIFY trackChanged);
137+
Q_PROPERTY(quint32 uniqueId READ uniqueId NOTIFY trackChanged BINDABLE bindableUniqueId);
137138
/// The title of the current track, or "Unknown Track" if none was provided.
138-
Q_PROPERTY(QString trackTitle READ trackTitle NOTIFY trackTitleChanged);
139+
Q_PROPERTY(QString trackTitle READ trackTitle NOTIFY trackTitleChanged BINDABLE bindableTrackTitle);
140+
/// The current track's artist, or an empty string if none was provided.
141+
Q_PROPERTY(QString trackArtist READ trackArtist NOTIFY trackArtistChanged BINDABLE bindableTrackArtist);
142+
/// > [!ERROR] deprecated in favor of @@trackArtist.
143+
Q_PROPERTY(QString trackArtists READ trackArtist NOTIFY trackArtistChanged BINDABLE bindableTrackArtist);
139144
/// The current track's album, or "Unknown Album" if none was provided.
140-
Q_PROPERTY(QString trackAlbum READ trackAlbum NOTIFY trackAlbumChanged);
145+
Q_PROPERTY(QString trackAlbum READ trackAlbum NOTIFY trackAlbumChanged BINDABLE bindableTrackAlbum);
141146
/// The current track's album artist, or "Unknown Artist" if none was provided.
142-
Q_PROPERTY(QString trackAlbumArtist READ trackAlbumArtist NOTIFY trackAlbumArtistChanged);
143-
/// The current track's artists, or an empty list if none were provided.
144-
Q_PROPERTY(QString trackArtists READ trackArtists NOTIFY trackArtistsChanged);
147+
Q_PROPERTY(QString trackAlbumArtist READ trackAlbumArtist NOTIFY trackAlbumArtistChanged BINDABLE bindableTrackAlbumArtist);
145148
/// The current track's art url, or `""` if none was provided.
146-
Q_PROPERTY(QString trackArtUrl READ trackArtUrl NOTIFY trackArtUrlChanged);
149+
Q_PROPERTY(QString trackArtUrl READ trackArtUrl NOTIFY trackArtUrlChanged BINDABLE bindableTrackArtUrl);
147150
/// The playback state of the media player.
148151
///
149152
/// - If @@canPlay is false, you cannot assign the `Playing` state.
@@ -254,7 +257,13 @@ class MprisPlayer: public QObject {
254257
[[nodiscard]] bool volumeSupported() const;
255258
void setVolume(qreal volume);
256259

257-
[[nodiscard]] const QVariantMap& metadata() const;
260+
QS_BINDABLE_GETTER(quint32, bUniqueId, uniqueId, bindableUniqueId);
261+
QS_BINDABLE_GETTER(QVariantMap, bMetadata, metadata, bindableMetadata);
262+
QS_BINDABLE_GETTER(QString, bTrackTitle, trackTitle, bindableTrackTitle);
263+
QS_BINDABLE_GETTER(QString, bTrackAlbum, trackAlbum, bindableTrackAlbum);
264+
QS_BINDABLE_GETTER(QString, bTrackAlbumArtist, trackAlbumArtist, bindableTrackAlbumArtist);
265+
QS_BINDABLE_GETTER(QString, bTrackArtist, trackArtist, bindableTrackArtist);
266+
QS_BINDABLE_GETTER(QString, bTrackArtUrl, trackArtUrl, bindableTrackArtUrl);
258267

259268
[[nodiscard]] MprisPlaybackState::Enum playbackState() const;
260269
void setPlaybackState(MprisPlaybackState::Enum playbackState);
@@ -281,9 +290,22 @@ class MprisPlayer: public QObject {
281290
signals:
282291
/// The track has changed.
283292
///
284-
/// All track info change signalss will fire immediately after if applicable,
285-
/// but their values will be updated before the signal fires.
293+
/// All track information properties that were sent by the player
294+
/// will be updated immediately following this signal. @@postTrackChanged
295+
/// will be sent after they update.
296+
///
297+
/// Track information properties: @@uniqueId, @@metadata, @@trackTitle,
298+
/// @@trackArtist, @@trackAlbum, @@trackAlbumArtist, @@trackArtUrl
299+
///
300+
/// > [!WARNING] Some particularly poorly behaved players will update metadata
301+
/// > *before* indicating the track has changed.
286302
void trackChanged();
303+
/// Sent after track info related properties have been updated, following @@trackChanged.
304+
///
305+
/// > [!WARNING] It is not safe to assume all track information is up to date after
306+
/// > this signal is emitted. A large number of players will update track information,
307+
/// > particularly @@trackArtUrl, slightly after this signal.
308+
void postTrackChanged();
287309

288310
QSDOC_HIDE void ready();
289311
void canControlChanged();
@@ -306,9 +328,9 @@ class MprisPlayer: public QObject {
306328
void volumeSupportedChanged();
307329
void metadataChanged();
308330
void trackTitleChanged();
331+
void trackArtistChanged();
309332
void trackAlbumChanged();
310333
void trackAlbumArtistChanged();
311-
void trackArtistsChanged();
312334
void trackArtUrlChanged();
313335
void playbackStateChanged();
314336
void loopStateChanged();
@@ -369,30 +391,21 @@ private slots:
369391

370392
DBusMprisPlayerApp* app = nullptr;
371393
DBusMprisPlayer* player = nullptr;
372-
quint32 mUniqueId = 0;
373394
QString mTrackId;
374395
QString mTrackUrl;
375-
QString mTrackTitle;
376-
QString mTrackArtists;
377-
QString mTrackAlbum;
378-
QString mTrackAlbumArtist;
379-
QString mTrackArtUrl;
380-
381-
DECLARE_MEMBER_NS(MprisPlayer, uniqueId, mUniqueId);
382396

383397
DECLARE_MEMBER(MprisPlayer, length, mLength, lengthChanged);
384398
DECLARE_MEMBER_SET(length, setLength);
385399

386400
// clang-format off
387-
DECLARE_PRIVATE_MEMBER(MprisPlayer, trackTitle, setTrackTitle, mTrackTitle, trackTitleChanged);
388-
DECLARE_PRIVATE_MEMBER(MprisPlayer, trackArtists, setTrackArtists, mTrackArtists, trackArtistsChanged);
389-
DECLARE_PRIVATE_MEMBER(MprisPlayer, trackAlbum, setTrackAlbum, mTrackAlbum, trackAlbumChanged);
390-
DECLARE_PRIVATE_MEMBER(MprisPlayer, trackAlbumArtist, setTrackAlbumArtist, mTrackAlbumArtist, trackAlbumArtistChanged);
391-
DECLARE_PRIVATE_MEMBER(MprisPlayer, trackArtUrl, setTrackArtUrl, mTrackArtUrl, trackArtUrlChanged);
401+
Q_OBJECT_BINDABLE_PROPERTY(MprisPlayer, quint32, bUniqueId);
402+
Q_OBJECT_BINDABLE_PROPERTY(MprisPlayer, QVariantMap, bMetadata, &MprisPlayer::metadataChanged);
403+
Q_OBJECT_BINDABLE_PROPERTY(MprisPlayer, QString, bTrackArtist, &MprisPlayer::trackArtistChanged);
404+
Q_OBJECT_BINDABLE_PROPERTY(MprisPlayer, QString, bTrackTitle, &MprisPlayer::trackTitleChanged);
405+
Q_OBJECT_BINDABLE_PROPERTY(MprisPlayer, QString, bTrackAlbum, &MprisPlayer::trackAlbumChanged);
406+
Q_OBJECT_BINDABLE_PROPERTY(MprisPlayer, QString, bTrackAlbumArtist, &MprisPlayer::trackAlbumArtistChanged);
407+
Q_OBJECT_BINDABLE_PROPERTY(MprisPlayer, QString, bTrackArtUrl, &MprisPlayer::trackArtUrlChanged);
392408
// clang-format on
393-
394-
public:
395-
DECLARE_MEMBER_GET(uniqueId);
396409
};
397410

398411
} // namespace qs::service::mpris

src/wayland/popupanchor.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@
44
#include <private/qwayland-xdg-shell.h>
55
#include <private/qwaylandwindow_p.h>
66
#include <private/wayland-xdg-shell-client-protocol.h>
7+
#include <qtmetamacros.h>
78
#include <qvariant.h>
89
#include <qwindow.h>
9-
#include <qtmetamacros.h>
1010

1111
#include "../core/popupanchor.hpp"
1212
#include "../core/types.hpp"

src/window/popupwindow.cpp

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
#include "popupwindow.hpp"
22

3-
#include <qlogging.h>
43
#include <qnamespace.h>
54
#include <qobject.h>
65
#include <qqmlinfo.h>
@@ -42,9 +41,7 @@ void ProxyPopupWindow::setParentWindow(QObject* parent) {
4241
this->mAnchor.setWindow(parent);
4342
}
4443

45-
QObject* ProxyPopupWindow::parentWindow() const {
46-
return this->mAnchor.window();
47-
}
44+
QObject* ProxyPopupWindow::parentWindow() const { return this->mAnchor.window(); }
4845

4946
void ProxyPopupWindow::updateTransientParent() {
5047
auto* bw = this->mAnchor.backingWindow();
@@ -70,7 +67,8 @@ void ProxyPopupWindow::updateTransientParent() {
7067
void ProxyPopupWindow::onParentUpdated() { this->updateTransientParent(); }
7168

7269
void ProxyPopupWindow::setScreen(QuickshellScreenInfo* /*unused*/) {
73-
qmlWarning(this) << "Cannot set screen of popup window, as that is controlled by the parent window";
70+
qmlWarning(this
71+
) << "Cannot set screen of popup window, as that is controlled by the parent window";
7472
}
7573

7674
void ProxyPopupWindow::setVisible(bool visible) {

0 commit comments

Comments
 (0)