services/pipewire: manage default objs using normal qt properties
Fixes use after free bugs due to pointer mismatches in destructors. Drops SimpleObjectHandle.
This commit is contained in:
parent
c3c3e2ca25
commit
36517a2c10
4 changed files with 83 additions and 75 deletions
|
|
@ -48,6 +48,7 @@ set shell id.
|
|||
- Fixed memory leak in IPC handlers.
|
||||
- Fixed ClippingRectangle related crashes.
|
||||
- Fixed crashes when monitors are unplugged.
|
||||
- Fixed crashes when default pipewire devices are lost.
|
||||
|
||||
## Packaging Changes
|
||||
|
||||
|
|
|
|||
|
|
@ -251,37 +251,6 @@ public:
|
|||
GuardedEmitBlocker block() { return GuardedEmitBlocker(&this->blocked); }
|
||||
};
|
||||
|
||||
template <auto member, auto destroyedSlot, auto changedSignal>
|
||||
class SimpleObjectHandleOps {
|
||||
using Traits = MemberPointerTraits<decltype(member)>;
|
||||
|
||||
public:
|
||||
static bool setObject(Traits::Class* parent, Traits::Type value) {
|
||||
if (value == parent->*member) return false;
|
||||
|
||||
if (parent->*member != nullptr) {
|
||||
QObject::disconnect(parent->*member, &QObject::destroyed, parent, destroyedSlot);
|
||||
}
|
||||
|
||||
parent->*member = value;
|
||||
|
||||
if (value != nullptr) {
|
||||
QObject::connect(parent->*member, &QObject::destroyed, parent, destroyedSlot);
|
||||
}
|
||||
|
||||
if constexpr (changedSignal != nullptr) {
|
||||
emit(parent->*changedSignal)();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template <auto member, auto destroyedSlot, auto changedSignal = nullptr>
|
||||
bool setSimpleObjectHandle(auto* parent, auto* value) {
|
||||
return SimpleObjectHandleOps<member, destroyedSlot, changedSignal>::setObject(parent, value);
|
||||
}
|
||||
|
||||
template <auto methodPtr>
|
||||
class MethodFunctor {
|
||||
using PtrMeta = MemberPointerTraits<decltype(methodPtr)>;
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@
|
|||
#include <spa/utils/json.h>
|
||||
|
||||
#include "../../core/logcat.hpp"
|
||||
#include "../../core/util.hpp"
|
||||
#include "metadata.hpp"
|
||||
#include "node.hpp"
|
||||
#include "registry.hpp"
|
||||
|
|
@ -138,32 +137,6 @@ void PwDefaultTracker::onNodeAdded(PwNode* node) {
|
|||
}
|
||||
}
|
||||
|
||||
void PwDefaultTracker::onNodeDestroyed(QObject* node) {
|
||||
if (node == this->mDefaultSink) {
|
||||
qCInfo(logDefaults) << "Default sink destroyed.";
|
||||
this->mDefaultSink = nullptr;
|
||||
emit this->defaultSinkChanged();
|
||||
}
|
||||
|
||||
if (node == this->mDefaultSource) {
|
||||
qCInfo(logDefaults) << "Default source destroyed.";
|
||||
this->mDefaultSource = nullptr;
|
||||
emit this->defaultSourceChanged();
|
||||
}
|
||||
|
||||
if (node == this->mDefaultConfiguredSink) {
|
||||
qCInfo(logDefaults) << "Default configured sink destroyed.";
|
||||
this->mDefaultConfiguredSink = nullptr;
|
||||
emit this->defaultConfiguredSinkChanged();
|
||||
}
|
||||
|
||||
if (node == this->mDefaultConfiguredSource) {
|
||||
qCInfo(logDefaults) << "Default configured source destroyed.";
|
||||
this->mDefaultConfiguredSource = nullptr;
|
||||
emit this->defaultConfiguredSourceChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void PwDefaultTracker::changeConfiguredSink(PwNode* node) {
|
||||
if (node != nullptr) {
|
||||
if (!node->type.testFlags(PwNodeType::AudioSink)) {
|
||||
|
|
@ -240,10 +213,23 @@ void PwDefaultTracker::setDefaultSink(PwNode* node) {
|
|||
if (node == this->mDefaultSink) return;
|
||||
qCInfo(logDefaults) << "Default sink changed to" << node;
|
||||
|
||||
setSimpleObjectHandle<
|
||||
&PwDefaultTracker::mDefaultSink,
|
||||
&PwDefaultTracker::onNodeDestroyed,
|
||||
&PwDefaultTracker::defaultSinkChanged>(this, node);
|
||||
if (this->mDefaultSink != nullptr) {
|
||||
QObject::disconnect(this->mDefaultSink, nullptr, this, nullptr);
|
||||
}
|
||||
|
||||
this->mDefaultSink = node;
|
||||
|
||||
if (node != nullptr) {
|
||||
QObject::connect(node, &QObject::destroyed, this, &PwDefaultTracker::onDefaultSinkDestroyed);
|
||||
}
|
||||
|
||||
emit this->defaultSinkChanged();
|
||||
}
|
||||
|
||||
void PwDefaultTracker::onDefaultSinkDestroyed() {
|
||||
qCInfo(logDefaults) << "Default sink destroyed.";
|
||||
this->mDefaultSink = nullptr;
|
||||
emit this->defaultSinkChanged();
|
||||
}
|
||||
|
||||
void PwDefaultTracker::setDefaultSinkName(const QString& name) {
|
||||
|
|
@ -257,10 +243,23 @@ void PwDefaultTracker::setDefaultSource(PwNode* node) {
|
|||
if (node == this->mDefaultSource) return;
|
||||
qCInfo(logDefaults) << "Default source changed to" << node;
|
||||
|
||||
setSimpleObjectHandle<
|
||||
&PwDefaultTracker::mDefaultSource,
|
||||
&PwDefaultTracker::onNodeDestroyed,
|
||||
&PwDefaultTracker::defaultSourceChanged>(this, node);
|
||||
if (this->mDefaultSource != nullptr) {
|
||||
QObject::disconnect(this->mDefaultSource, nullptr, this, nullptr);
|
||||
}
|
||||
|
||||
this->mDefaultSource = node;
|
||||
|
||||
if (node != nullptr) {
|
||||
QObject::connect(node, &QObject::destroyed, this, &PwDefaultTracker::onDefaultSourceDestroyed);
|
||||
}
|
||||
|
||||
emit this->defaultSourceChanged();
|
||||
}
|
||||
|
||||
void PwDefaultTracker::onDefaultSourceDestroyed() {
|
||||
qCInfo(logDefaults) << "Default source destroyed.";
|
||||
this->mDefaultSource = nullptr;
|
||||
emit this->defaultSourceChanged();
|
||||
}
|
||||
|
||||
void PwDefaultTracker::setDefaultSourceName(const QString& name) {
|
||||
|
|
@ -274,10 +273,28 @@ void PwDefaultTracker::setDefaultConfiguredSink(PwNode* node) {
|
|||
if (node == this->mDefaultConfiguredSink) return;
|
||||
qCInfo(logDefaults) << "Default configured sink changed to" << node;
|
||||
|
||||
setSimpleObjectHandle<
|
||||
&PwDefaultTracker::mDefaultConfiguredSink,
|
||||
&PwDefaultTracker::onNodeDestroyed,
|
||||
&PwDefaultTracker::defaultConfiguredSinkChanged>(this, node);
|
||||
if (this->mDefaultConfiguredSink != nullptr) {
|
||||
QObject::disconnect(this->mDefaultConfiguredSink, nullptr, this, nullptr);
|
||||
}
|
||||
|
||||
this->mDefaultConfiguredSink = node;
|
||||
|
||||
if (node != nullptr) {
|
||||
QObject::connect(
|
||||
node,
|
||||
&QObject::destroyed,
|
||||
this,
|
||||
&PwDefaultTracker::onDefaultConfiguredSinkDestroyed
|
||||
);
|
||||
}
|
||||
|
||||
emit this->defaultConfiguredSinkChanged();
|
||||
}
|
||||
|
||||
void PwDefaultTracker::onDefaultConfiguredSinkDestroyed() {
|
||||
qCInfo(logDefaults) << "Default configured sink destroyed.";
|
||||
this->mDefaultConfiguredSink = nullptr;
|
||||
emit this->defaultConfiguredSinkChanged();
|
||||
}
|
||||
|
||||
void PwDefaultTracker::setDefaultConfiguredSinkName(const QString& name) {
|
||||
|
|
@ -291,10 +308,28 @@ void PwDefaultTracker::setDefaultConfiguredSource(PwNode* node) {
|
|||
if (node == this->mDefaultConfiguredSource) return;
|
||||
qCInfo(logDefaults) << "Default configured source changed to" << node;
|
||||
|
||||
setSimpleObjectHandle<
|
||||
&PwDefaultTracker::mDefaultConfiguredSource,
|
||||
&PwDefaultTracker::onNodeDestroyed,
|
||||
&PwDefaultTracker::defaultConfiguredSourceChanged>(this, node);
|
||||
if (this->mDefaultConfiguredSource != nullptr) {
|
||||
QObject::disconnect(this->mDefaultConfiguredSource, nullptr, this, nullptr);
|
||||
}
|
||||
|
||||
this->mDefaultConfiguredSource = node;
|
||||
|
||||
if (node != nullptr) {
|
||||
QObject::connect(
|
||||
node,
|
||||
&QObject::destroyed,
|
||||
this,
|
||||
&PwDefaultTracker::onDefaultConfiguredSourceDestroyed
|
||||
);
|
||||
}
|
||||
|
||||
emit this->defaultConfiguredSourceChanged();
|
||||
}
|
||||
|
||||
void PwDefaultTracker::onDefaultConfiguredSourceDestroyed() {
|
||||
qCInfo(logDefaults) << "Default configured source destroyed.";
|
||||
this->mDefaultConfiguredSource = nullptr;
|
||||
emit this->defaultConfiguredSourceChanged();
|
||||
}
|
||||
|
||||
void PwDefaultTracker::setDefaultConfiguredSourceName(const QString& name) {
|
||||
|
|
|
|||
|
|
@ -44,7 +44,10 @@ private slots:
|
|||
void onMetadataAdded(PwMetadata* metadata);
|
||||
void onMetadataProperty(const char* key, const char* type, const char* value);
|
||||
void onNodeAdded(PwNode* node);
|
||||
void onNodeDestroyed(QObject* node);
|
||||
void onDefaultSinkDestroyed();
|
||||
void onDefaultSourceDestroyed();
|
||||
void onDefaultConfiguredSinkDestroyed();
|
||||
void onDefaultConfiguredSourceDestroyed();
|
||||
|
||||
private:
|
||||
void setDefaultSink(PwNode* node);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue