mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -05:00 
			
		
		
		
	gst: use target.object instead of node.target, soft-deprecate ids
Use target-object=<serial/name> instead of path=<id> for specifying sink/src targets. Deprecate path= argument. Change device provider to preferably expose serials instead of ids.
This commit is contained in:
		
							parent
							
								
									d66e9f1ae1
								
							
						
					
					
						commit
						67a27d80c6
					
				
					 6 changed files with 128 additions and 12 deletions
				
			
		| 
						 | 
				
			
			@ -44,6 +44,7 @@ G_DEFINE_TYPE (GstPipeWireDevice, gst_pipewire_device, GST_TYPE_DEVICE);
 | 
			
		|||
enum
 | 
			
		||||
{
 | 
			
		||||
  PROP_ID = 1,
 | 
			
		||||
  PROP_SERIAL,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static GstElement *
 | 
			
		||||
| 
						 | 
				
			
			@ -51,12 +52,16 @@ gst_pipewire_device_create_element (GstDevice * device, const gchar * name)
 | 
			
		|||
{
 | 
			
		||||
  GstPipeWireDevice *pipewire_dev = GST_PIPEWIRE_DEVICE (device);
 | 
			
		||||
  GstElement *elem;
 | 
			
		||||
  gchar *str;
 | 
			
		||||
  gchar *id_str, *serial_str;
 | 
			
		||||
 | 
			
		||||
  elem = gst_element_factory_make (pipewire_dev->element, name);
 | 
			
		||||
  str = g_strdup_printf ("%u", pipewire_dev->id);
 | 
			
		||||
  g_object_set (elem, "path", str, NULL);
 | 
			
		||||
  g_free (str);
 | 
			
		||||
 | 
			
		||||
  /* XXX: eventually only add target-object here */
 | 
			
		||||
  id_str = g_strdup_printf ("%u", pipewire_dev->id);
 | 
			
		||||
  serial_str = g_strdup_printf ("%"PRIu64, pipewire_dev->serial);
 | 
			
		||||
  g_object_set (elem, "path", id_str, "target-object", serial_str, NULL);
 | 
			
		||||
  g_free (id_str);
 | 
			
		||||
  g_free (serial_str);
 | 
			
		||||
 | 
			
		||||
  return elem;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -65,7 +70,7 @@ static gboolean
 | 
			
		|||
gst_pipewire_device_reconfigure_element (GstDevice * device, GstElement * element)
 | 
			
		||||
{
 | 
			
		||||
  GstPipeWireDevice *pipewire_dev = GST_PIPEWIRE_DEVICE (device);
 | 
			
		||||
  gchar *str;
 | 
			
		||||
  gchar *id_str, *serial_str;
 | 
			
		||||
 | 
			
		||||
  if (spa_streq(pipewire_dev->element, "pipewiresrc")) {
 | 
			
		||||
    if (!GST_IS_PIPEWIRE_SRC (element))
 | 
			
		||||
| 
						 | 
				
			
			@ -77,9 +82,12 @@ gst_pipewire_device_reconfigure_element (GstDevice * device, GstElement * elemen
 | 
			
		|||
    g_assert_not_reached ();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  str = g_strdup_printf ("%u", pipewire_dev->id);
 | 
			
		||||
  g_object_set (element, "path", str, NULL);
 | 
			
		||||
  g_free (str);
 | 
			
		||||
  /* XXX: eventually only add target-object here */
 | 
			
		||||
  id_str = g_strdup_printf ("%u", pipewire_dev->id);
 | 
			
		||||
  serial_str = g_strdup_printf ("%"PRIu64, pipewire_dev->serial);
 | 
			
		||||
  g_object_set (element, "path", id_str, "target-object", serial_str, NULL);
 | 
			
		||||
  g_free (id_str);
 | 
			
		||||
  g_free (serial_str);
 | 
			
		||||
 | 
			
		||||
  return TRUE;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -97,6 +105,9 @@ gst_pipewire_device_get_property (GObject * object, guint prop_id,
 | 
			
		|||
    case PROP_ID:
 | 
			
		||||
      g_value_set_uint (value, device->id);
 | 
			
		||||
      break;
 | 
			
		||||
    case PROP_SERIAL:
 | 
			
		||||
      g_value_set_uint64 (value, device->serial);
 | 
			
		||||
      break;
 | 
			
		||||
    default:
 | 
			
		||||
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 | 
			
		||||
      break;
 | 
			
		||||
| 
						 | 
				
			
			@ -115,6 +126,9 @@ gst_pipewire_device_set_property (GObject * object, guint prop_id,
 | 
			
		|||
    case PROP_ID:
 | 
			
		||||
      device->id = g_value_get_uint (value);
 | 
			
		||||
      break;
 | 
			
		||||
    case PROP_SERIAL:
 | 
			
		||||
      device->serial = g_value_get_uint64 (value);
 | 
			
		||||
      break;
 | 
			
		||||
    default:
 | 
			
		||||
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 | 
			
		||||
      break;
 | 
			
		||||
| 
						 | 
				
			
			@ -144,6 +158,11 @@ gst_pipewire_device_class_init (GstPipeWireDeviceClass * klass)
 | 
			
		|||
      g_param_spec_uint ("id", "Id",
 | 
			
		||||
          "The internal id of the PipeWire device", 0, G_MAXUINT32, SPA_ID_INVALID,
 | 
			
		||||
          G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
 | 
			
		||||
 | 
			
		||||
  g_object_class_install_property (object_class, PROP_SERIAL,
 | 
			
		||||
      g_param_spec_uint64 ("serial", "Serial",
 | 
			
		||||
          "The internal serial of the PipeWire device", 0, G_MAXUINT64, SPA_ID_INVALID,
 | 
			
		||||
          G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
| 
						 | 
				
			
			@ -176,6 +195,7 @@ struct node_data {
 | 
			
		|||
  struct pw_node *proxy;
 | 
			
		||||
  struct spa_hook proxy_listener;
 | 
			
		||||
  uint32_t id;
 | 
			
		||||
  uint64_t serial;
 | 
			
		||||
  struct spa_hook node_listener;
 | 
			
		||||
  struct pw_node_info *info;
 | 
			
		||||
  GstCaps *caps;
 | 
			
		||||
| 
						 | 
				
			
			@ -187,6 +207,7 @@ struct port_data {
 | 
			
		|||
  struct pw_port *proxy;
 | 
			
		||||
  struct spa_hook proxy_listener;
 | 
			
		||||
  uint32_t id;
 | 
			
		||||
  uint64_t serial;
 | 
			
		||||
  struct spa_hook port_listener;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -236,9 +257,10 @@ new_node (GstPipeWireDeviceProvider *self, struct node_data *data)
 | 
			
		|||
 | 
			
		||||
  gstdev = g_object_new (GST_TYPE_PIPEWIRE_DEVICE,
 | 
			
		||||
      "display-name", name, "caps", data->caps, "device-class", klass,
 | 
			
		||||
      "id", data->id, "properties", props, NULL);
 | 
			
		||||
      "id", data->id, "serial", data->serial, "properties", props, NULL);
 | 
			
		||||
 | 
			
		||||
  gstdev->id = data->id;
 | 
			
		||||
  gstdev->serial = data->serial;
 | 
			
		||||
  gstdev->type = type;
 | 
			
		||||
  gstdev->element = element;
 | 
			
		||||
  if (props)
 | 
			
		||||
| 
						 | 
				
			
			@ -476,6 +498,8 @@ static void registry_event_global(void *data, uint32_t id, uint32_t permissions,
 | 
			
		|||
    nd->self = self;
 | 
			
		||||
    nd->proxy = node;
 | 
			
		||||
    nd->id = id;
 | 
			
		||||
    if (!props || !spa_atou64(spa_dict_lookup(props, PW_KEY_OBJECT_SERIAL), &nd->serial, 0))
 | 
			
		||||
      nd->serial = SPA_ID_INVALID;
 | 
			
		||||
    spa_list_append(&rd->nodes, &nd->link);
 | 
			
		||||
    pw_node_add_listener(node, &nd->node_listener, &node_events, nd);
 | 
			
		||||
    pw_proxy_add_listener((struct pw_proxy*)node, &nd->proxy_listener, &proxy_node_events, nd);
 | 
			
		||||
| 
						 | 
				
			
			@ -500,6 +524,8 @@ static void registry_event_global(void *data, uint32_t id, uint32_t permissions,
 | 
			
		|||
    pd->node_data = nd;
 | 
			
		||||
    pd->proxy = port;
 | 
			
		||||
    pd->id = id;
 | 
			
		||||
    if (!props || !spa_atou64(spa_dict_lookup(props, PW_KEY_OBJECT_SERIAL), &pd->serial, 0))
 | 
			
		||||
      pd->serial = SPA_ID_INVALID;
 | 
			
		||||
    pw_port_add_listener(port, &pd->port_listener, &port_events, pd);
 | 
			
		||||
    pw_proxy_add_listener((struct pw_proxy*)port, &pd->proxy_listener, &proxy_port_events, pd);
 | 
			
		||||
    resync(self);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -56,6 +56,7 @@ struct _GstPipeWireDevice {
 | 
			
		|||
 | 
			
		||||
  GstPipeWireDeviceType  type;
 | 
			
		||||
  uint32_t            id;
 | 
			
		||||
  uint64_t            serial;
 | 
			
		||||
  const gchar        *element;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -60,6 +60,7 @@ enum
 | 
			
		|||
{
 | 
			
		||||
  PROP_0,
 | 
			
		||||
  PROP_PATH,
 | 
			
		||||
  PROP_TARGET_OBJECT,
 | 
			
		||||
  PROP_CLIENT_NAME,
 | 
			
		||||
  PROP_STREAM_PROPERTIES,
 | 
			
		||||
  PROP_MODE,
 | 
			
		||||
| 
						 | 
				
			
			@ -124,6 +125,7 @@ gst_pipewire_sink_finalize (GObject * object)
 | 
			
		|||
  if (pwsink->properties)
 | 
			
		||||
    gst_structure_free (pwsink->properties);
 | 
			
		||||
  g_free (pwsink->path);
 | 
			
		||||
  g_free (pwsink->target_object);
 | 
			
		||||
  g_free (pwsink->client_name);
 | 
			
		||||
 | 
			
		||||
  G_OBJECT_CLASS (parent_class)->finalize (object);
 | 
			
		||||
| 
						 | 
				
			
			@ -160,6 +162,16 @@ gst_pipewire_sink_class_init (GstPipeWireSinkClass * klass)
 | 
			
		|||
                                                        "The sink path to connect to (NULL = default)",
 | 
			
		||||
                                                        NULL,
 | 
			
		||||
                                                        G_PARAM_READWRITE |
 | 
			
		||||
                                                        G_PARAM_STATIC_STRINGS |
 | 
			
		||||
                                                        G_PARAM_DEPRECATED));
 | 
			
		||||
 | 
			
		||||
  g_object_class_install_property (gobject_class,
 | 
			
		||||
                                   PROP_TARGET_OBJECT,
 | 
			
		||||
                                   g_param_spec_string ("target-object",
 | 
			
		||||
                                                        "Target object",
 | 
			
		||||
                                                        "The sink name/serial to connect to (NULL = default)",
 | 
			
		||||
                                                        NULL,
 | 
			
		||||
                                                        G_PARAM_READWRITE |
 | 
			
		||||
                                                        G_PARAM_STATIC_STRINGS));
 | 
			
		||||
 | 
			
		||||
  g_object_class_install_property (gobject_class,
 | 
			
		||||
| 
						 | 
				
			
			@ -339,6 +351,11 @@ gst_pipewire_sink_set_property (GObject * object, guint prop_id,
 | 
			
		|||
      pwsink->path = g_value_dup_string (value);
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case PROP_TARGET_OBJECT:
 | 
			
		||||
      g_free (pwsink->target_object);
 | 
			
		||||
      pwsink->target_object = g_value_dup_string (value);
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case PROP_CLIENT_NAME:
 | 
			
		||||
      g_free (pwsink->client_name);
 | 
			
		||||
      pwsink->client_name = g_value_dup_string (value);
 | 
			
		||||
| 
						 | 
				
			
			@ -376,6 +393,10 @@ gst_pipewire_sink_get_property (GObject * object, guint prop_id,
 | 
			
		|||
      g_value_set_string (value, pwsink->path);
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case PROP_TARGET_OBJECT:
 | 
			
		||||
      g_value_set_string (value, pwsink->target_object);
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case PROP_CLIENT_NAME:
 | 
			
		||||
      g_value_set_string (value, pwsink->client_name);
 | 
			
		||||
      break;
 | 
			
		||||
| 
						 | 
				
			
			@ -522,15 +543,37 @@ gst_pipewire_sink_setcaps (GstBaseSink * bsink, GstCaps * caps)
 | 
			
		|||
 | 
			
		||||
  if (state == PW_STREAM_STATE_UNCONNECTED) {
 | 
			
		||||
    enum pw_stream_flags flags = 0;
 | 
			
		||||
    uint32_t target_id;
 | 
			
		||||
 | 
			
		||||
    if (pwsink->mode != GST_PIPEWIRE_SINK_MODE_PROVIDE)
 | 
			
		||||
      flags |= PW_STREAM_FLAG_AUTOCONNECT;
 | 
			
		||||
    else
 | 
			
		||||
      flags |= PW_STREAM_FLAG_DRIVER;
 | 
			
		||||
 | 
			
		||||
    target_id = pwsink->path ? (uint32_t)atoi(pwsink->path) : PW_ID_ANY;
 | 
			
		||||
 | 
			
		||||
    if (pwsink->target_object) {
 | 
			
		||||
      struct spa_dict_item items[2] = {
 | 
			
		||||
        SPA_DICT_ITEM_INIT(PW_KEY_TARGET_OBJECT, pwsink->target_object),
 | 
			
		||||
        SPA_DICT_ITEM_INIT(PW_KEY_NODE_TARGET, NULL),
 | 
			
		||||
      };
 | 
			
		||||
      struct spa_dict dict = SPA_DICT_INIT_ARRAY(items);
 | 
			
		||||
      uint64_t serial;
 | 
			
		||||
 | 
			
		||||
      /* If target.object is a name, set it also to node.target */
 | 
			
		||||
      if (spa_atou64(pwsink->target_object, &serial, 0)) {
 | 
			
		||||
        dict.n_items = 1;
 | 
			
		||||
      } else {
 | 
			
		||||
        target_id = PW_ID_ANY;
 | 
			
		||||
        items[1].value = pwsink->target_object;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      pw_stream_update_properties (pwsink->stream, &dict);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pw_stream_connect (pwsink->stream,
 | 
			
		||||
                          PW_DIRECTION_OUTPUT,
 | 
			
		||||
                          pwsink->path ? (uint32_t)atoi(pwsink->path) : PW_ID_ANY,
 | 
			
		||||
                          target_id,
 | 
			
		||||
                          flags,
 | 
			
		||||
                          (const struct spa_pod **) possible->pdata,
 | 
			
		||||
                          possible->len);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -78,6 +78,7 @@ struct _GstPipeWireSink {
 | 
			
		|||
 | 
			
		||||
  /*< private >*/
 | 
			
		||||
  gchar *path;
 | 
			
		||||
  gchar *target_object;
 | 
			
		||||
  gchar *client_name;
 | 
			
		||||
  int fd;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -67,6 +67,7 @@ enum
 | 
			
		|||
{
 | 
			
		||||
  PROP_0,
 | 
			
		||||
  PROP_PATH,
 | 
			
		||||
  PROP_TARGET_OBJECT,
 | 
			
		||||
  PROP_CLIENT_NAME,
 | 
			
		||||
  PROP_STREAM_PROPERTIES,
 | 
			
		||||
  PROP_ALWAYS_COPY,
 | 
			
		||||
| 
						 | 
				
			
			@ -116,6 +117,11 @@ gst_pipewire_src_set_property (GObject * object, guint prop_id,
 | 
			
		|||
      pwsrc->path = g_value_dup_string (value);
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case PROP_TARGET_OBJECT:
 | 
			
		||||
      g_free (pwsrc->target_object);
 | 
			
		||||
      pwsrc->target_object = g_value_dup_string (value);
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case PROP_CLIENT_NAME:
 | 
			
		||||
      g_free (pwsrc->client_name);
 | 
			
		||||
      pwsrc->client_name = g_value_dup_string (value);
 | 
			
		||||
| 
						 | 
				
			
			@ -169,6 +175,10 @@ gst_pipewire_src_get_property (GObject * object, guint prop_id,
 | 
			
		|||
      g_value_set_string (value, pwsrc->path);
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case PROP_TARGET_OBJECT:
 | 
			
		||||
      g_value_set_string (value, pwsrc->target_object);
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case PROP_CLIENT_NAME:
 | 
			
		||||
      g_value_set_string (value, pwsrc->client_name);
 | 
			
		||||
      break;
 | 
			
		||||
| 
						 | 
				
			
			@ -244,6 +254,7 @@ gst_pipewire_src_finalize (GObject * object)
 | 
			
		|||
  if (pwsrc->clock)
 | 
			
		||||
    gst_object_unref (pwsrc->clock);
 | 
			
		||||
  g_free (pwsrc->path);
 | 
			
		||||
  g_free (pwsrc->target_object);
 | 
			
		||||
  g_free (pwsrc->client_name);
 | 
			
		||||
  g_object_unref(pwsrc->pool);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -274,6 +285,16 @@ gst_pipewire_src_class_init (GstPipeWireSrcClass * klass)
 | 
			
		|||
                                                        "The source path to connect to (NULL = default)",
 | 
			
		||||
                                                        NULL,
 | 
			
		||||
                                                        G_PARAM_READWRITE |
 | 
			
		||||
                                                        G_PARAM_STATIC_STRINGS |
 | 
			
		||||
                                                        G_PARAM_DEPRECATED));
 | 
			
		||||
 | 
			
		||||
  g_object_class_install_property (gobject_class,
 | 
			
		||||
                                   PROP_TARGET_OBJECT,
 | 
			
		||||
                                   g_param_spec_string ("target-object",
 | 
			
		||||
                                                        "Target object",
 | 
			
		||||
                                                        "The source name/serial to connect to (NULL = default)",
 | 
			
		||||
                                                        NULL,
 | 
			
		||||
                                                        G_PARAM_READWRITE |
 | 
			
		||||
                                                        G_PARAM_STATIC_STRINGS));
 | 
			
		||||
 | 
			
		||||
  g_object_class_install_property (gobject_class,
 | 
			
		||||
| 
						 | 
				
			
			@ -675,6 +696,7 @@ gst_pipewire_src_negotiate (GstBaseSrc * basesrc)
 | 
			
		|||
  GPtrArray *possible;
 | 
			
		||||
  const char *error = NULL;
 | 
			
		||||
  struct timespec abstime;
 | 
			
		||||
  uint32_t target_id;
 | 
			
		||||
 | 
			
		||||
  /* first see what is possible on our source pad */
 | 
			
		||||
  thiscaps = gst_pad_query_caps (GST_BASE_SRC_PAD (basesrc), NULL);
 | 
			
		||||
| 
						 | 
				
			
			@ -727,11 +749,33 @@ gst_pipewire_src_negotiate (GstBaseSrc * basesrc)
 | 
			
		|||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  GST_DEBUG_OBJECT (basesrc, "connect capture with path %s", pwsrc->path);
 | 
			
		||||
  target_id = pwsrc->path ? (uint32_t)atoi(pwsrc->path) : PW_ID_ANY;
 | 
			
		||||
 | 
			
		||||
  if (pwsrc->target_object) {
 | 
			
		||||
      struct spa_dict_item items[2] = {
 | 
			
		||||
        SPA_DICT_ITEM_INIT(PW_KEY_TARGET_OBJECT, pwsrc->target_object),
 | 
			
		||||
        SPA_DICT_ITEM_INIT(PW_KEY_NODE_TARGET, NULL),
 | 
			
		||||
      };
 | 
			
		||||
      struct spa_dict dict = SPA_DICT_INIT_ARRAY(items);
 | 
			
		||||
      uint64_t serial;
 | 
			
		||||
 | 
			
		||||
      /* If target.object is a name, set it also to node.target */
 | 
			
		||||
      if (spa_atou64(pwsrc->target_object, &serial, 0)) {
 | 
			
		||||
        dict.n_items = 1;
 | 
			
		||||
      } else {
 | 
			
		||||
        target_id = PW_ID_ANY;
 | 
			
		||||
        items[1].value = pwsrc->target_object;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      pw_stream_update_properties (pwsrc->stream, &dict);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  GST_DEBUG_OBJECT (basesrc, "connect capture with path %s, target-object %s",
 | 
			
		||||
                    pwsrc->path, pwsrc->target_object);
 | 
			
		||||
  pwsrc->negotiated = FALSE;
 | 
			
		||||
  pw_stream_connect (pwsrc->stream,
 | 
			
		||||
                     PW_DIRECTION_INPUT,
 | 
			
		||||
                     pwsrc->path ? (uint32_t)atoi(pwsrc->path) : PW_ID_ANY,
 | 
			
		||||
                     target_id,
 | 
			
		||||
                     PW_STREAM_FLAG_AUTOCONNECT | PW_STREAM_FLAG_DONT_RECONNECT,
 | 
			
		||||
                     (const struct spa_pod **)possible->pdata,
 | 
			
		||||
                     possible->len);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -60,6 +60,7 @@ struct _GstPipeWireSrc {
 | 
			
		|||
 | 
			
		||||
  /*< private >*/
 | 
			
		||||
  gchar *path;
 | 
			
		||||
  gchar *target_object;
 | 
			
		||||
  gchar *client_name;
 | 
			
		||||
  gboolean always_copy;
 | 
			
		||||
  gint min_buffers;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue