Implement GstDynamicTypeFactory as a new registry feature.
GstDynamicTypeFactory provides a way of registering a GType
into the registry, such that it will be registered as a dynamic
type when the registry is loaded, and then automatically loaded
if the type is needed during caps parsing.
This allows using non-core types in pad templates, by loading a
registry feature to create the GType on the fly.
https://bugzilla.gnome.org/show_bug.cgi?id=750079
gstdevicemonitor.c \
gstdeviceprovider.c \
gstdeviceproviderfactory.c \
+ gstdynamictypefactory.c \
gstelement.c \
gstelementfactory.c \
gsterror.c \
#include <gst/gstdevice.h>
#include <gst/gstdevicemonitor.h>
#include <gst/gstdeviceprovider.h>
+#include <gst/gstdynamictypefactory.h>
#include <gst/gstelement.h>
#include <gst/gstelementmetadata.h>
#include <gst/gsterror.h>
gpointer _gst_reserved[GST_PADDING];
};
+struct _GstDynamicTypeFactory {
+ GstPluginFeature feature;
+
+ GType type; /* GType of the type, when loaded. 0 if not */
+};
+
+struct _GstDynamicTypeFactoryClass {
+ GstPluginFeatureClass parent;
+};
+
/* privat flag used by GstBus / GstMessage */
#define GST_MESSAGE_FLAG_ASYNC_DELIVERY (GST_MINI_OBJECT_FLAG_LAST << 0)
--- /dev/null
+/* GStreamer
+ * Copyright (C) 2015 Jan Schmidt <jan@centricular.com>
+ *
+ * gstdynamictypefactory.c: Implementation of GstDynamicTypeFactory
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * SECTION:gstdynamictypefactory
+ * @short_description: Represents a registered dynamically loadable GType
+ * @see_also: #GstPlugin, #GstPluginFeature.
+ *
+ * #GstDynamicTypeFactory is used to represent a type that can be
+ * automatically loaded the first time it is used. For example,
+ * a non-standard type for use in caps fields.
+ *
+ * In general, applications and plugins don't need to use the factory
+ * beyond registering the type in a plugin init function. Once that is
+ * done, the type is stored in the registry, and ready as soon as the
+ * registry is loaded.
+ *
+ * <example>
+ * <title>Registering a type for dynamic loading</title>
+ * <programlisting language="c">
+ *
+ * static gboolean
+ * plugin_init (GstPlugin * plugin)
+ * {
+ * return gst_dynamic_type_register (plugin, GST_TYPE_CUSTOM_CAPS_FIELD);
+ * }
+ * </programlisting>
+ * </example>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "gst_private.h"
+
+#include <glib-object.h>
+
+#include "gst.h"
+
+#include "glib-compat-private.h"
+
+
+GST_DEBUG_CATEGORY_STATIC (dynamic_type_factory_debug);
+#define GST_CAT_DEFAULT dynamic_type_factory_debug
+
+#define _do_init \
+{ \
+ GST_DEBUG_CATEGORY_INIT (dynamic_type_factory_debug, \
+ "GST_DYNAMIC_TYPE_FACTORY", GST_DEBUG_BOLD, \
+ "dynamic type factories allow automatically loading a type from a plugin"); \
+}
+
+G_DEFINE_TYPE_WITH_CODE (GstDynamicTypeFactory, gst_dynamic_type_factory,
+ GST_TYPE_PLUGIN_FEATURE, _do_init);
+
+static void
+gst_dynamic_type_factory_class_init (GstDynamicTypeFactoryClass * klass)
+{
+}
+
+static void
+gst_dynamic_type_factory_init (GstDynamicTypeFactory * factory)
+{
+}
+
+static GstDynamicTypeFactory *
+gst_dynamic_type_factory_find (const gchar * name)
+{
+ GstPluginFeature *feature;
+
+ g_return_val_if_fail (name != NULL, NULL);
+
+ feature = gst_registry_find_feature (gst_registry_get (), name,
+ GST_TYPE_DYNAMIC_TYPE_FACTORY);
+ if (feature)
+ return GST_DYNAMIC_TYPE_FACTORY (feature);
+
+ return NULL;
+}
+
+GType
+gst_dynamic_type_factory_load (const gchar * factoryname)
+{
+ GstDynamicTypeFactory *factory = gst_dynamic_type_factory_find (factoryname);
+
+ /* Called with a non-dynamic or unregistered type? */
+ if (factory == NULL)
+ return FALSE;
+
+ factory =
+ GST_DYNAMIC_TYPE_FACTORY (gst_plugin_feature_load (GST_PLUGIN_FEATURE
+ (factory)));
+ if (factory == NULL)
+ return 0;
+
+ GST_DEBUG_OBJECT (factory, "Loaded type %s", factoryname);
+
+ return factory->type;
+}
+
+static GstDynamicTypeFactory *
+gst_dynamic_type_factory_create (GstRegistry * registry,
+ GstPlugin * plugin, const gchar * name)
+{
+ GstDynamicTypeFactory *factory;
+
+ factory =
+ GST_DYNAMIC_TYPE_FACTORY_CAST (g_object_newv
+ (GST_TYPE_DYNAMIC_TYPE_FACTORY, 0, NULL));
+ gst_plugin_feature_set_name (GST_PLUGIN_FEATURE_CAST (factory), name);
+ GST_LOG_OBJECT (factory, "Created new dynamictypefactory for type %s", name);
+
+ if (plugin && plugin->desc.name) {
+ GST_PLUGIN_FEATURE_CAST (factory)->plugin_name = plugin->desc.name;
+ GST_PLUGIN_FEATURE_CAST (factory)->plugin = plugin;
+ g_object_add_weak_pointer ((GObject *) plugin,
+ (gpointer *) & GST_PLUGIN_FEATURE_CAST (factory)->plugin);
+ } else {
+ GST_PLUGIN_FEATURE_CAST (factory)->plugin_name = "NULL";
+ GST_PLUGIN_FEATURE_CAST (factory)->plugin = NULL;
+ }
+ GST_PLUGIN_FEATURE_CAST (factory)->loaded = TRUE;
+
+ return factory;
+}
+
+gboolean
+gst_dynamic_type_register (GstPlugin * plugin, GType dyn_type)
+{
+ GstDynamicTypeFactory *factory;
+ const gchar *name;
+ GstPluginFeature *existing_feature;
+ GstRegistry *registry;
+
+ name = g_type_name (dyn_type);
+ g_return_val_if_fail (name != NULL, FALSE);
+
+ registry = gst_registry_get ();
+
+ /* check if feature already exists, if it exists there is no need to
+ * update it for this method of dynamic type */
+ existing_feature = gst_registry_lookup_feature (registry, name);
+ if (existing_feature) {
+ GST_DEBUG_OBJECT (registry, "update existing feature %p (%s)",
+ existing_feature, name);
+ existing_feature->loaded = TRUE;
+ GST_DYNAMIC_TYPE_FACTORY (existing_feature)->type = dyn_type;
+ gst_object_unref (existing_feature);
+ return TRUE;
+ }
+
+ factory = gst_dynamic_type_factory_create (registry, plugin, name);
+ factory->type = dyn_type;
+
+ gst_registry_add_feature (registry, GST_PLUGIN_FEATURE_CAST (factory));
+
+ return TRUE;
+}
--- /dev/null
+/* GStreamer
+ * Copyright (C) 2015 Jan Schmidt <jan@centricular.com>
+ *
+ * gstdynamictypefactory.h: Header for GstDynamicTypeFactory
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __GST_DYNAMIC_TYPE_FACTORY_H__
+#define __GST_DYNAMIC_TYPE_FACTORY_H__
+
+/**
+ * GstDynamicTypeFactory:
+ *
+ * The opaque #GstDynamicTypeFactory data structure.
+ */
+typedef struct _GstDynamicTypeFactory GstDynamicTypeFactory;
+typedef struct _GstDynamicTypeFactoryClass GstDynamicTypeFactoryClass;
+
+#include <gst/gstconfig.h>
+#include <gst/gstplugin.h>
+#include <gst/gstpluginfeature.h>
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_DYNAMIC_TYPE_FACTORY (gst_dynamic_type_factory_get_type())
+#define GST_DYNAMIC_TYPE_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_DYNAMIC_TYPE_FACTORY,\
+ GstDynamicTypeFactory))
+#define GST_DYNAMIC_TYPE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_DYNAMIC_TYPE_FACTORY,\
+ GstDynamicTypeFactoryClass))
+#define GST_IS_DYNAMIC_TYPE_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_DYNAMIC_TYPE_FACTORY))
+#define GST_IS_DYNAMIC_TYPE_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_DYNAMIC_TYPE_FACTORY))
+#define GST_DYNAMIC_TYPE_FACTORY_CAST(obj) ((GstDynamicTypeFactory *)(obj))
+
+GType gst_dynamic_type_factory_get_type (void);
+
+GType gst_dynamic_type_factory_load (const gchar *factoryname);
+
+gboolean gst_dynamic_type_register (GstPlugin *plugin, GType type);
+
+G_END_DECLS
+
+#endif
* Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
* 2000,2004 Wim Taymans <wim@fluendo.com>
*
- * gstelement.h: Header for GstElement
+ * gstelementfactory.h: Header for GstElementFactory
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
#include <gst/gsttypefind.h>
#include <gst/gsttypefindfactory.h>
#include <gst/gstdeviceproviderfactory.h>
+#include <gst/gstdynamictypefactory.h>
#include <gst/gsturi.h>
#include <gst/gstinfo.h>
#include <gst/gstenumtypes.h>
GST_TYPE_ELEMENT_FACTORY;
GST_TYPE_TYPE_FIND_FACTORY;
GST_TYPE_DEVICE_PROVIDER_FACTORY;
+ GST_TYPE_DYNAMIC_TYPE_FACTORY;
#ifndef GST_DISABLE_GST_DEBUG
timer = g_timer_new ();
#include <gst/gsttypefind.h>
#include <gst/gsttypefindfactory.h>
#include <gst/gstdeviceproviderfactory.h>
+#include <gst/gstdynamictypefactory.h>
#include <gst/gsturi.h>
#include <gst/gstinfo.h>
#include <gst/gstenumtypes.h>
pf = g_slice_new0 (GstRegistryChunkPluginFeature);
pf_size = sizeof (GstRegistryChunkPluginFeature);
chk = gst_registry_chunks_make_data (pf, pf_size);
+ } else if (GST_IS_DYNAMIC_TYPE_FACTORY (feature)) {
+ GstRegistryChunkDynamicTypeFactory *tmp;
+
+ tmp = g_slice_new0 (GstRegistryChunkDynamicTypeFactory);
+ chk =
+ gst_registry_chunks_make_data (tmp,
+ sizeof (GstRegistryChunkDynamicTypeFactory));
+ pf = (GstRegistryChunkPluginFeature *) tmp;
} else {
GST_WARNING_OBJECT (feature, "unhandled feature type '%s'", type_name);
}
("Reading/casting for GstRegistryChunkPluginFeature at address %p",
*in);
unpack_element (*in, pf, GstRegistryChunkPluginFeature, end, fail);
+ } else if (GST_IS_DYNAMIC_TYPE_FACTORY (feature)) {
+ GstRegistryChunkDynamicTypeFactory *tmp;
+
+ unpack_element (*in, tmp, GstRegistryChunkDynamicTypeFactory, end, fail);
+
+ pf = (GstRegistryChunkPluginFeature *) tmp;
} else {
GST_WARNING ("unhandled factory type : %s", G_OBJECT_TYPE_NAME (feature));
goto fail;
} GstRegistryChunkDeviceProviderFactory;
/*
+ * GstRegistryChunkDynamicTypeFactory:
+ *
+ * A structure containing the dynamic type factory flags field
+ */
+typedef struct _GstRegistryChunkDynamicTypeFactory
+{
+ GstRegistryChunkPluginFeature plugin_feature;
+
+ guint type_flags;
+} GstRegistryChunkDynamicTypeFactory;
+
+/*
* GstRegistryChunkPadTemplate:
*
* A structure containing the static pad templates of a plugin feature
int i;
GstStructureAbbreviation *abbrs;
gint n_abbrs;
+ GType ret;
g_return_val_if_fail (type_name != NULL, G_TYPE_INVALID);
}
/* this is the fallback */
- return g_type_from_name (type_name);
+ ret = g_type_from_name (type_name);
+ /* If not found, try it as a dynamic type */
+ if (G_UNLIKELY (ret == 0))
+ ret = gst_dynamic_type_factory_load (type_name);
+ return ret;
}
static const char *
if (end != NULL) {
gchar *class_name = g_strndup (set_class, end - set_class);
GType flags_type = g_type_from_name (class_name);
+ if (flags_type == 0) {
+ GST_TRACE ("Looking for dynamic type %s", class_name);
+ gst_dynamic_type_factory_load (class_name);
+ }
- g_free (class_name);
-
- if (flags_type != 0)
+ if (flags_type != 0) {
flags_klass = g_type_class_ref (flags_type);
+ GST_TRACE ("Going to parse %s as %s", s, class_name);
+ }
+ g_free (class_name);
}
if (flags_klass) {
gst_device_provider_unhide_provider
gst_device_reconfigure_element
gst_double_range_get_type
+ gst_dynamic_type_factory_get_type
+ gst_dynamic_type_factory_load
+ gst_dynamic_type_register
gst_element_abort_state
gst_element_add_pad
gst_element_add_property_deep_notify_watch