diff options
author | Mathias Hasselmann <mathias.hasselmann@kdab.com> | 2013-10-29 20:04:19 +0100 |
---|---|---|
committer | Mathias Hasselmann <mathias.hasselmann@kdab.com> | 2013-10-29 20:04:19 +0100 |
commit | 2b291759186876e189de36d4404b40f7b696e013 (patch) | |
tree | acd876d0c58afa4020abc745af7beadc330ad888 | |
parent | 8dc7502ac0a86569945769d790ed79b4cd966079 (diff) | |
download | qtquickstreamer-2b291759186876e189de36d4404b40f7b696e013.tar.gz qtquickstreamer-2b291759186876e189de36d4404b40f7b696e013.tar.xz |
More work
-rw-r--r-- | src/makemetapads.cpp | 208 | ||||
-rw-r--r-- | src/makemetapads.pro | 6 | ||||
-rw-r--r-- | src/metapads.h | 16 | ||||
-rw-r--r-- | src/object.cpp | 351 | ||||
-rw-r--r-- | src/object.h | 37 | ||||
-rw-r--r-- | src/plugin.cpp | 48 | ||||
-rw-r--r-- | src/qtquickstreamerplugin.pro | 20 | ||||
-rw-r--r-- | src/src.pro | 8 | ||||
-rw-r--r-- | tests/tests.pro | 4 | ||||
-rw-r--r-- | tests/tst_qml/tst_qml.pro | 13 | ||||
-rw-r--r-- | tests/tst_qml/tst_qmltest.cpp | 32 | ||||
-rw-r--r-- | tests/tst_wrapping/tst_wrappingtest.cpp | 6 |
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(); |