summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMathias Hasselmann <mathias.hasselmann@kdab.com>2013-10-29 20:04:19 +0100
committerMathias Hasselmann <mathias.hasselmann@kdab.com>2013-10-29 20:04:19 +0100
commit2b291759186876e189de36d4404b40f7b696e013 (patch)
treeacd876d0c58afa4020abc745af7beadc330ad888
parent8dc7502ac0a86569945769d790ed79b4cd966079 (diff)
downloadqtquickstreamer-2b291759186876e189de36d4404b40f7b696e013.tar.gz
qtquickstreamer-2b291759186876e189de36d4404b40f7b696e013.tar.xz
More work
-rw-r--r--src/makemetapads.cpp208
-rw-r--r--src/makemetapads.pro6
-rw-r--r--src/metapads.h16
-rw-r--r--src/object.cpp351
-rw-r--r--src/object.h37
-rw-r--r--src/plugin.cpp48
-rw-r--r--src/qtquickstreamerplugin.pro20
-rw-r--r--src/src.pro8
-rw-r--r--tests/tests.pro4
-rw-r--r--tests/tst_qml/tst_qml.pro13
-rw-r--r--tests/tst_qml/tst_qmltest.cpp32
-rw-r--r--tests/tst_wrapping/tst_wrappingtest.cpp6
12 files changed, 560 insertions, 189 deletions
diff --git a/src/makemetapads.cpp b/src/makemetapads.cpp
new file mode 100644
index 0000000..e669700
--- /dev/null
+++ b/src/makemetapads.cpp
@@ -0,0 +1,208 @@
+#include <QCoreApplication>
+#include <QStringList>
+#include <QTextStream>
+
+int main(int argc, char **argv)
+{
+ QCoreApplication app(argc, argv);
+ const auto &args = app.arguments();
+
+ if (args.count() != 3) {
+ QTextStream(stderr) << QStringLiteral("Usage: %1 TYPE-COUNT FACTORY-COUNT").arg(args.first()) << endl;
+ return EXIT_FAILURE;
+ }
+
+ bool isTypeCount = false;
+ const int typeCount = args.at(1).toInt(&isTypeCount);
+
+ if (not isTypeCount || typeCount < 1) {
+ QTextStream(stderr) << QStringLiteral("%1: Invalid type pad count").arg(args.first()) << endl;
+ return EXIT_FAILURE;
+ }
+
+ bool isFactoryCount = false;
+ const int factoryCount = args.at(2).toInt(&isFactoryCount);
+
+ if (not isFactoryCount || factoryCount < 1) {
+ QTextStream(stderr) << QStringLiteral("%1: Invalid factory pad count").arg(args.first()) << endl;
+ return EXIT_FAILURE;
+ }
+
+ QTextStream out(stdout);
+
+ out << "#include \"metapads.h\"" << endl
+ << "#include \"object.h\"" << endl
+ << "#include <gst/gst.h>" << endl
+ << "#include <QVector>" << endl
+ << endl
+ << "namespace QQuickStreamer {" << endl
+ << "namespace Private {" << endl
+ << endl
+ << "static QVector<GType> objectTypes;" << endl
+ << "static QVector<GstElementFactory *> elementFactories;" << endl
+ << endl
+ << "static void *createObject(int which, const void *t) Q_DECL_NOEXCEPT" << endl
+ << "{" << endl
+ << " if (t)" << endl
+ << " return new Object(*static_cast<const Object*>(t));" << endl
+ << endl
+ << " const auto type = objectTypes.at(which);" << endl
+ << " return new Object(GST_OBJECT(g_object_newv(type, 0, Q_NULLPTR)));" << endl
+ << "}" << endl
+ << endl
+ << "static void *constructObject(int which, void *where, const void *t) Q_DECL_NOEXCEPT" << endl
+ << "{" << endl
+ << " if (t)" << endl
+ << " return new(where) Object(*static_cast<const Object*>(t));" << endl
+ << endl
+ << " const auto type = objectTypes.at(which);" << endl
+ << " return new(where) Object(GST_OBJECT(g_object_newv(type, 0, Q_NULLPTR)));" << endl
+ << "}" << endl
+ << endl;
+
+ for (int i = 0; i < typeCount; ++i) {
+ out << "static void *createObject" << i << "(const void *t) Q_DECL_NOEXCEPT" << endl
+ << "{" << endl
+ << " return createObject(" << i << ", t);" << endl
+ << "}" << endl
+ << endl
+ << "static void *constructObject" << i << "(void *where, const void *t) Q_DECL_NOEXCEPT" << endl
+ << "{" << endl
+ << " return constructObject(" << i << ", where, t);" << endl
+ << "}" << endl
+ << endl;
+ }
+
+ /*
+ for (int i = 0; i < typeCount; ++i) {
+ out << "static void *createObject" << i << "(const void *t) Q_DECL_NOEXCEPT" << endl
+ << "{" << endl
+ << " if (t)" << endl
+ << " return new Object(*static_cast<const Object*>(t));" << endl
+ << endl
+ << " const auto type = objectTypes.at(" << i << ");" << endl
+ << " return new Object(GST_OBJECT(g_object_newv(type, 0, Q_NULLPTR)));" << endl
+ << "}" << endl
+ << endl
+ << "static void *constructObject" << i << "(void *where, const void *t) Q_DECL_NOEXCEPT" << endl
+ << "{" << endl
+ << " if (t)" << endl
+ << " return new(where) Object(*static_cast<const Object*>(t));" << endl
+ << endl
+ << " const auto type = objectTypes.at(" << i << ");" << endl
+ << " return new(where) Object(GST_OBJECT(g_object_newv(type, 0, Q_NULLPTR)));" << endl
+ << "}" << endl
+ << endl;
+ }
+ */
+
+ out << "static MetaTypePads objectTypePads[] = {" << endl;
+
+ for (int i = 0; i < typeCount; ++i)
+ out << " { &createObject" << i << ", &constructObject" << i << " }," << endl;
+
+ out << " { Q_NULLPTR, Q_NULLPTR }" << endl
+ << "};" << endl
+ << endl;
+
+ out << "const MetaTypePads &MetaTypePads::forObjectType(GType type) Q_DECL_NOEXCEPT" << endl
+ << "{" << endl
+ << " const auto &pads = objectTypePads[objectTypes.size()];" << endl
+ << endl
+ << " if (pads.create && pads.construct) {" << endl
+ << " objectTypes.append(type);" << endl
+ << " } else {" << endl
+ << " qWarning(\"No other object type pad available.\");" << endl
+ << " }" << endl
+ << endl
+ << " return pads;" << endl
+ << "}" << endl
+ << endl;
+
+ out << "static void *createElement(int which, const void *t) Q_DECL_NOEXCEPT" << endl
+ << "{" << endl
+ << " if (t)" << endl
+ << " return new Object(*static_cast<const Object*>(t));" << endl
+ << endl
+ << " auto *const factory = elementFactories.at(which);" << endl
+ << " auto *const element = gst_element_factory_create(factory, Q_NULLPTR);" << endl
+ << " return new Object(GST_OBJECT(element));" << endl
+ << "}" << endl
+ << endl
+ << "static void *constructElement(int which, void *where, const void *t) Q_DECL_NOEXCEPT" << endl
+ << "{" << endl
+ << " if (t)" << endl
+ << " return new(where) Object(*static_cast<const Object*>(t));" << endl
+ << endl
+ << " auto *const factory = elementFactories.at(which);" << endl
+ << " auto *const element = gst_element_factory_create(factory, Q_NULLPTR);" << endl
+ << " return new(where) Object(GST_OBJECT(element));" << endl
+ << "}" << endl
+ << endl;
+
+ for (int i = 0; i < factoryCount; ++i) {
+ out << "static void *createElement" << i << "(const void *t) Q_DECL_NOEXCEPT" << endl
+ << "{" << endl
+ << " return createElement(" << i << ", t);" << endl
+ << "}" << endl
+ << endl
+ << "static void *constructElement" << i << "(void *where, const void *t) Q_DECL_NOEXCEPT" << endl
+ << "{" << endl
+ << " return constructElement(" << i << ", where, t);" << endl
+ << "}" << endl
+ << endl;
+ }
+
+ /*
+ for (int i = 0; i < factoryCount; ++i) {
+ out << "static void *createElement" << i << "(const void *t) Q_DECL_NOEXCEPT" << endl
+ << "{" << endl
+ << " if (t)" << endl
+ << " return new Object(*static_cast<const Object*>(t));" << endl
+ << endl
+ << " auto *const factory = elementFactories.at(" << i << ");" << endl
+ << " auto *const element = gst_element_factory_create(factory, Q_NULLPTR);" << endl
+ << " return new Object(GST_OBJECT(element));" << endl
+ << "}" << endl
+ << endl
+ << "static void *constructElement" << i << "(void *where, const void *t) Q_DECL_NOEXCEPT" << endl
+ << "{" << endl
+ << " if (t)" << endl
+ << " return new(where) Object(*static_cast<const Object*>(t));" << endl
+ << endl
+ << " auto *const factory = elementFactories.at(" << i << ");" << endl
+ << " auto *const element = gst_element_factory_create(factory, Q_NULLPTR);" << endl
+ << " return new(where) Object(GST_OBJECT(element));" << endl
+ << "}" << endl
+ << endl;
+ }
+ */
+
+ out << "static MetaTypePads elementFactoryPads[] = {" << endl;
+
+ for (int i = 0; i < factoryCount; ++i)
+ out << " { &createElement" << i << ", &constructElement" << i << " }," << endl;
+
+ out << " { Q_NULLPTR, Q_NULLPTR }" << endl
+ << "};" << endl
+ << endl;
+
+ out << "const MetaTypePads &MetaTypePads::forElementFactory(GstElementFactory *factory) Q_DECL_NOEXCEPT" << endl
+ << "{" << endl
+ << " const auto &pads = elementFactoryPads[elementFactories.size()];" << endl
+ << endl
+ << " if (pads.create && pads.construct) {" << endl
+ << " elementFactories.append(GST_ELEMENT_FACTORY(g_object_ref(factory)));" << endl
+ << " } else {" << endl
+ << " qWarning(\"No other element factory pad available.\");" << endl
+ << " }" << endl
+ << endl
+ << " return pads;" << endl
+ << "}" << endl
+ << endl;
+
+ out << "} // namespace Private" << endl
+ << "} // namespace QQuickStreamer" << endl;
+
+ return EXIT_SUCCESS;
+}
diff --git a/src/makemetapads.pro b/src/makemetapads.pro
new file mode 100644
index 0000000..d359b6b
--- /dev/null
+++ b/src/makemetapads.pro
@@ -0,0 +1,6 @@
+TEMPLATE = app
+
+CONFIG += console c++11
+QT -= GUID
+
+SOURCES = makemetapads.cpp
diff --git a/src/metapads.h b/src/metapads.h
new file mode 100644
index 0000000..32fbec2
--- /dev/null
+++ b/src/metapads.h
@@ -0,0 +1,16 @@
+#include "object.h"
+
+namespace QQuickStreamer {
+namespace Private {
+
+struct MetaTypePads
+{
+ QMetaType::Creator create;
+ QMetaType::Constructor construct;
+
+ static const MetaTypePads &forElementFactory(GstElementFactory *factory) Q_DECL_NOEXCEPT;
+ static const MetaTypePads &forObjectType(GType type) Q_DECL_NOEXCEPT;
+};
+
+} // namespace QQuickStreamer
+} // namespace Private
diff --git a/src/object.cpp b/src/object.cpp
index b722bee..36a3f99 100644
--- a/src/object.cpp
+++ b/src/object.cpp
@@ -1,10 +1,10 @@
#include "object.h"
+#include "metapads.h"
-#include <5.0.1/QtCore/private/qmetaobjectbuilder_p.h>
+#include <gst/gst.h>
-#include <QVector>
-
-#include <gst/gstobject.h>
+#include <QtCore/private/qmetaobjectbuilder_p.h>
+#include <QtCore/QVector>
#include <functional>
@@ -21,91 +21,13 @@ struct PropertyInfo
WriteDelegate write;
};
-struct TypeInfo
-{
- TypeInfo()
- : parent(Q_NULLPTR)
- , metaObject(Q_NULLPTR)
- {
- }
-
- int readProperty(GstObject *object, int id, QVariant *value) const
- {
- if (parent)
- id = parent->readProperty(object, id, value);
- if (id < 0)
- return id;
-
- if (id < properties.size())
- properties.at(id).read(object, value);
-
- return id - properties.size();
- }
-
- int writeProperty(GstObject *object, int id, const QVariant &value) const
- {
- if (parent)
- id = parent->writeProperty(object, id, value);
- if (id < 0)
- return id;
-
- if (id < properties.size())
- properties.at(id).write(object, value);
-
- return id - properties.size();
- }
-
- void emitPropertyChanged(Object *object, const GParamSpec *pspec) const
- {
- for (int i = 0; i < properties.size(); ++i) {
- // can compare by pointer because GParamSpec::name is interned
- if (pspec->name == properties.at(i).name) {
- QMetaObject::activate(object, metaObject, i, Q_NULLPTR);
- return;
- }
- }
-
- if (parent)
- parent->emitPropertyChanged(object, pspec);
- }
-
- const TypeInfo *parent;
- const QMetaObject *metaObject;
- QVector<PropertyInfo> properties;
-};
-
-static QHash<GType, TypeInfo *> cachedTypeInfo;
-
-static const TypeInfo *makeTypeInfo(GType gtype);
-
-static GQuark dataKeyQuark()
-{
- static const GQuark quark = g_quark_from_static_string("qt-quick-streamer-object-data-key-quark");
- return quark;
-}
-
-void *findWrapper(void *object)
-{
- return g_object_get_qdata(G_OBJECT(object), dataKeyQuark());
-}
-
-static const TypeInfo *findTypeInfo(GType gtype)
-{
- Q_ASSERT(g_type_is_a(gtype, G_TYPE_OBJECT));
- const auto *typeInfo = Private::cachedTypeInfo.value(gtype);
-
- if (typeInfo == Q_NULLPTR)
- typeInfo = makeTypeInfo(gtype);
-
- return typeInfo;
-}
-
static bool isDash(char ch)
{
return ch == '-' || ch == '_';
}
-static QByteArray camelCaseName(const QByteArray &input)
+static QByteArray toCamelCase(const QByteArray &input,
+ char (*convertFirst)(char, const std::locale &))
{
int nDashes = 0;
@@ -120,17 +42,23 @@ static QByteArray camelCaseName(const QByteArray &input)
bool wordBoundary = false;
- for (char ch: input) {
- if (isDash(ch)) {
+ auto it = std::begin(input);
+ const auto end = std::end(input);
+ const auto &loc = std::locale::classic();
+
+ output += convertFirst(*it, loc);
+
+ while (++it != end) {
+ if (isDash(*it)) {
wordBoundary = true;
continue;
}
if (wordBoundary) {
- output += std::toupper(ch, std::locale::classic());
+ output += std::toupper(*it, loc);
wordBoundary = false;
} else {
- output += std::tolower(ch, std::locale::classic());
+ output += std::tolower(*it, loc);
}
}
@@ -346,105 +274,234 @@ PropertyInfo::WriteDelegate bindWriteDelegate(Args... args)
return std::bind(args...);
}
-static const TypeInfo *makeTypeInfo(GType gtype)
+struct TypeInfo
{
- QScopedPointer<TypeInfo> typeInfo(new TypeInfo);
+ TypeInfo()
+ : parent(Q_NULLPTR)
+ , metaObject(Q_NULLPTR)
+ {
+ }
- QMetaObjectBuilder objectBuilder;
- objectBuilder.setClassName(g_type_name(gtype));
+ static const TypeInfo *create(GType type, const MetaTypePads &metaTypePads)
+ {
+ QScopedPointer<TypeInfo> typeInfo(new TypeInfo);
- if (gtype != G_TYPE_OBJECT)
- typeInfo->parent = findTypeInfo(g_type_parent(gtype));
+ QMetaObjectBuilder objectBuilder;
+ objectBuilder.setClassName(g_type_name(type));
- objectBuilder.setSuperClass(typeInfo->parent ? typeInfo->parent->metaObject
- : &QObject::staticMetaObject);
+ if (type != G_TYPE_OBJECT)
+ typeInfo->parent = find(g_type_parent(type));
- const auto gobject_class = static_cast<GObjectClass *>(g_type_class_ref(gtype));
+ objectBuilder.setSuperClass(typeInfo->parent ? typeInfo->parent->metaObject
+ : &QObject::staticMetaObject);
- uint nPSpecs = 0;
- auto *const pSpecs = g_object_class_list_properties(gobject_class, &nPSpecs);
+ const auto gobject_class = static_cast<GObjectClass *>(g_type_class_ref(type));
- for (uint i = 0; i < nPSpecs; ++i) {
- const auto *const pSpec = pSpecs[i];
+ uint nPSpecs = 0;
+ auto *const pSpecs = g_object_class_list_properties(gobject_class, &nPSpecs);
- if (pSpec->owner_type != gtype)
- continue;
+ for (uint i = 0; i < nPSpecs; ++i) {
+ const auto *const pSpec = pSpecs[i];
- const auto &name = camelCaseName(pSpec->name);
- const auto &type = metaTypeName(pSpec->value_type);
+ if (pSpec->owner_type != type)
+ continue;
- if (pSpec->flags & G_PARAM_DEPRECATED) {
- qWarning("Ignoring deprecated property %s::%s", g_type_name(gtype), pSpec->name);
- continue;
+ const auto &propertyName = toCamelCase(pSpec->name, std::tolower);
+ const auto &propertyType = metaTypeName(pSpec->value_type);
+
+ if (pSpec->flags & G_PARAM_DEPRECATED) {
+ qWarning("Ignoring deprecated property %s::%s", g_type_name(type), pSpec->name);
+ continue;
+ }
+
+ if (propertyType.isEmpty()) {
+ qWarning("Ignoring property %s::%s of unsupported type %s",
+ g_type_name(type), pSpec->name, g_type_name(pSpec->value_type));
+ continue;
+ }
+
+ auto notifier = objectBuilder.addSignal(propertyName + QByteArrayLiteral("Changed()"));
+ auto property = objectBuilder.addProperty(propertyName, propertyType, notifier.index());
+
+ qDebug("%s %d %d", propertyName.constData(), notifier.index(), property.index());
+
+ property.setReadable(pSpec->flags & G_PARAM_READABLE);
+ property.setWritable(pSpec->flags & G_PARAM_WRITABLE);
+
+ using namespace std::placeholders;
+
+ const auto readDelegate = property.isReadable()
+ ? bindReadDelegate(&readGObjectProperty, _1, pSpec->name, pSpec->value_type, _2)
+ : bindReadDelegate(&readNothing, _1, pSpec->name, _2);
+ const auto writeDelegate = property.isWritable()
+ ? bindWriteDelegate(&writeGObjectProperty, _1, pSpec->name, pSpec->value_type, _2)
+ : bindWriteDelegate(&writeNothing, _1, pSpec->name, _2);
+
+ typeInfo->properties.append({pSpec->name, readDelegate, writeDelegate});
}
- if (type.isEmpty()) {
- qWarning("Ignoring property %s::%s of unsupported type %s",
- g_type_name(gtype), pSpec->name, g_type_name(pSpec->value_type));
- continue;
+ g_free(pSpecs);
+
+ uint nSignalIds = 0;
+ auto *const signalIds = g_signal_list_ids(type, &nSignalIds);
+
+ for (uint i = 0; i < nSignalIds; ++i) {
+ GSignalQuery query;
+ g_signal_query(signalIds[i], &query);
+ Q_ASSERT(signalIds[i] == query.signal_id);
+ qDebug("found signal: %s::%s", g_type_name(type), query.signal_name);
}
- auto notifier = objectBuilder.addSignal(name + QByteArrayLiteral("Changed()"));
- auto property = objectBuilder.addProperty(name, type, notifier.index());
+ g_type_class_unref(gobject_class);
- qDebug("%s %d %d", name.constData(), notifier.index(), property.index());
+ typedef QtMetaTypePrivate::QMetaTypeFunctionHelper<Object> MetaTypeHelper;
+ static const QMetaType::TypeFlags typeFlags(QtPrivate::QMetaTypeTypeFlags<Object>::Flags);
- property.setReadable(pSpec->flags & G_PARAM_READABLE);
- property.setWritable(pSpec->flags & G_PARAM_WRITABLE);
+ typeInfo->metaObject = objectBuilder.toMetaObject();
+ typeInfo->metaTypeId = QMetaType::registerNormalizedType(typeInfo->metaObject->className(),
+ MetaTypeHelper::Delete,
+ metaTypePads.create,
+ MetaTypeHelper::Destruct,
+ metaTypePads.construct,
+ sizeof(Object),
+ typeFlags,
+ typeInfo->metaObject);
- using namespace std::placeholders;
- const auto readDelegate = property.isReadable()
- ? bindReadDelegate(&readGObjectProperty, _1, pSpec->name, pSpec->value_type, _2)
- : bindReadDelegate(&readNothing, _1, pSpec->name, _2);
- const auto writeDelegate = property.isWritable()
- ? bindWriteDelegate(&writeGObjectProperty, _1, pSpec->name, pSpec->value_type, _2)
- : bindWriteDelegate(&writeNothing, _1, pSpec->name, _2);
+ cache.insert(type, typeInfo.data());
+ return typeInfo.take();
+ }
+
+ static const TypeInfo *find(GType type)
+ {
+ Q_ASSERT(g_type_is_a(type, G_TYPE_OBJECT));
+ Q_ASSERT(not g_type_is_a(type, GST_TYPE_ELEMENT_FACTORY));
+
+ const auto *typeInfo = cache.value(type);
+
+ if (typeInfo == Q_NULLPTR)
+ typeInfo = create(type, MetaTypePads::forObjectType(type));
- typeInfo->properties.append({pSpec->name, readDelegate, writeDelegate});
+ return typeInfo;
}
-
- g_free(pSpecs);
- uint nSignalIds = 0;
- auto *const signalIds = g_signal_list_ids(gtype, &nSignalIds);
+ static const TypeInfo *find(GstElementFactory *factory)
+ {
+ Q_ASSERT(GST_IS_ELEMENT_FACTORY(factory));
+
+ const auto type = gst_element_factory_get_element_type(factory);
+ const auto *typeInfo = cache.value(type);
+
+ if (typeInfo == Q_NULLPTR)
+ typeInfo = create(type, MetaTypePads::forElementFactory(factory));
- for (uint i = 0; i < nSignalIds; ++i) {
- GSignalQuery query;
- g_signal_query(signalIds[i], &query);
- Q_ASSERT(signalIds[i] == query.signal_id);
- qDebug("found signal: %s::%s", g_type_name(gtype), query.signal_name);
+ return typeInfo;
}
- g_type_class_unref(gobject_class);
+ int readProperty(GstObject *object, int id, QVariant *value) const
+ {
+ if (parent)
+ id = parent->readProperty(object, id, value);
+ if (id < 0)
+ return id;
- typeInfo->metaObject = objectBuilder.toMetaObject();
- cachedTypeInfo.insert(gtype, typeInfo.data());
- return typeInfo.take();
-}
+ if (id < properties.size())
+ properties.at(id).read(object, value);
+
+ return id - properties.size();
+ }
+
+ int writeProperty(GstObject *object, int id, const QVariant &value) const
+ {
+ if (parent)
+ id = parent->writeProperty(object, id, value);
+ if (id < 0)
+ return id;
+
+ if (id < properties.size())
+ properties.at(id).write(object, value);
+
+ return id - properties.size();
+ }
+
+ void emitPropertyChanged(Object *object, const GParamSpec *pspec) const
+ {
+ for (int i = 0; i < properties.size(); ++i) {
+ // can compare by pointer because GParamSpec::name is interned
+ if (pspec->name == properties.at(i).name) {
+ QMetaObject::activate(object, metaObject, i, Q_NULLPTR);
+ return;
+ }
+ }
+
+ if (parent)
+ parent->emitPropertyChanged(object, pspec);
+ }
+
+ const TypeInfo *parent;
+ const QMetaObject *metaObject;
+ int metaTypeId;
+
+ QVector<PropertyInfo> properties;
+ static QHash<GType, TypeInfo *> cache;
+};
+
+QHash<GType, TypeInfo *> TypeInfo::cache;
} // namespace Private
-Object::Object(GstObject *target)
- : QObject()
+using Private::TypeInfo;
+using Private::toCamelCase;
+
+Object::Object(GstObject *target, QObject *parent)
+ : QObject(parent)
, m_target(target)
{
Q_ASSERT(m_target != Q_NULLPTR);
g_object_ref_sink(m_target);
- g_object_set_qdata(G_OBJECT(target), Private::dataKeyQuark(), this);
g_signal_connect_swapped(target, "notify", reinterpret_cast<GCallback>(&Object::emitPropertyChanged), this);
}
+Object::Object(const Object &other)
+ : QObject(other.parent())
+ , m_target(static_cast<GstObject *>(g_object_ref(other.m_target)))
+{
+}
+
Object::~Object()
{
- g_object_set_qdata(G_OBJECT(m_target), Private::dataKeyQuark(), Q_NULLPTR);
g_object_unref(m_target);
}
+/* FIXME
+static QByteArray pointerName(GType type)
+{
+ QByteArray typeName = g_type_name(type);
+
+ if (std::islower(typeName.at(0)))
+ typeName = toCamelCase(typeName, std::toupper);
+
+ if (typeName != g_type_name(type))
+ qDebug("%s - %s", g_type_name(type), typeName.constData());
+
+ typeName += QByteArrayLiteral(" *");
+}
+*/
+
+int Object::registerElementFactory(GstElementFactory *factory)
+{
+ return TypeInfo::find(factory)->metaTypeId;
+}
+
+int Object::registerObjectClass(GType type)
+{
+ return TypeInfo::find(type)->metaTypeId;
+}
+
const QMetaObject *Object::metaObject() const
{
- return Private::findTypeInfo(G_OBJECT_TYPE(m_target))->metaObject;
+ return TypeInfo::find(G_OBJECT_TYPE(m_target))->metaObject;
}
void *Object::qt_metacast(const char *className)
@@ -496,19 +553,19 @@ int Object::qt_metacall(QMetaObject::Call call, int id, void **args)
int Object::readProperty(int id, QVariant *value)
{
- const auto *const typeInfo = Private::findTypeInfo(G_OBJECT_TYPE(m_target));
+ const auto *const typeInfo = TypeInfo::find(G_OBJECT_TYPE(m_target));
return typeInfo->readProperty(m_target, id, value);
}
int Object::writeProperty(int id, const QVariant &value)
{
- const auto *const typeInfo = Private::findTypeInfo(G_OBJECT_TYPE(m_target));
+ const auto *const typeInfo = TypeInfo::find(G_OBJECT_TYPE(m_target));
return typeInfo->writeProperty(m_target, id, value);
}
void Object::emitPropertyChanged(Object *self, GParamSpec *pspec)
{
- const auto *const typeInfo = Private::findTypeInfo(G_OBJECT_TYPE(self->m_target));
+ const auto *const typeInfo = TypeInfo::find(G_OBJECT_TYPE(self->m_target));
typeInfo->emitPropertyChanged(self, pspec);
}
diff --git a/src/object.h b/src/object.h
index 60b8e0e..059d55e 100644
--- a/src/object.h
+++ b/src/object.h
@@ -3,8 +3,10 @@
#include <QObject>
-typedef struct _GParamSpec GParamSpec;
-typedef struct _GstObject GstObject;
+typedef unsigned long GType;
+typedef struct _GParamSpec GParamSpec;
+typedef struct _GstElementFactory GstElementFactory;
+typedef struct _GstObject GstObject;
namespace QQuickStreamer {
@@ -13,15 +15,14 @@ class Object : public QObject
public:
Q_OBJECT_CHECK
- template<class Wrapper, class Target>
- friend Wrapper *wrap(Target *);
+ explicit Object(GstObject *target, QObject *parent = Q_NULLPTR);
+ Object(const Object &other);
-protected:
- explicit Object(GstObject *target);
-
-public:
~Object();
+ static int registerElementFactory(GstElementFactory *factory);
+ static int registerObjectClass(GType type);
+
const QMetaObject *metaObject() const Q_DECL_OVERRIDE;
void *qt_metacast(const char *classname) Q_DECL_OVERRIDE;
int qt_metacall(QMetaObject::Call call, int id, void **args) Q_DECL_OVERRIDE;
@@ -35,26 +36,6 @@ private:
GstObject *const m_target;
};
-namespace Private {
-
-void *findWrapper(void *object);
-
-}
-
-template<class Wrapper, class Target>
-inline Wrapper *wrap(Target *target)
-{
- if (target == Q_NULLPTR)
- return Q_NULLPTR;
-
- Wrapper *wrapper = static_cast<Wrapper *>(Private::findWrapper(target));
-
- if (wrapper == Q_NULLPTR)
- wrapper = new Wrapper(target);
-
- return wrapper;
-}
-
} // namespace QQuickStreamer
#endif // QQUICKSTREAMEROBJECT_H
diff --git a/src/plugin.cpp b/src/plugin.cpp
index 3693010..34aae57 100644
--- a/src/plugin.cpp
+++ b/src/plugin.cpp
@@ -1,8 +1,10 @@
#include "plugin.h"
-//#include "qquickstreamerpipeline.h"
+#include "object.h"
#include <QtQml>
+#include <gst/gst.h>
+
namespace QQuickStreamer {
static const auto NAMESPACE_URI = QByteArrayLiteral("QtQuickStreamer");
@@ -16,6 +18,50 @@ void Plugin::registerTypes(const char *uri)
{
Q_ASSERT(uri == NAMESPACE_URI);
+ if (not gst_is_initialized()) {
+ GError *error = Q_NULLPTR;
+
+ if (not gst_init_check(Q_NULLPTR, Q_NULLPTR, &error)) {
+ qWarning("Cannot initialize %s module: %s", NAMESPACE_URI.constData(), error->message);
+ g_error_free(error);
+ return;
+ }
+ }
+
+ qDebug() << "uri:" << uri;
+
+ auto *const elements = gst_element_factory_list_get_elements(GST_ELEMENT_FACTORY_TYPE_ANY, GST_RANK_NONE);
+
+ for (auto *l = elements; l; l = l->next) {
+ auto *const feature = GST_PLUGIN_FEATURE(l->data);
+ auto *const factory = GST_ELEMENT_FACTORY(gst_plugin_feature_load(feature));
+ const int metaTypeId = Object::registerElementFactory(factory);
+ g_object_unref(factory);
+
+ qDebug() << metaTypeId << QMetaType::typeName(metaTypeId);
+
+/*
+ qDebug() << g_type_name(gst_element_factory_get_element_type((GstElementFactory *)l->data)) << gst_element_get_name(l->data);
+
+ char *const elementName = gst_element_get_name(l->data);
+
+ QByteArray pointerName;
+ pointerName.append("Gst");
+ pointerName.append(elementName);
+ pointerName.append(" *");
+ g_free(elementName);
+
+ QMetaObject *m;
+
+ */
+ }
+
+ gst_plugin_feature_list_free(elements);
+
+ /*
+ qmlRegisterType<Object>
+ QMetaType::registerNormalizedType()
+ */
/*
// @uri com.kdab.QtQuickStreamer
qmlRegisterUncreatableType<QQuickStreamerElement>(uri, 1, 0, "Element", QStringLiteral("This is an abstract type"));
diff --git a/src/qtquickstreamerplugin.pro b/src/qtquickstreamerplugin.pro
index bd404bd..7c8c9ec 100644
--- a/src/qtquickstreamerplugin.pro
+++ b/src/qtquickstreamerplugin.pro
@@ -2,12 +2,14 @@ TEMPLATE = lib
CONFIG += plugin c++11
#DESTDIR = org/qt-project/QtQuickStreamer
-QT += qml
+QT += core-private qml
+message($$QT.core.private_includes)
CONFIG += link_pkgconfig
PKGCONFIG += gstreamer-1.0
SOURCES = \
+ metapads.cpp \
plugin.cpp \
object.cpp
@@ -15,13 +17,21 @@ SOURCES = \
# qquickstreamerbin.cpp \
# qquickstreamerpipeline.cpp
-OTHER_FILES = \
- qmldir
-
-HEADERS += \
+HEADERS = \
+ metapads.h \
plugin.h \
object.h
+OTHER_FILES = \
+ qmldir \
+ qquickstreamerplugin.json
+
# qquickstreamerelement.h \
# qquickstreamerbin.h \
# qquickstreamerpipeline.h
+
+metapads.target = metapads.cpp
+metapads.depends = $$OUT_PWD/makemetapads
+metapads.commands = $$OUT_PWD/makemetapads 256 4096 > $$metapads.target || rm -f $$metapads.target
+
+QMAKE_EXTRA_TARGETS += metapads
diff --git a/src/src.pro b/src/src.pro
index 37dfbd1..f8344ac 100644
--- a/src/src.pro
+++ b/src/src.pro
@@ -1,4 +1,10 @@
TEMPLATE = subdirs
SUBDIRS = \
- qtquickstreamerplugin.pro
+ makemetapads \
+ qtquickstreamerplugin
+
+makemetapads.file = makemetapads.pro
+
+qtquickstreamerplugin.file = qtquickstreamerplugin.pro
+qtquickstreamerplugin.depends = makemetapads
diff --git a/tests/tests.pro b/tests/tests.pro
index d9d63e7..075dbe5 100644
--- a/tests/tests.pro
+++ b/tests/tests.pro
@@ -1,4 +1,6 @@
TEMPLATE = subdirs
SUBDIRS += \
- tst_wrapping
+ tst_qml
+
+# tst_wrapping \
diff --git a/tests/tst_qml/tst_qml.pro b/tests/tst_qml/tst_qml.pro
new file mode 100644
index 0000000..9b9c406
--- /dev/null
+++ b/tests/tst_qml/tst_qml.pro
@@ -0,0 +1,13 @@
+QT += qml testlib
+
+QT -= gui
+
+TARGET = tst_qmltest
+CONFIG += console
+CONFIG -= app_bundle
+
+TEMPLATE = app
+
+
+SOURCES += tst_qmltest.cpp
+DEFINES += SRCDIR=\\\"$$PWD/\\\"
diff --git a/tests/tst_qml/tst_qmltest.cpp b/tests/tst_qml/tst_qmltest.cpp
new file mode 100644
index 0000000..38e5411
--- /dev/null
+++ b/tests/tst_qml/tst_qmltest.cpp
@@ -0,0 +1,32 @@
+#include <QString>
+#include <QtTest>
+#include <QCoreApplication>
+#include <QtQml>
+
+class QmlTest : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void testCase1()
+ {
+ QQmlEngine engine;
+ engine.addImportPath(qApp->applicationDirPath() + "/../../src");
+ qDebug() << (qApp->applicationDirPath() + "/../../src");
+
+ QStringListModel modelData;
+ QQmlContext *context = new QQmlContext(engine.rootContext());
+ context->setContextProperty("myModel", &modelData);
+
+ QQmlComponent component(&engine);
+ component.setData("import QtQuickStreamer 1.0\n"
+ "Pipeline { name: 'qmltest' }",
+ QUrl());
+ qDebug() << component.errors();
+ QObject *view = component.create(context);
+ }
+};
+
+QTEST_MAIN(QmlTest)
+
+#include "tst_qmltest.moc"
diff --git a/tests/tst_wrapping/tst_wrappingtest.cpp b/tests/tst_wrapping/tst_wrappingtest.cpp
index 4e0a2d2..2aca849 100644
--- a/tests/tst_wrapping/tst_wrappingtest.cpp
+++ b/tests/tst_wrapping/tst_wrappingtest.cpp
@@ -9,12 +9,6 @@ class WrappingTest : public QObject
{
Q_OBJECT
-public:
- WrappingTest()
- {
- gst_init(Q_NULLPTR, Q_NULLPTR);
- }
-
private slots:
void testCase1();