diff --git a/src/services/pipewire/qml.cpp b/src/services/pipewire/qml.cpp index 5d8c45e7..9efb17eb 100644 --- a/src/services/pipewire/qml.cpp +++ b/src/services/pipewire/qml.cpp @@ -18,6 +18,16 @@ namespace qs::service::pipewire { +PwObjectIface::PwObjectIface(PwBindableObject* object): QObject(object), object(object) { + // We want to destroy the interface before QObject::destroyed is fired, as handlers + // connected before PwObjectIface will run first and emit signals that hit user code, + // which can then try to reference the iface again after ~PwNode() has been called but + // before ~QObject() has finished. + QObject::connect(object, &PwBindableObject::destroying, this, &PwObjectIface::onObjectDestroying); +} + +void PwObjectIface::onObjectDestroying() { delete this; } + void PwObjectIface::ref() { this->refcount++; diff --git a/src/services/pipewire/qml.hpp b/src/services/pipewire/qml.hpp index 5bcc70d4..e3489a1c 100644 --- a/src/services/pipewire/qml.hpp +++ b/src/services/pipewire/qml.hpp @@ -36,7 +36,7 @@ class PwObjectIface Q_OBJECT; public: - explicit PwObjectIface(PwBindableObject* object): QObject(object), object(object) {}; + explicit PwObjectIface(PwBindableObject* object); // destructor should ONLY be called by the pw object destructor, making an unref unnecessary ~PwObjectIface() override = default; Q_DISABLE_COPY_MOVE(PwObjectIface); @@ -44,6 +44,9 @@ public: void ref() override; void unref() override; +private slots: + void onObjectDestroying(); + private: quint32 refcount = 0; PwBindableObject* object;