mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -05:00 
			
		
		
		
	devicemonitor: various improvements
Set the active device providers as a property on the daemon. In the device monitor we can then obsolete the already monitored devices. Copy all device properties to the source. Set the device class as a property on the monitored devices.
This commit is contained in:
		
							parent
							
								
									191909cb05
								
							
						
					
					
						commit
						1378a65fb7
					
				
					 2 changed files with 137 additions and 13 deletions
				
			
		| 
						 | 
				
			
			@ -44,35 +44,31 @@ enum
 | 
			
		|||
 | 
			
		||||
static GstDevice *
 | 
			
		||||
gst_pinos_device_new (gpointer id, const gchar * device_name,
 | 
			
		||||
    GstCaps * caps, const gchar * path, GstPinosDeviceType type)
 | 
			
		||||
    GstCaps * caps, const gchar * path, const gchar *klass,
 | 
			
		||||
    GstPinosDeviceType type, GstStructure *props)
 | 
			
		||||
{
 | 
			
		||||
  GstPinosDevice *gstdev;
 | 
			
		||||
  const gchar *element = NULL;
 | 
			
		||||
  const gchar *klass = NULL;
 | 
			
		||||
 | 
			
		||||
  g_return_val_if_fail (device_name, NULL);
 | 
			
		||||
  g_return_val_if_fail (path, NULL);
 | 
			
		||||
  g_return_val_if_fail (caps, NULL);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  switch (type) {
 | 
			
		||||
    case GST_PINOS_DEVICE_TYPE_SOURCE:
 | 
			
		||||
      element = "pinossrc";
 | 
			
		||||
      klass = "Video/Source/Pinos";
 | 
			
		||||
      break;
 | 
			
		||||
    case GST_PINOS_DEVICE_TYPE_SINK:
 | 
			
		||||
      element = "pinossink";
 | 
			
		||||
      klass = "Video/Sink/Pinos";
 | 
			
		||||
      break;
 | 
			
		||||
    default:
 | 
			
		||||
      g_assert_not_reached ();
 | 
			
		||||
      break;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  gstdev = g_object_new (GST_TYPE_PINOS_DEVICE,
 | 
			
		||||
      "display-name", device_name, "caps", caps, "device-class", klass,
 | 
			
		||||
      "path", path, NULL);
 | 
			
		||||
      "path", path, "properties", props, NULL);
 | 
			
		||||
 | 
			
		||||
  gstdev->id = id;
 | 
			
		||||
  gstdev->type = type;
 | 
			
		||||
| 
						 | 
				
			
			@ -209,17 +205,39 @@ static GstDevice *
 | 
			
		|||
new_source (const PinosSourceInfo *info)
 | 
			
		||||
{
 | 
			
		||||
  GstCaps *caps;
 | 
			
		||||
  GstStructure *props;
 | 
			
		||||
  gpointer state = NULL;
 | 
			
		||||
  const gchar *klass;
 | 
			
		||||
 | 
			
		||||
  if (info->formats)
 | 
			
		||||
    caps = gst_caps_from_string (g_bytes_get_data (info->formats, NULL));
 | 
			
		||||
  else
 | 
			
		||||
    caps = gst_caps_new_any();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  props = gst_structure_new_empty ("pinos-proplist");
 | 
			
		||||
 | 
			
		||||
  while (TRUE) {
 | 
			
		||||
    const char *key, *val;
 | 
			
		||||
 | 
			
		||||
    if (!(key = pinos_properties_iterate (info->properties, &state)))
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    val = pinos_properties_get (info->properties, key);
 | 
			
		||||
    gst_structure_set (props, key, G_TYPE_STRING, val, NULL);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  klass = pinos_properties_get (info->properties, "gstreamer.device.class");
 | 
			
		||||
  if (klass == NULL)
 | 
			
		||||
    klass = "unknown/unknown";
 | 
			
		||||
 | 
			
		||||
  return gst_pinos_device_new (info->id,
 | 
			
		||||
                               info->name,
 | 
			
		||||
                               caps,
 | 
			
		||||
                               info->source_path,
 | 
			
		||||
                               GST_PINOS_DEVICE_TYPE_SOURCE);
 | 
			
		||||
                               klass,
 | 
			
		||||
                               GST_PINOS_DEVICE_TYPE_SOURCE,
 | 
			
		||||
                               props);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
| 
						 | 
				
			
			@ -317,6 +335,30 @@ list_source_info_cb (PinosContext          *c,
 | 
			
		|||
  return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
get_daemon_info_cb (PinosContext *c, const PinosDaemonInfo *info, gpointer userdata)
 | 
			
		||||
{
 | 
			
		||||
  GstDeviceProvider *provider = userdata;
 | 
			
		||||
  const gchar *value;
 | 
			
		||||
 | 
			
		||||
  if (info == NULL)
 | 
			
		||||
    return TRUE;
 | 
			
		||||
 | 
			
		||||
  value = pinos_properties_get (info->properties, "gstreamer.deviceproviders");
 | 
			
		||||
  if (value) {
 | 
			
		||||
    gchar **providers = g_strsplit (value, ",", -1);
 | 
			
		||||
    gint i;
 | 
			
		||||
 | 
			
		||||
    GST_DEBUG_OBJECT (provider, "have obsoleted providers: %s\n", value);
 | 
			
		||||
 | 
			
		||||
    for (i = 0; providers[i]; i++) {
 | 
			
		||||
      gst_device_provider_add_obsoleted (provider, providers[i]);
 | 
			
		||||
    }
 | 
			
		||||
    g_strfreev (providers);
 | 
			
		||||
  }
 | 
			
		||||
  return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static GList *
 | 
			
		||||
gst_pinos_device_provider_probe (GstDeviceProvider * provider)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -325,6 +367,8 @@ gst_pinos_device_provider_probe (GstDeviceProvider * provider)
 | 
			
		|||
  PinosContext *c = NULL;
 | 
			
		||||
  InfoData data;
 | 
			
		||||
 | 
			
		||||
  GST_DEBUG_OBJECT (self, "starting probe");
 | 
			
		||||
 | 
			
		||||
  if (!(m = g_main_context_new ()))
 | 
			
		||||
    return NULL;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -354,6 +398,13 @@ gst_pinos_device_provider_probe (GstDeviceProvider * provider)
 | 
			
		|||
  }
 | 
			
		||||
  GST_DEBUG_OBJECT (self, "connected");
 | 
			
		||||
 | 
			
		||||
  pinos_context_get_daemon_info (c,
 | 
			
		||||
                                 PINOS_DAEMON_INFO_FLAGS_NONE,
 | 
			
		||||
                                 get_daemon_info_cb,
 | 
			
		||||
                                 NULL,
 | 
			
		||||
                                 self);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  data.end = FALSE;
 | 
			
		||||
  data.devices = NULL;
 | 
			
		||||
  pinos_context_list_source_info (c,
 | 
			
		||||
| 
						 | 
				
			
			@ -419,6 +470,8 @@ gst_pinos_device_provider_start (GstDeviceProvider * provider)
 | 
			
		|||
  GError *error = NULL;
 | 
			
		||||
  GMainContext *c;
 | 
			
		||||
 | 
			
		||||
  GST_DEBUG_OBJECT (self, "starting provider");
 | 
			
		||||
 | 
			
		||||
  c = g_main_context_new ();
 | 
			
		||||
 | 
			
		||||
  if (!(self->loop = pinos_main_loop_new (c, "pinos-device-monitor"))) {
 | 
			
		||||
| 
						 | 
				
			
			@ -455,8 +508,32 @@ gst_pinos_device_provider_start (GstDeviceProvider * provider)
 | 
			
		|||
                    (GCallback) context_subscribe_cb,
 | 
			
		||||
                    self);
 | 
			
		||||
 | 
			
		||||
  pinos_context_connect (self->context, PINOS_CONTEXT_FLAGS_NOFAIL);
 | 
			
		||||
  pinos_context_connect (self->context, PINOS_CONTEXT_FLAGS_NONE);
 | 
			
		||||
  for (;;) {
 | 
			
		||||
    PinosContextState state;
 | 
			
		||||
 | 
			
		||||
    state = pinos_context_get_state (self->context);
 | 
			
		||||
 | 
			
		||||
    if (state <= 0) {
 | 
			
		||||
      GST_WARNING_OBJECT (self, "Failed to connect: %s",
 | 
			
		||||
          pinos_context_get_error (self->context)->message);
 | 
			
		||||
      goto not_running;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (state == PINOS_CONTEXT_STATE_READY)
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    /* Wait until something happens */
 | 
			
		||||
    pinos_main_loop_wait (self->loop);
 | 
			
		||||
  }
 | 
			
		||||
  GST_DEBUG_OBJECT (self, "connected");
 | 
			
		||||
  pinos_context_get_daemon_info (self->context,
 | 
			
		||||
                                 PINOS_DAEMON_INFO_FLAGS_NONE,
 | 
			
		||||
                                 get_daemon_info_cb,
 | 
			
		||||
                                 NULL,
 | 
			
		||||
                                 self);
 | 
			
		||||
  pinos_main_loop_unlock (self->loop);
 | 
			
		||||
 | 
			
		||||
  g_main_context_unref (c);
 | 
			
		||||
 | 
			
		||||
  return TRUE;
 | 
			
		||||
| 
						 | 
				
			
			@ -466,6 +543,14 @@ failed:
 | 
			
		|||
    g_main_context_unref (c);
 | 
			
		||||
    return FALSE;
 | 
			
		||||
  }
 | 
			
		||||
not_running:
 | 
			
		||||
  {
 | 
			
		||||
    pinos_main_loop_unlock (self->loop);
 | 
			
		||||
    pinos_main_loop_stop (self->loop);
 | 
			
		||||
    g_clear_object (&self->context);
 | 
			
		||||
    g_clear_object (&self->loop);
 | 
			
		||||
    return TRUE;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
| 
						 | 
				
			
			@ -476,8 +561,9 @@ gst_pinos_device_provider_stop (GstDeviceProvider * provider)
 | 
			
		|||
  if (self->context) {
 | 
			
		||||
    pinos_context_disconnect (self->context);
 | 
			
		||||
  }
 | 
			
		||||
  if (self->loop) {
 | 
			
		||||
    pinos_main_loop_stop (self->loop);
 | 
			
		||||
 | 
			
		||||
  }
 | 
			
		||||
  g_clear_object (&self->context);
 | 
			
		||||
  g_clear_object (&self->loop);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -42,6 +42,21 @@ enum
 | 
			
		|||
 | 
			
		||||
G_DEFINE_TYPE (PinosGstManager, pinos_gst_manager, G_TYPE_OBJECT);
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
copy_properties (GQuark field_id,
 | 
			
		||||
                 const GValue *value,
 | 
			
		||||
                 gpointer user_data)
 | 
			
		||||
{
 | 
			
		||||
  PinosProperties *properties = user_data;
 | 
			
		||||
 | 
			
		||||
  if (G_VALUE_HOLDS_STRING (value))
 | 
			
		||||
    pinos_properties_set (properties,
 | 
			
		||||
                          g_quark_to_string (field_id),
 | 
			
		||||
                          g_value_get_string (value));
 | 
			
		||||
 | 
			
		||||
  return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
device_added (PinosGstManager *manager,
 | 
			
		||||
              GstDevice       *device)
 | 
			
		||||
| 
						 | 
				
			
			@ -50,6 +65,8 @@ device_added (PinosGstManager *manager,
 | 
			
		|||
  gchar *name;
 | 
			
		||||
  GstElement *element;
 | 
			
		||||
  PinosSource *source;
 | 
			
		||||
  GstStructure *p;
 | 
			
		||||
  PinosProperties *properties;
 | 
			
		||||
 | 
			
		||||
  name = gst_device_get_display_name (device);
 | 
			
		||||
  if (strcmp (name, "gst") == 0)
 | 
			
		||||
| 
						 | 
				
			
			@ -57,8 +74,15 @@ device_added (PinosGstManager *manager,
 | 
			
		|||
 | 
			
		||||
  g_print("Device added: %s\n", name);
 | 
			
		||||
 | 
			
		||||
  properties = pinos_properties_new (NULL);
 | 
			
		||||
  if ((p = gst_device_get_properties (device)))
 | 
			
		||||
    gst_structure_foreach (p, copy_properties, properties);
 | 
			
		||||
  pinos_properties_set (properties,
 | 
			
		||||
                        "gstreamer.device.class",
 | 
			
		||||
                        gst_device_get_device_class (device));
 | 
			
		||||
 | 
			
		||||
  element = gst_device_create_element (device, NULL);
 | 
			
		||||
  source = pinos_gst_source_new (priv->daemon, name, element);
 | 
			
		||||
  source = pinos_gst_source_new (priv->daemon, name, properties, element);
 | 
			
		||||
  g_object_set_data (G_OBJECT (device), "PinosSource", source);
 | 
			
		||||
  g_free (name);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -129,6 +153,9 @@ start_monitor (PinosGstManager *manager)
 | 
			
		|||
  PinosGstManagerPrivate *priv = manager->priv;
 | 
			
		||||
  GstBus *bus;
 | 
			
		||||
  GList *devices;
 | 
			
		||||
  gchar **providers;
 | 
			
		||||
  gchar *provided;
 | 
			
		||||
  PinosProperties *props;
 | 
			
		||||
 | 
			
		||||
  disable_pinos_provider (manager);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -139,9 +166,20 @@ start_monitor (PinosGstManager *manager)
 | 
			
		|||
  gst_object_unref (bus);
 | 
			
		||||
 | 
			
		||||
  gst_device_monitor_add_filter (priv->monitor, "Video/Source", NULL);
 | 
			
		||||
 | 
			
		||||
  gst_device_monitor_add_filter (priv->monitor, "Audio/Source", NULL);
 | 
			
		||||
  gst_device_monitor_start (priv->monitor);
 | 
			
		||||
 | 
			
		||||
  providers = gst_device_monitor_get_providers (priv->monitor);
 | 
			
		||||
  provided = g_strjoinv (",", providers);
 | 
			
		||||
  g_strfreev (providers);
 | 
			
		||||
 | 
			
		||||
  g_object_get (priv->daemon, "properties", &props, NULL);
 | 
			
		||||
  pinos_properties_set (props, "gstreamer.deviceproviders", provided);
 | 
			
		||||
  g_object_set (priv->daemon, "properties", props, NULL);
 | 
			
		||||
  pinos_properties_free (props);
 | 
			
		||||
 | 
			
		||||
  g_free (provided);
 | 
			
		||||
 | 
			
		||||
  devices = gst_device_monitor_get_devices (priv->monitor);
 | 
			
		||||
  while (devices != NULL) {
 | 
			
		||||
    GstDevice *device = devices->data;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue