summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Olbrich <m.olbrich@pengutronix.de>2013-11-19 08:54:15 +0100
committerMichael Olbrich <m.olbrich@pengutronix.de>2013-11-19 08:54:15 +0100
commitac24e816eda177e583bea019b7b98f2111291804 (patch)
tree9efcdbe1a2bfaf7ab9cd3b78c68614d77cbed560
parentb3547cc3368d3558c193604e71c24c7cbbdb9ba6 (diff)
downloadqtquickstreamer-signals.tar.gz
qtquickstreamer-signals.tar.xz
Impelement signal argumentssignals
-rw-r--r--src/QuickStreamer/item.cpp204
-rw-r--r--src/QuickStreamer/item.h1
2 files changed, 190 insertions, 15 deletions
diff --git a/src/QuickStreamer/item.cpp b/src/QuickStreamer/item.cpp
index e934f6c..91da974 100644
--- a/src/QuickStreamer/item.cpp
+++ b/src/QuickStreamer/item.cpp
@@ -76,11 +76,14 @@ struct PropertyDelegate
struct SignalDelegate
{
- typedef std::function<void()> SignalClosure;
+ typedef std::function<void(va_list *)> SignalClosure;
- static void invokeClosure(void *data)
+ static void invokeClosure(void *data, ...)
{
- (*static_cast<SignalClosure *>(data))();
+ va_list args;
+ va_start(args, data);
+
+ (*static_cast<SignalClosure *>(data))(&args);
}
static void deleteClosure(void *data, GClosure *)
@@ -88,24 +91,161 @@ struct SignalDelegate
delete static_cast<SignalClosure *>(data);
}
- void connect(Item *item) const
+ void connect(Item *item) const;
+ void activate(Item *object, va_list *args) const
{
- const int signalIndex = methodId;
+ QVarLengthArray<qint64, 10> values(paramTypes.count()+1);
+ QVarLengthArray<void*, 10> params(paramTypes.count()+1);
+ QStringList strings;
+ QList<Item*> objects;
+
+ for (int i = 1; i <= paramTypes.count(); ++i) {
+ params[i] = &values[i];
+ switch(const auto type = paramTypes[i-1])
+ {
+ case G_TYPE_CHAR:
+ *reinterpret_cast<char *>(&values[i]) = va_arg(*args, int);
+ break;
+
+ case G_TYPE_UCHAR:
+ *reinterpret_cast<uchar *>(&values[i]) = va_arg(*args, int);
+ break;
+
+ case G_TYPE_BOOLEAN:
+ *reinterpret_cast<bool *>(&values[i]) = va_arg(*args, int);
+ break;
+
+ case G_TYPE_INT:
+ *reinterpret_cast<int *>(&values[i]) = va_arg(*args, int);
+ break;
+
+ case G_TYPE_UINT:
+ *reinterpret_cast<uint *>(&values[i]) = va_arg(*args, uint);
+ break;
+
+ case G_TYPE_LONG:
+ *reinterpret_cast<long *>(&values[i]) = va_arg(*args, ulong);
+ break;
+
+ case G_TYPE_ULONG:
+ *reinterpret_cast<ulong *>(&values[i]) = va_arg(*args, ulong);
+ break;
+
+ case G_TYPE_INT64:
+ *reinterpret_cast<qint64 *>(&values[i]) = va_arg(*args, qint64);
+ break;
+
+ case G_TYPE_UINT64:
+ *reinterpret_cast<quint64 *>(&values[i]) = va_arg(*args, quint64);
+ break;
+
+ case G_TYPE_FLOAT:
+ *reinterpret_cast<float *>(&values[i]) = va_arg(*args, double);
+ break;
+
+ case G_TYPE_DOUBLE:
+ *reinterpret_cast<double *>(&values[i]) = va_arg(*args, double);
+ break;
+
+ case G_TYPE_STRING:
+ strings.append(QString(va_arg(*args, char*)));
+ params[i] = &strings.last();
+ break;
+
+ case G_TYPE_POINTER:
+ *reinterpret_cast<void **>(&values[i]) = va_arg(*args, void*);
+ break;
+
+ //case G_TYPE_BOXED G_TYPE_MAKE_FUNDAMENTAL (18)
+ //case G_TYPE_PARAM G_TYPE_MAKE_FUNDAMENTAL (19)
+ //case G_TYPE_OBJECT G_TYPE_MAKE_FUNDAMENTAL (20)
+ //case G_TYPE_VARIANT G_TYPE_MAKE_FUNDAMENTAL (21)
+
+ default:
+ if (g_type_is_a(type, G_TYPE_ENUM)) {
+ *reinterpret_cast<int *>(&values[i]) = va_arg(*args, int);
+ break;
+ }
+
+ if (g_type_is_a(type, G_TYPE_FLAGS)) {
+ *reinterpret_cast<uint *>(&values[i]) = va_arg(*args, uint);
+ break;
+ }
- auto closure = new SignalClosure([item, signalIndex] {
- QMetaObject::activate(item, signalIndex, Q_NULLPTR); // FIXME: deal with signal arguments
- });
+ if (g_type_is_a(type, GST_TYPE_OBJECT)) {
+ GstObject *gobject = va_arg(*args, GstObject*);
+ if (GST_IS_PAD(gobject)) {
+ }
+ objects.append(new Item(gobject));
+ params[i] = &objects.last();
+ break;
+ }
- g_signal_connect_data(item->target(), name.constData(),
- G_CALLBACK(&SignalDelegate::invokeClosure), closure,
- &SignalDelegate::deleteClosure,
- G_CONNECT_SWAPPED);
+ qWarning("Cannot convert unsupported GValue type: %s", G_VALUE_TYPE_NAME(type));
+ values[i] = 0;
+ va_arg(*args, void*);
+ break;
+ }
+ }
+ QMetaObject::activate(object, methodId, params.data());
+ qDeleteAll(objects);
}
QByteArray name;
int methodId;
+ QVector<GType> paramTypes;
};
+class SignalEvent : public QEvent
+{
+public:
+ SignalEvent(Item *item, const SignalDelegate *signal, va_list *args, QSemaphore *semaphore)
+ : QEvent(static_cast<QEvent::Type>(type))
+ , m_item(item)
+ , m_signal(signal)
+ , m_args(args)
+ , m_semaphore(semaphore)
+ {}
+
+ static void sendSignal(Item *item, const SignalDelegate *signal, va_list *args)
+ {
+ QSemaphore semaphore;
+ SignalEvent *event = new SignalEvent(item, signal, args, &semaphore);
+ QCoreApplication::postEvent(item, event);
+ semaphore.acquire();
+ }
+
+ void activate()
+ {
+ m_signal->activate(m_item, m_args);
+ m_semaphore->release();
+ }
+
+ static int type;
+private:
+ Item *m_item;
+ const SignalDelegate *m_signal;
+ va_list *m_args;
+ QSemaphore *m_semaphore;
+};
+
+int SignalEvent::type = QEvent::registerEventType();
+
+void SignalDelegate::connect(Item *item) const
+{
+ auto closure = new SignalClosure([item, this](va_list *args) {
+ if (QThread::currentThread() == item->thread())
+ this->activate(item, args);
+ else
+ SignalEvent::sendSignal(item, this, args);
+ });
+
+ g_signal_connect_data(item->target(), name.constData(),
+ G_CALLBACK(&SignalDelegate::invokeClosure), closure,
+ &SignalDelegate::deleteClosure,
+ G_CONNECT_SWAPPED);
+}
+
static bool isDash(char ch)
{
return ch == '-' || ch == '_';
@@ -608,7 +748,7 @@ struct TypeInfo
if (delegate.spec) {
auto notifier = objectBuilder->addSignal(propertyName + QByteArrayLiteral("Changed()"));
signalDelegates.append({ QByteArrayLiteral("notify::") + delegate.spec->name,
- parent->metaObject->methodCount() + notifier.index() });
+ parent->metaObject->methodCount() + notifier.index(), {} });
notifierIndex = notifier.index();
}
@@ -716,7 +856,32 @@ struct TypeInfo
GSignalQuery query;
g_signal_query(signalIds[i], &query);
Q_ASSERT(signalIds[i] == query.signal_id);
- qDebug("FIXME: register signal %s::%s", g_type_name(type), query.signal_name);
+ if (query.signal_flags & G_SIGNAL_ACTION) {
+ qDebug("FIXME: register action %s::%s", g_type_name(type), query.signal_name);
+ } else {
+ auto signalName = toCamelCase(query.signal_name, std::tolower);
+ auto signature = signalName + '(';
+ QList<QByteArray> names;
+ QVector<GType> paramTypes;
+ QByteArray args;
+ for (uint i = 0; i < query.n_params; ++i) {
+ names.append(QByteArrayLiteral("arg") + QByteArray::number(i));
+ if (!args.isNull())
+ args.append(',');
+ args.append(metaTypeName(query.param_types[i]));
+ paramTypes.append(query.param_types[i]);
+ }
+ signature.append(args);
+ signature.append(')');
+ auto signal = objectBuilder.addSignal(signature);
+ signal.setParameterNames(names);
+
+ int index = signal.index();
+ if (typeInfo->parent)
+ index += typeInfo->parent->metaObject->methodCount();
+ typeInfo->signalDelegates.append({ QByteArray(query.signal_name), index,
+ paramTypes });
+ }
}
typedef QtMetaTypePrivate::QMetaTypeFunctionHelper<Item*> MetaTypeHelper;
@@ -864,7 +1029,6 @@ struct TypeInfo
QByteArray elementName;
QVector<PropertyDelegate> propertyDelegates;
QVector<SignalDelegate> signalDelegates;
-
static QHash<GType, TypeInfo *> cache;
};
@@ -1032,6 +1196,16 @@ void Item::componentComplete()
}
}
+bool Item::event(QEvent *e)
+{
+ if (e->type() == Private::SignalEvent::type) {
+ Private::SignalEvent *event = static_cast<Private::SignalEvent*>(e);
+ event->activate();
+ return true;
+ }
+ return QObject::event(e);
+}
+
GstObject *Item::target() const
{
return m_target;
diff --git a/src/QuickStreamer/item.h b/src/QuickStreamer/item.h
index 775b2e1..56826a2 100644
--- a/src/QuickStreamer/item.h
+++ b/src/QuickStreamer/item.h
@@ -54,6 +54,7 @@ public:
void classBegin() Q_DECL_OVERRIDE;
void componentComplete() Q_DECL_OVERRIDE;
+ bool event(QEvent *e) Q_DECL_OVERRIDE;
GstObject *target() const;