mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -05:00 
			
		
		
		
	Rework how clients connect.
Add buffer flags. The idea is to make it possible to easily check when a buffer contains control information that we need to parse to update the port fields. Make the client create remote nodes and ports and set up proxies for them. Make a port base class implementing most of the logic to pass buffers locally and remotely. Remove most code from stream.c, it's now in the port. Make a portsink and portsrc that can write and read to/from any port. We use these in the server to send and receive data. Rework format negotiation. The final format is now sent in-line before the data. The server will select a format on output ports.
This commit is contained in:
		
							parent
							
								
									e85c3002f7
								
							
						
					
					
						commit
						4a5ed1e1f5
					
				
					 35 changed files with 3111 additions and 761 deletions
				
			
		| 
						 | 
				
			
			@ -32,7 +32,7 @@
 | 
			
		|||
 | 
			
		||||
struct _PinosClientPortPrivate
 | 
			
		||||
{
 | 
			
		||||
  gint foo;
 | 
			
		||||
  GDBusProxy *proxy;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
G_DEFINE_TYPE (PinosClientPort, pinos_client_port, PINOS_TYPE_PORT);
 | 
			
		||||
| 
						 | 
				
			
			@ -40,6 +40,7 @@ G_DEFINE_TYPE (PinosClientPort, pinos_client_port, PINOS_TYPE_PORT);
 | 
			
		|||
enum
 | 
			
		||||
{
 | 
			
		||||
  PROP_0,
 | 
			
		||||
  PROP_PROXY,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
| 
						 | 
				
			
			@ -49,8 +50,13 @@ pinos_client_port_get_property (GObject    *_object,
 | 
			
		|||
                           GParamSpec *pspec)
 | 
			
		||||
{
 | 
			
		||||
  PinosClientPort *port = PINOS_CLIENT_PORT (_object);
 | 
			
		||||
  PinosClientPortPrivate *priv = port->priv;
 | 
			
		||||
 | 
			
		||||
  switch (prop_id) {
 | 
			
		||||
    case PROP_PROXY:
 | 
			
		||||
      g_value_set_object (value, priv->proxy);
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    default:
 | 
			
		||||
      G_OBJECT_WARN_INVALID_PROPERTY_ID (port, prop_id, pspec);
 | 
			
		||||
      break;
 | 
			
		||||
| 
						 | 
				
			
			@ -64,20 +70,126 @@ pinos_client_port_set_property (GObject      *_object,
 | 
			
		|||
                           GParamSpec   *pspec)
 | 
			
		||||
{
 | 
			
		||||
  PinosClientPort *port = PINOS_CLIENT_PORT (_object);
 | 
			
		||||
  PinosClientPortPrivate *priv = port->priv;
 | 
			
		||||
 | 
			
		||||
  switch (prop_id) {
 | 
			
		||||
    case PROP_PROXY:
 | 
			
		||||
      priv->proxy = g_value_dup_object (value);
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    default:
 | 
			
		||||
      G_OBJECT_WARN_INVALID_PROPERTY_ID (port, prop_id, pspec);
 | 
			
		||||
      break;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
proxy_g_properties_changed (GDBusProxy *_proxy,
 | 
			
		||||
                            GVariant *changed_properties,
 | 
			
		||||
                            GStrv invalidated_properties,
 | 
			
		||||
                            gpointer user_data)
 | 
			
		||||
{
 | 
			
		||||
  PinosClientPort *port = user_data;
 | 
			
		||||
  GVariantIter *iter;
 | 
			
		||||
  gchar *key;
 | 
			
		||||
 | 
			
		||||
  g_variant_get (changed_properties, "a{sv}", &iter);
 | 
			
		||||
  while (g_variant_iter_next (iter, "{&sv}", &key, NULL)) {
 | 
			
		||||
    GVariant *variant;
 | 
			
		||||
    gsize size;
 | 
			
		||||
    gpointer data;
 | 
			
		||||
    GBytes *bytes;
 | 
			
		||||
 | 
			
		||||
    g_debug ("changed %s", key);
 | 
			
		||||
 | 
			
		||||
    variant = g_dbus_proxy_get_cached_property (_proxy, key);
 | 
			
		||||
    if (variant == NULL)
 | 
			
		||||
      continue;
 | 
			
		||||
 | 
			
		||||
    if (strcmp (key, "Format") == 0) {
 | 
			
		||||
      data = g_variant_dup_string (variant, &size);
 | 
			
		||||
      bytes = g_bytes_new_take (data, size);
 | 
			
		||||
      g_object_set (port, "format", bytes, NULL);
 | 
			
		||||
    }
 | 
			
		||||
    g_variant_unref (variant);
 | 
			
		||||
  }
 | 
			
		||||
  g_variant_iter_free (iter);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
static void
 | 
			
		||||
proxy_set_property_cb (GDBusProxy   *proxy,
 | 
			
		||||
                       GAsyncResult *res,
 | 
			
		||||
                       gpointer      user_data)
 | 
			
		||||
{
 | 
			
		||||
  GVariant *ret;
 | 
			
		||||
  GError *error = NULL;
 | 
			
		||||
 | 
			
		||||
  ret = g_dbus_proxy_call_finish (proxy, res, &error);
 | 
			
		||||
  if (ret == NULL) {
 | 
			
		||||
    g_warning ("Error setting property: %s", error->message);
 | 
			
		||||
    g_error_free (error);
 | 
			
		||||
  } else
 | 
			
		||||
    g_variant_unref (ret);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
on_property_notify (GObject    *obj,
 | 
			
		||||
                    GParamSpec *pspec,
 | 
			
		||||
                    gpointer    user_data)
 | 
			
		||||
{
 | 
			
		||||
  PinosPort *port = PINOS_PORT (obj);
 | 
			
		||||
  PinosClientPortPrivate *priv = PINOS_CLIENT_PORT (port)->priv;
 | 
			
		||||
  const gchar *prop_name = NULL;
 | 
			
		||||
  GVariant *variant;
 | 
			
		||||
 | 
			
		||||
  g_debug ("update %s", pspec ? g_param_spec_get_name (pspec) : "NULL");
 | 
			
		||||
 | 
			
		||||
  if (pspec == NULL || strcmp (g_param_spec_get_name (pspec), "properties") == 0) {
 | 
			
		||||
    PinosProperties *props = pinos_port_get_properties (port);
 | 
			
		||||
    prop_name = "Properties";
 | 
			
		||||
    variant = props ? pinos_properties_to_variant (props) : NULL;
 | 
			
		||||
  }
 | 
			
		||||
  if (pspec == NULL || strcmp (g_param_spec_get_name (pspec), "possible-formats") == 0) {
 | 
			
		||||
    GBytes *bytes = pinos_port_get_possible_formats (port);
 | 
			
		||||
    prop_name = "PossibleFormats";
 | 
			
		||||
    variant = bytes ? g_variant_new_string (g_bytes_get_data (bytes, NULL)) : NULL;
 | 
			
		||||
  }
 | 
			
		||||
  if (pspec == NULL || strcmp (g_param_spec_get_name (pspec), "format") == 0) {
 | 
			
		||||
    GBytes *bytes = pinos_port_get_format (port);
 | 
			
		||||
    prop_name = "Format";
 | 
			
		||||
    variant = bytes ? g_variant_new_string (g_bytes_get_data (bytes, NULL)) : NULL;
 | 
			
		||||
  }
 | 
			
		||||
  if (prop_name) {
 | 
			
		||||
    g_dbus_proxy_call (G_DBUS_PROXY (priv->proxy),
 | 
			
		||||
                       "org.freedesktop.DBus.Properties.Set",
 | 
			
		||||
                       g_variant_new ("(ssv)",
 | 
			
		||||
                         "org.pinos.Port1",
 | 
			
		||||
                         prop_name,
 | 
			
		||||
                         variant),
 | 
			
		||||
                       G_DBUS_CALL_FLAGS_NONE,
 | 
			
		||||
                       -1,
 | 
			
		||||
                       NULL,
 | 
			
		||||
                       (GAsyncReadyCallback) proxy_set_property_cb,
 | 
			
		||||
                       port);
 | 
			
		||||
    if (variant)
 | 
			
		||||
      g_variant_unref (variant);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
pinos_client_port_constructed (GObject * object)
 | 
			
		||||
{
 | 
			
		||||
  PinosClientPort *port = PINOS_CLIENT_PORT (object);
 | 
			
		||||
  PinosClientPortPrivate *priv = port->priv;
 | 
			
		||||
 | 
			
		||||
  g_debug ("client-port %p: constructed", port);
 | 
			
		||||
  g_signal_connect (priv->proxy,
 | 
			
		||||
                    "g-properties-changed",
 | 
			
		||||
                    (GCallback) proxy_g_properties_changed,
 | 
			
		||||
                    port);
 | 
			
		||||
 | 
			
		||||
  G_OBJECT_CLASS (pinos_client_port_parent_class)->constructed (object);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -92,12 +204,15 @@ pinos_client_port_dispose (GObject * object)
 | 
			
		|||
  G_OBJECT_CLASS (pinos_client_port_parent_class)->dispose (object);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
pinos_client_port_finalize (GObject * object)
 | 
			
		||||
{
 | 
			
		||||
  PinosClientPort *port = PINOS_CLIENT_PORT (object);
 | 
			
		||||
  PinosClientPortPrivate *priv = port->priv;
 | 
			
		||||
 | 
			
		||||
  g_debug ("client-port %p: finalize", port);
 | 
			
		||||
  g_clear_object (&priv->proxy);
 | 
			
		||||
 | 
			
		||||
  G_OBJECT_CLASS (pinos_client_port_parent_class)->finalize (object);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -114,6 +229,16 @@ pinos_client_port_class_init (PinosClientPortClass * klass)
 | 
			
		|||
  gobject_class->finalize = pinos_client_port_finalize;
 | 
			
		||||
  gobject_class->set_property = pinos_client_port_set_property;
 | 
			
		||||
  gobject_class->get_property = pinos_client_port_get_property;
 | 
			
		||||
 | 
			
		||||
  g_object_class_install_property (gobject_class,
 | 
			
		||||
                                   PROP_PROXY,
 | 
			
		||||
                                   g_param_spec_object ("proxy",
 | 
			
		||||
                                                        "Proxy",
 | 
			
		||||
                                                        "The Proxy",
 | 
			
		||||
                                                        G_TYPE_DBUS_PROXY,
 | 
			
		||||
                                                        G_PARAM_READWRITE |
 | 
			
		||||
                                                        G_PARAM_CONSTRUCT_ONLY |
 | 
			
		||||
                                                        G_PARAM_STATIC_STRINGS));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
| 
						 | 
				
			
			@ -121,3 +246,72 @@ pinos_client_port_init (PinosClientPort * port)
 | 
			
		|||
{
 | 
			
		||||
  port->priv = PINOS_CLIENT_PORT_GET_PRIVATE (port);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * pinos_client_port_new:
 | 
			
		||||
 * @node: a #PinosClientNode
 | 
			
		||||
 * @id: an id
 | 
			
		||||
 * @socket: a socket with the server port
 | 
			
		||||
 *
 | 
			
		||||
 * Create a new client port.
 | 
			
		||||
 *
 | 
			
		||||
 * Returns: a new client port
 | 
			
		||||
 */
 | 
			
		||||
PinosClientPort *
 | 
			
		||||
pinos_client_port_new (PinosClientNode *node,
 | 
			
		||||
                       gpointer         id,
 | 
			
		||||
                       GSocket         *socket)
 | 
			
		||||
{
 | 
			
		||||
  PinosClientPort *port;
 | 
			
		||||
  GDBusProxy *proxy = id;
 | 
			
		||||
  GVariant *variant;
 | 
			
		||||
  PinosDirection direction = PINOS_DIRECTION_INVALID;
 | 
			
		||||
  const gchar *name = "unknown";
 | 
			
		||||
  GBytes *possible_formats = NULL;
 | 
			
		||||
  GBytes *format = NULL;
 | 
			
		||||
  PinosProperties *properties = NULL;
 | 
			
		||||
 | 
			
		||||
  variant = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (proxy), "Direction");
 | 
			
		||||
  if (variant != NULL) {
 | 
			
		||||
    direction = g_variant_get_uint32 (variant);
 | 
			
		||||
    g_variant_unref (variant);
 | 
			
		||||
  }
 | 
			
		||||
  variant = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (proxy), "Name");
 | 
			
		||||
  if (variant != NULL) {
 | 
			
		||||
    name = g_variant_get_string (variant, NULL);
 | 
			
		||||
    g_variant_unref (variant);
 | 
			
		||||
  }
 | 
			
		||||
  variant = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (proxy), "PossibleFormats");
 | 
			
		||||
  if (variant != NULL) {
 | 
			
		||||
    gsize size;
 | 
			
		||||
    gpointer data;
 | 
			
		||||
    data = g_variant_dup_string (variant, &size);
 | 
			
		||||
    possible_formats = g_bytes_new_take (data, size);
 | 
			
		||||
    g_variant_unref (variant);
 | 
			
		||||
  }
 | 
			
		||||
  variant = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (proxy), "Format");
 | 
			
		||||
  if (variant != NULL) {
 | 
			
		||||
    gsize size;
 | 
			
		||||
    gpointer data;
 | 
			
		||||
    data = g_variant_dup_string (variant, &size);
 | 
			
		||||
    format = g_bytes_new_take (data, size);
 | 
			
		||||
    g_variant_unref (variant);
 | 
			
		||||
  }
 | 
			
		||||
  variant = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (proxy), "Properties");
 | 
			
		||||
  if (variant != NULL) {
 | 
			
		||||
    properties = pinos_properties_from_variant (variant);
 | 
			
		||||
    g_variant_unref (variant);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  port = g_object_new (PINOS_TYPE_CLIENT_PORT,
 | 
			
		||||
                       "node", node,
 | 
			
		||||
                       "direction", direction,
 | 
			
		||||
                       "name", name,
 | 
			
		||||
                       "possible-formats", possible_formats,
 | 
			
		||||
                       "format", format,
 | 
			
		||||
                       "properties", properties,
 | 
			
		||||
                       "proxy", proxy,
 | 
			
		||||
                       "socket", socket,
 | 
			
		||||
                       NULL);
 | 
			
		||||
  return port;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue