From 37ac24f73170070b69413fb83eeef64d980f3e6a Mon Sep 17 00:00:00 2001 From: Mathias Hasselmann Date: Thu, 14 Nov 2013 00:43:03 +0100 Subject: Start to handle signals properly --- src/QuickStreamer/item.cpp | 83 +++++++++++++++++++++++++++++++++------------- src/QuickStreamer/item.h | 2 +- 2 files changed, 61 insertions(+), 24 deletions(-) diff --git a/src/QuickStreamer/item.cpp b/src/QuickStreamer/item.cpp index 9a716fd..a521241 100644 --- a/src/QuickStreamer/item.cpp +++ b/src/QuickStreamer/item.cpp @@ -74,6 +74,38 @@ struct PropertyDelegate ResetDelegate reset; }; +struct SignalDelegate +{ + typedef std::function SignalClosure; + + static void invokeClosure(void *data) + { + (*static_cast(data))(); + } + + static void deleteClosure(void *data, GClosure *) + { + delete static_cast(data); + } + + void connect(Item *item) const + { + const int signalIndex = methodId; + + auto closure = new SignalClosure([item, signalIndex] { + QMetaObject::activate(item, signalIndex, Q_NULLPTR); // FIXME: deal with signal arguments + }); + + g_signal_connect_data(item->target(), name.constData(), + G_CALLBACK(&SignalDelegate::invokeClosure), closure, + &SignalDelegate::deleteClosure, + G_CONNECT_SWAPPED); + } + + QByteArray name; + int methodId; +}; + static bool isDash(char ch) { return ch == '-' || ch == '_'; @@ -553,15 +585,23 @@ struct TypeInfo const QByteArray &propertyType, QMetaObjectBuilder *objectBuilder) { - auto notifierBuilder = objectBuilder->addSignal(propertyName + QByteArrayLiteral("Changed()")); - auto propertyBuilder = objectBuilder->addProperty(propertyName, propertyType, notifierBuilder.index()); + int notifierIndex = -1; + + if (delegate.spec) { + auto notifier = objectBuilder->addSignal(propertyName + QByteArrayLiteral("Changed()")); + signalDelegates.append({ QByteArrayLiteral("notify::") + delegate.spec->name, + parent->metaObject->methodCount() + notifier.index() }); + notifierIndex = notifier.index(); + } + + auto property = objectBuilder->addProperty(propertyName, propertyType, notifierIndex); - propertyBuilder.setReadable(delegate.read != Q_NULLPTR); - propertyBuilder.setWritable(delegate.write != Q_NULLPTR); - propertyBuilder.setResettable(delegate.reset != Q_NULLPTR); + property.setReadable(delegate.read != Q_NULLPTR); + property.setWritable(delegate.write != Q_NULLPTR); + property.setResettable(delegate.reset != Q_NULLPTR); if (propertyType.endsWith(ENUMERATOR_TYPE_SUFFIX)) { // FIXME - propertyBuilder.setEnumOrFlag(true); + property.setEnumOrFlag(true); const auto &scopeName = propertyType.left(propertyType.length() - ENUMERATOR_TYPE_SUFFIX.length()); const int scopeId = QMetaType::type(scopeName.constData()); @@ -785,20 +825,18 @@ struct TypeInfo return id - propertyDelegates.size(); } - void emitPropertyChanged(Item *object, const GParamSpec *pspec) const + int connectSignal(Item *item, int id) const { - for (int i = 0; i < propertyDelegates.size(); ++i) { - auto const &p = propertyDelegates.at(i); + if (parent) + id = parent->connectSignal(item, id); - // can compare by pointer because GParamSpec::name is interned - if (p.spec && pspec->name == p.spec->name) { - QMetaObject::activate(object, metaObject, i, Q_NULLPTR); - return; - } - } + if (id < 0) + return id; - if (parent) - parent->emitPropertyChanged(object, pspec); + if (id < signalDelegates.size()) + signalDelegates.at(id).connect(item); + + return id - signalDelegates.size(); } const TypeInfo *parent; @@ -806,6 +844,8 @@ struct TypeInfo QByteArray elementName; QVector propertyDelegates; + QVector signalDelegates; + static QHash cache; }; @@ -826,9 +866,6 @@ Item::Item(GstObject *target, QObject *parent) g_object_ref_sink(m_target); g_object_set_qdata(G_OBJECT(m_target), ITEM_DATA_QUARK, this); - - auto notifyCallback = reinterpret_cast(&Item::emitPropertyChanged); - g_signal_connect_swapped(target, "notify", notifyCallback, this); } Item::Item(const Item &other) @@ -953,10 +990,10 @@ GstObject *Item::target() const return m_target; } -void Item::emitPropertyChanged(Item *self, GParamSpec *pspec) +void Item::connectNotify(const QMetaMethod &signal) { - const auto *const typeInfo = TypeInfo::find(G_OBJECT_TYPE(self->m_target)); - typeInfo->emitPropertyChanged(self, pspec); + const int signalIndex = signal.methodIndex() - QObject::staticMetaObject.methodCount(); + TypeInfo::find(G_OBJECT_TYPE(m_target))->connectSignal(this, signalIndex); } } // namespace QQuickStreamer diff --git a/src/QuickStreamer/item.h b/src/QuickStreamer/item.h index 2a2830c..99ba21d 100644 --- a/src/QuickStreamer/item.h +++ b/src/QuickStreamer/item.h @@ -57,7 +57,7 @@ public: GstObject *target() const; protected: - static void emitPropertyChanged(Item *self, GParamSpec *pspec); + void connectNotify(const QMetaMethod &signal) Q_DECL_OVERRIDE; private: GstObject *const m_target; -- cgit v1.2.3