device-provider: Allow notifying application of device changes
authorThibault Saunier <tsaunier@igalia.com>
Wed, 30 Jan 2019 13:41:58 +0000 (10:41 -0300)
committerThibault Saunier <tsaunier@igalia.com>
Fri, 8 Feb 2019 16:44:02 +0000 (13:44 -0300)
Thi introduces new APIs to post a `DEVICE_CHANGED` message on the
bus so the application is notifies when a device is modified. For
example, if the "defaultness" of a device was changed or any property
that can be changed at any time. Atomically changing the device
object notifying that way allow us to abtract away the internal threads.

New APIS:
  - gst_message_new_device_changed
  - gst_message_parse_device_changed
  - gst_device_provider_device_changed

docs/gst/gstreamer-sections.txt
gst/gstdevicemonitor.c
gst/gstdeviceprovider.c
gst/gstdeviceprovider.h
gst/gstmessage.c
gst/gstmessage.h
gst/gstquark.c
gst/gstquark.h

index 7e920e0..a32b06b 100644 (file)
@@ -1748,8 +1748,10 @@ gst_message_parse_have_context
 
 gst_message_new_device_added
 gst_message_new_device_removed
+gst_message_new_device_changed
 gst_message_parse_device_added
 gst_message_parse_device_removed
+gst_message_parse_device_changed
 
 gst_message_new_property_notify
 gst_message_parse_property_notify
@@ -3928,6 +3930,7 @@ gst_device_provider_class_set_metadata
 gst_device_provider_class_set_static_metadata
 gst_device_provider_device_add
 gst_device_provider_device_remove
+gst_device_provider_device_changed
 gst_device_provider_get_bus
 gst_device_provider_get_devices
 gst_device_provider_get_factory
index bbe492c..088eb4c 100644 (file)
@@ -234,15 +234,18 @@ bus_sync_message (GstBus * bus, GstMessage * message,
 {
   GstMessageType type = GST_MESSAGE_TYPE (message);
 
-  if (type == GST_MESSAGE_DEVICE_ADDED || type == GST_MESSAGE_DEVICE_REMOVED) {
+  if (type == GST_MESSAGE_DEVICE_ADDED || type == GST_MESSAGE_DEVICE_REMOVED ||
+      type == GST_MESSAGE_DEVICE_CHANGED) {
     gboolean matches = TRUE;
     GstDevice *device;
     GstDeviceProvider *provider;
 
     if (type == GST_MESSAGE_DEVICE_ADDED)
       gst_message_parse_device_added (message, &device);
-    else
+    else if (type == GST_MESSAGE_DEVICE_REMOVED)
       gst_message_parse_device_removed (message, &device);
+    else
+      gst_message_parse_device_changed (message, &device, NULL);
 
     GST_OBJECT_LOCK (monitor);
     provider =
index 2e0b55d..be70221 100644 (file)
@@ -772,3 +772,53 @@ gst_device_provider_unhide_provider (GstDeviceProvider * provider,
     g_free (unhidden_name);
   }
 }
+
+/**
+ * gst_device_provider_device_changed:
+ * @device: (transfer-none): the new version of @changed_device
+ * @changed_device: (transfer-floating): the old version of the device that has been udpated
+ *
+ * This function is used when @changed_device was modified into its new form
+ * @device. This will post a `DEVICE_CHANGED` message on the bus to let
+ * the application know that the device was modified. #GstDevice is immutable
+ * for MT. safety purposes so this is an "atomic" way of letting the application
+ * know when a device was modified.
+ *
+ * Since: 1.16
+ */
+void
+gst_device_provider_device_changed (GstDeviceProvider * provider,
+    GstDevice * device, GstDevice * changed_device)
+{
+  GList *dev_lst;
+  GstMessage *message;
+
+  g_return_if_fail (GST_IS_DEVICE_PROVIDER (provider));
+  g_return_if_fail (GST_IS_DEVICE (device));
+  g_return_if_fail (GST_IS_DEVICE (changed_device));
+
+  GST_OBJECT_LOCK (provider);
+  dev_lst = g_list_find (provider->devices, changed_device);
+  if (!dev_lst) {
+    GST_ERROR_OBJECT (provider,
+        "Trying to update a device we do not have in our own list!");
+
+    GST_OBJECT_UNLOCK (provider);
+    return;
+  }
+
+  if (!gst_object_set_parent (GST_OBJECT (device), GST_OBJECT (provider))) {
+    GST_OBJECT_UNLOCK (provider);
+    GST_WARNING_OBJECT (provider, "Could not parent device %p to provider,"
+        " it already has a parent", device);
+    return;
+  }
+  dev_lst->data = device;
+  GST_OBJECT_UNLOCK (provider);
+
+  message =
+      gst_message_new_device_changed (GST_OBJECT (provider), device,
+      changed_device);
+  gst_bus_post (provider->priv->bus, message);
+  gst_object_unparent (GST_OBJECT (changed_device));
+}
index a8f4474..bcde319 100644 (file)
@@ -162,6 +162,11 @@ GST_API
 const gchar * gst_device_provider_class_get_metadata       (GstDeviceProviderClass * klass,
                                                             const gchar * key);
 
+GST_API
+void gst_device_provider_device_changed                    (GstDeviceProvider * provider,
+                                                            GstDevice *device,
+                                                            GstDevice *changed_device);
+
 /* factory management */
 
 GST_API
index 25c47e1..e415e73 100644 (file)
@@ -107,6 +107,7 @@ static GstMessageQuarks message_quarks[] = {
   {GST_MESSAGE_HAVE_CONTEXT, "have-context", 0},
   {GST_MESSAGE_DEVICE_ADDED, "device-added", 0},
   {GST_MESSAGE_DEVICE_REMOVED, "device-removed", 0},
+  {GST_MESSAGE_DEVICE_CHANGED, "device-changed", 0},
   {GST_MESSAGE_PROPERTY_NOTIFY, "property-notify", 0},
   {GST_MESSAGE_STREAM_COLLECTION, "stream-collection", 0},
   {GST_MESSAGE_STREAMS_SELECTED, "streams-selected", 0},
@@ -2691,6 +2692,69 @@ gst_message_parse_device_removed (GstMessage * message, GstDevice ** device)
 }
 
 /**
+ * gst_message_new_device_changed:
+ * @src: The #GstObject that created the message
+ * @device: (transfer none): The newly created device representing @replaced_device
+ *         with its new configuration.
+ *
+ * Creates a new device-changed message. The device-changed message is produced
+ * by #GstDeviceProvider or a #GstDeviceMonitor. They announce that a device
+ * properties has changed and @device represent the new modified version of @changed_device.
+ *
+ * Returns: a newly allocated #GstMessage
+ *
+ * Since: 1.16
+ */
+GstMessage *
+gst_message_new_device_changed (GstObject * src, GstDevice * device,
+    GstDevice * changed_device)
+{
+  GstMessage *message;
+  GstStructure *structure;
+
+  g_return_val_if_fail (device != NULL, NULL);
+  g_return_val_if_fail (GST_IS_DEVICE (device), NULL);
+
+  structure = gst_structure_new_id (GST_QUARK (MESSAGE_DEVICE_CHANGED),
+      GST_QUARK (DEVICE), GST_TYPE_DEVICE, device,
+      GST_QUARK (DEVICE_CHANGED), GST_TYPE_DEVICE, changed_device, NULL);
+  message = gst_message_new_custom (GST_MESSAGE_DEVICE_CHANGED, src, structure);
+
+  return message;
+}
+
+/**
+ * gst_message_parse_device_changed:
+ * @message: a #GstMessage of type %GST_MESSAGE_DEVICE_CHANGED
+ * @device: (out) (allow-none) (transfer full): A location where to store a
+ *  pointer to the updated version of the #GstDevice, or %NULL
+ * @changed_device: (out) (allow-none) (transfer full): A location where to store a
+ *  pointer to the old version of the #GstDevice, or %NULL
+ *
+ * Parses a device-changed message. The device-changed message is produced by
+ * #GstDeviceProvider or a #GstDeviceMonitor. It announces the
+ * disappearance of monitored devices. * It announce that a device properties has
+ * changed and @device represents the new modified version of @changed_device.
+ *
+ * Since: 1.16
+ */
+void
+gst_message_parse_device_changed (GstMessage * message, GstDevice ** device,
+    GstDevice ** changed_device)
+{
+  g_return_if_fail (GST_IS_MESSAGE (message));
+  g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_DEVICE_CHANGED);
+
+  if (device)
+    gst_structure_id_get (GST_MESSAGE_STRUCTURE (message),
+        GST_QUARK (DEVICE), GST_TYPE_DEVICE, device, NULL);
+
+  if (changed_device)
+    gst_structure_id_get (GST_MESSAGE_STRUCTURE (message),
+        GST_QUARK (DEVICE_CHANGED), GST_TYPE_DEVICE, changed_device, NULL);
+}
+
+/**
  * gst_message_new_property_notify:
  * @src: The #GstObject whose property changed (may or may not be a #GstElement)
  * @property_name: name of the property that changed
index 9831308..fc50ce9 100644 (file)
@@ -119,6 +119,8 @@ typedef struct _GstMessage GstMessage;
  * @GST_MESSAGE_REDIRECT: Message indicating to request the application to
  *     try to play the given URL(s). Useful if for example a HTTP 302/303
  *     response is received with a non-HTTP URL inside. (Since 1.10)
+ * @GST_MESSAGE_DEVICE_CHANGED: Message indicating a #GstDevice was changed
+ *     a #GstDeviceProvider (Since 1.16)
  * @GST_MESSAGE_ANY: mask for all of the above messages.
  *
  * The different message types that are available.
@@ -171,6 +173,7 @@ typedef enum
   GST_MESSAGE_STREAM_COLLECTION = GST_MESSAGE_EXTENDED + 4,
   GST_MESSAGE_STREAMS_SELECTED  = GST_MESSAGE_EXTENDED + 5,
   GST_MESSAGE_REDIRECT          = GST_MESSAGE_EXTENDED + 6,
+  GST_MESSAGE_DEVICE_CHANGED    = GST_MESSAGE_EXTENDED + 6,
   GST_MESSAGE_ANY               = (gint) (0xffffffff)
 } GstMessageType;
 
@@ -806,6 +809,15 @@ GstMessage *    gst_message_new_device_removed    (GstObject * src, GstDevice *
 GST_API
 void            gst_message_parse_device_removed  (GstMessage * message, GstDevice ** device);
 
+/* DEVICE_CHANGED */
+
+GST_API
+GstMessage *    gst_message_new_device_changed    (GstObject * src, GstDevice * device, GstDevice *changed_device);
+
+GST_API
+void            gst_message_parse_device_changed  (GstMessage * message, GstDevice ** device, GstDevice ** changed_device);
+
+
 /* PROPERTY_NOTIFY */
 
 GST_API
index 4d5b36f..4614578 100644 (file)
@@ -75,7 +75,8 @@ static const gchar *_quark_strings[] = {
   "GstMessageStreamCollection", "collection", "stream", "stream-collection",
   "GstMessageStreamsSelected", "GstMessageRedirect", "redirect-entry-locations",
   "redirect-entry-taglists", "redirect-entry-structures",
-  "GstEventStreamGroupDone", "GstQueryBitrate", "nominal-bitrate"
+  "GstEventStreamGroupDone", "GstQueryBitrate", "nominal-bitrate",
+  "GstMessageDeviceChanged", "device-changed"
 };
 
 GQuark _priv_gst_quark_table[GST_QUARK_MAX];
index d3daaed..e93a61f 100644 (file)
@@ -219,7 +219,9 @@ typedef enum _GstQuarkId
   GST_QUARK_EVENT_STREAM_GROUP_DONE = 188,
   GST_QUARK_QUERY_BITRATE = 189,
   GST_QUARK_NOMINAL_BITRATE = 190,
-  GST_QUARK_MAX = 191
+  GST_QUARK_MESSAGE_DEVICE_CHANGED = 191,
+  GST_QUARK_DEVICE_CHANGED = 192,
+  GST_QUARK_MAX = 193
 } GstQuarkId;
 
 extern GQuark _priv_gst_quark_table[GST_QUARK_MAX];