plugin: add release datetime field to GstPluginDesc and set it if GST_PACKAGE_RELEASE...
authorTim-Philipp Müller <tim.muller@collabora.co.uk>
Sat, 19 Jun 2010 23:33:36 +0000 (00:33 +0100)
committerTim-Philipp Müller <tim.muller@collabora.co.uk>
Fri, 23 Jul 2010 16:00:56 +0000 (17:00 +0100)
This is a string describing a date and/or date/time in a simple subset of
the ISO-8601 format, namely either "YYYY-MM-DD" or "YYYY-MM-DDTHH:MMZ" (with
'T' the date/time separator and the 'Z' indicating UTC).

The main purpose of this field is to keep track of plugin and element versions
on an absolute timeline, so it's possible to determine which one is newer when
comparing two date time numbers. This will allow us to express 'replaces'-type
relationships betweeen plugins and element factories in future, even across
different modules and plugin merges or splits (source module version numbers
aren't particularly useful here, since they can only meaningfully be compared
within the same module). It also allows applications and libraries to reliably
check that a plugin is recent enough without making assumptions about modules
or module versions.

We use a string here to keep things simple and clear, esp. on the build system
side of things.

https://bugzilla.gnome.org/show_bug.cgi?id=623040

gst/gstplugin.c
gst/gstplugin.h
tests/check/gst/gstplugin.c

index 68e72ef..599af83 100644 (file)
@@ -231,7 +231,7 @@ gst_plugin_register_static (gint major_version, gint minor_version,
     const gchar * package, const gchar * origin)
 {
   GstPluginDesc desc = { major_version, minor_version, name, description,
-    init_func, version, license, source, package, origin,
+    init_func, version, license, source, package, origin, NULL,
   };
   GstPlugin *plugin;
   gboolean res = FALSE;
@@ -300,7 +300,7 @@ gst_plugin_register_static_full (gint major_version, gint minor_version,
 {
   GstPluginDesc desc = { major_version, minor_version, name, description,
     (GstPluginInitFunc) init_full_func, version, license, source, package,
-    origin,
+    origin, NULL,
   };
   GstPlugin *plugin;
   gboolean res = FALSE;
@@ -645,6 +645,44 @@ _gst_plugin_fault_handler_setup (void)
 }
 #endif /* HAVE_SIGACTION */
 
+/* g_time_val_from_iso8601() doesn't do quite what we want */
+static gboolean
+check_release_datetime (const gchar * date_time)
+{
+  guint64 val;
+
+  /* we require YYYY-MM-DD or YYYY-MM-DDTHH:MMZ format */
+  if (!g_ascii_isdigit (*date_time))
+    return FALSE;
+
+  val = g_ascii_strtoull (date_time, (gchar **) & date_time, 10);
+  if (val < 2000 || val > 2100 || *date_time != '-')
+    return FALSE;
+
+  val = g_ascii_strtoull (date_time + 1, (gchar **) & date_time, 10);
+  if (val == 0 || val > 12 || *date_time != '-')
+    return FALSE;
+
+  val = g_ascii_strtoull (date_time + 1, (gchar **) & date_time, 10);
+  if (val == 0 || val > 32)
+    return FALSE;
+
+  /* end of string or date/time separator + HH:MMZ */
+  if (*date_time == 'T' || *date_time == ' ') {
+    val = g_ascii_strtoull (date_time + 1, (gchar **) & date_time, 10);
+    if (val > 24 || *date_time != ':')
+      return FALSE;
+
+    val = g_ascii_strtoull (date_time + 1, (gchar **) & date_time, 10);
+    if (val > 59 || *date_time != 'Z')
+      return FALSE;
+
+    ++date_time;
+  }
+
+  return (*date_time == '\0');
+}
+
 static GStaticMutex gst_plugin_loading_mutex = G_STATIC_MUTEX_INIT;
 
 #define CHECK_PLUGIN_DESC_FIELD(desc,field,fn)                               \
@@ -769,6 +807,13 @@ gst_plugin_load_file (const gchar * filename, GError ** error)
     CHECK_PLUGIN_DESC_FIELD (plugin->orig_desc, source, filename);
     CHECK_PLUGIN_DESC_FIELD (plugin->orig_desc, package, filename);
     CHECK_PLUGIN_DESC_FIELD (plugin->orig_desc, origin, filename);
+
+    if (plugin->orig_desc->release_datetime != NULL &&
+        !check_release_datetime (plugin->orig_desc->release_datetime)) {
+      GST_ERROR ("GstPluginDesc for '%s' has invalid datetime '%s'",
+          filename, plugin->orig_desc->release_datetime);
+      plugin->orig_desc->release_datetime = NULL;
+    }
   }
 
   GST_LOG ("Plugin %p for file \"%s\" prepared, calling entry function...",
@@ -829,6 +874,7 @@ gst_plugin_desc_copy (GstPluginDesc * dest, const GstPluginDesc * src)
   dest->source = g_intern_string (src->source);
   dest->package = g_intern_string (src->package);
   dest->origin = g_intern_string (src->origin);
+  dest->release_datetime = g_intern_string (src->release_datetime);
 }
 
 /**
index aa893bf..c4f9c44 100644 (file)
@@ -150,7 +150,11 @@ typedef gboolean (*GstPluginInitFullFunc) (GstPlugin *plugin, gpointer user_data
  * @source: source module plugin belongs to
  * @package: shipped package plugin belongs to
  * @origin: URL to provider of plugin
- * @_gst_reserved: private, for later expansion
+ * @release_datetime: date time string in ISO 8601 format (or rather, a
+ *     subset thereof), or NULL. Allowed are the following formats:
+ *     "YYYY-MM-DD" and "YYY-MM-DDTHH:MMZ" (with 'T' a separator and 'Z'
+ *     indicating UTC/Zulu time). This field should be set via the
+ *     GST_PACKAGE_RELEASE_DATETIME preprocessor macro (Since: 0.10.31)
  *
  * A plugin should export a variable of this type called plugin_desc. The plugin
  * loader will use the data provided there to initialize the plugin.
@@ -169,8 +173,9 @@ struct _GstPluginDesc {
   const gchar *source;
   const gchar *package;
   const gchar *origin;
-
-  gpointer _gst_reserved[GST_PADDING];
+  const gchar *release_datetime;
+  /*< private >*/
+  gpointer _gst_reserved[GST_PADDING - 1];
 };
 
 
@@ -218,6 +223,12 @@ struct _GstPluginClass {
   gpointer _gst_reserved[GST_PADDING];
 };
 
+#ifdef GST_PACKAGE_RELEASE_DATETIME
+#define __GST_PACKAGE_RELEASE_DATETIME GST_PACKAGE_RELEASE_DATETIME
+#else
+#define __GST_PACKAGE_RELEASE_DATETIME NULL
+#endif
+
 /**
  * GST_PLUGIN_DEFINE:
  * @major: major version number of the gstreamer-core that plugin was compiled for
@@ -235,6 +246,13 @@ struct _GstPluginClass {
  * by other applications.
  *
  * The macro uses a define named PACKAGE for the #GstPluginDesc,source field.
+ * When using autoconf, this is usually set automatically via the AC_INIT
+ * macro, and set in config.h. If you are not using autoconf, you will need to
+ * define PACKAGE yourself and set it to a short mnemonic string identifying
+ * your application/package, e.g. 'someapp' or 'my-plugins-foo.
+ *
+ * If defined, the GST_PACKAGE_RELEASE_DATETIME will also be used for the
+ * #GstPluginDesc,release_datetime field.
  */
 #define GST_PLUGIN_DEFINE(major,minor,name,description,init,version,license,package,origin)    \
 G_BEGIN_DECLS \
@@ -249,6 +267,7 @@ GST_PLUGIN_EXPORT GstPluginDesc gst_plugin_desc = { \
   PACKAGE,                                             \
   package,                                             \
   origin,                                              \
+  __GST_PACKAGE_RELEASE_DATETIME,                       \
   GST_PADDING_INIT                                     \
 }; \
 G_END_DECLS
@@ -294,6 +313,7 @@ _gst_plugin_static_init__ ##init (void)                     \
     PACKAGE,                                           \
     package,                                           \
     origin,                                            \
+    NULL,                                              \
     GST_PADDING_INIT                                   \
   };                                                   \
   _gst_plugin_register_static (&plugin_desc_);         \
index 18a56a1..f851677 100644 (file)
@@ -104,7 +104,7 @@ static GstPluginDesc plugin_desc = {
   PACKAGE,
   GST_PACKAGE_NAME,
   GST_PACKAGE_ORIGIN,
-
+  NULL,
   GST_PADDING_INIT
 };