diff --git a/modules/meson.build b/modules/meson.build
index 79448d4db76c978220f6d65b196908982e0d610c..9c96b586c9004c6ab392fc9b9f0ca1b5141aa84f 100644
--- a/modules/meson.build
+++ b/modules/meson.build
@@ -41,7 +41,6 @@ shared_library(
   [
     'module-pipewire.c',
     'module-pipewire/simple-endpoint-link.c',
-    'module-pipewire/simple-endpoint.c',
   ],
   c_args : [common_c_args, '-DG_LOG_DOMAIN="m-pipewire"'],
   install : true,
diff --git a/modules/module-pipewire.c b/modules/module-pipewire.c
index 9d16f19bafa9a62b7c4be6cfae62d0912d7e09cc..91ae9b9a2a5a372f2ffe83ae487467bfb9390940 100644
--- a/modules/module-pipewire.c
+++ b/modules/module-pipewire.c
@@ -15,8 +15,6 @@
 #include <wp/wp.h>
 #include <pipewire/pipewire.h>
 
-void simple_endpoint_factory (WpFactory * factory, GType type,
-    GVariant * properties, GAsyncReadyCallback ready, gpointer user_data);
 void simple_endpoint_link_factory (WpFactory * factory, GType type,
     GVariant * properties, GAsyncReadyCallback ready, gpointer user_data);
 
@@ -28,9 +26,7 @@ wireplumber__module_init (WpModule * module, WpCore * core, GVariant * args)
   pw_module_load (pw_core, "libpipewire-module-client-device", NULL, NULL);
   pw_module_load (pw_core, "libpipewire-module-adapter", NULL, NULL);
 
-  /* Register simple-endpoint and simple-endpoint-link */
-  wp_factory_new (core, "pipewire-simple-endpoint",
-      simple_endpoint_factory);
+  /* Register simple-endpoint-link */
   wp_factory_new (core, "pipewire-simple-endpoint-link",
       simple_endpoint_link_factory);
 }
diff --git a/modules/module-pipewire/simple-endpoint.c b/modules/module-pipewire/simple-endpoint.c
deleted file mode 100644
index 9dba4885914f1aaccc2d4631b6d2e3d1e90ad0d7..0000000000000000000000000000000000000000
--- a/modules/module-pipewire/simple-endpoint.c
+++ /dev/null
@@ -1,544 +0,0 @@
-/* WirePlumber
- *
- * Copyright © 2019 Collabora Ltd.
- *    @author George Kiagiadakis <george.kiagiadakis@collabora.com>
- *
- * SPDX-License-Identifier: MIT
- */
-
-/**
- * The simple endpoint is a WpEndpoint implementation that represents
- * all ports of a single direction of a single pipewire node.
- * It can be used to create an Endpoint for a client node or for any
- * other arbitrary node that does not need any kind of internal management.
- */
-
-#include <spa/param/audio/format-utils.h>
-
-#include <wp/wp.h>
-#include <pipewire/pipewire.h>
-#include <spa/pod/parser.h>
-#include <spa/param/props.h>
-
-struct _WpPipewireSimpleEndpoint
-{
-  WpEndpoint parent;
-
-  /* properties */
-  gchar *role;
-  guint64 creation_time;
-  gchar *target;
-
-  /* The task to signal the endpoint is initialized */
-  GTask *init_task;
-
-  /* Proxies */
-  WpProxyNode *proxy_node;
-  GPtrArray *proxies_port;
-
-  /* controls cache */
-  gfloat volume;
-  gboolean mute;
-};
-
-enum {
-  PROP_0,
-  PROP_PROXY_NODE,
-  PROP_ROLE,
-  PROP_CREATION_TIME,
-  PROP_TARGET,
-};
-
-enum {
-  CONTROL_VOLUME = 0,
-  CONTROL_MUTE,
-};
-
-static GAsyncInitableIface *wp_simple_endpoint_parent_interface = NULL;
-static void wp_simple_endpoint_async_initable_init (gpointer iface,
-    gpointer iface_data);
-
-G_DECLARE_FINAL_TYPE (WpPipewireSimpleEndpoint,
-    simple_endpoint, WP_PIPEWIRE, SIMPLE_ENDPOINT, WpEndpoint)
-
-G_DEFINE_TYPE_WITH_CODE (WpPipewireSimpleEndpoint, simple_endpoint,
-    WP_TYPE_ENDPOINT,
-    G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE,
-                           wp_simple_endpoint_async_initable_init))
-
-static gboolean
-proxy_safe_augment_finish (WpPipewireSimpleEndpoint * self, WpProxy *proxy,
-    GAsyncResult *res)
-{
-  GError *error = NULL;
-
-  /* Return FALSE if we are already aborting */
-  if (!self->init_task)
-    return FALSE;
-
-  wp_proxy_augment_finish (proxy, res, &error);
-  if (error) {
-    g_warning ("WpPipewireSimpleEndpoint:%p Aborting construction", self);
-    g_task_return_error (self->init_task, error);
-    g_clear_object (&self->init_task);
-    return FALSE;
-  }
-
-  return TRUE;
-}
-
-static void
-node_proxy_param (WpProxy *proxy, int seq, uint32_t id,
-    uint32_t index, uint32_t next, const struct spa_pod *param,
-    WpPipewireSimpleEndpoint *self)
-{
-  switch (id) {
-    case SPA_PARAM_Props:
-    {
-      struct spa_pod_prop *prop;
-      struct spa_pod_object *obj = (struct spa_pod_object *) param;
-      float volume = self->volume;
-      bool mute = self->mute;
-
-      SPA_POD_OBJECT_FOREACH(obj, prop) {
-        switch (prop->key) {
-        case SPA_PROP_volume:
-          spa_pod_get_float(&prop->value, &volume);
-          break;
-        case SPA_PROP_mute:
-          spa_pod_get_bool(&prop->value, &mute);
-          break;
-        default:
-          break;
-        }
-      }
-
-      g_debug ("WpEndpoint:%p param event, vol:(%lf -> %f) mute:(%d -> %d)",
-          self, self->volume, volume, self->mute, mute);
-
-      if (self->volume != volume) {
-        self->volume = volume;
-        wp_endpoint_notify_control_value (WP_ENDPOINT (self), CONTROL_VOLUME);
-      }
-      if (self->mute != mute) {
-        self->mute = mute;
-        wp_endpoint_notify_control_value (WP_ENDPOINT (self), CONTROL_MUTE);
-      }
-
-      break;
-    }
-    default:
-      break;
-  }
-}
-
-static void
-on_all_ports_done (WpProxy *proxy, GAsyncResult *res,
-    WpPipewireSimpleEndpoint *self)
-{
-  GError *error = NULL;
-
-  /* return if already aborted */
-  if (!self->init_task)
-    return;
-
-  wp_proxy_sync_finish (proxy, res, &error);
-
-  if (error)
-    g_task_return_error (self->init_task, error);
-  else
-    g_task_return_boolean (self->init_task, TRUE);
-
-  g_clear_object(&self->init_task);
-}
-
-static void
-on_proxy_port_augmented (WpProxy *proxy, GAsyncResult *res,
-    WpPipewireSimpleEndpoint *self)
-{
-  if (!proxy_safe_augment_finish (self, proxy, res))
-    return;
-
-  /* Add the proxy port to the array */
-  g_ptr_array_add(self->proxies_port, g_object_ref (proxy));
-
-  /* Sync with the server and use the task data as a flag to know
-     whether we already called sync or not */
-  if (!g_task_get_task_data (self->init_task)) {
-    wp_proxy_sync (WP_PROXY(self->proxy_node), NULL,
-        (GAsyncReadyCallback) on_all_ports_done, self);
-    g_task_set_task_data (self->init_task, GUINT_TO_POINTER (1), NULL);
-  }
-}
-
-static void
-on_port_added (WpCore *core, WpProxy *proxy, gpointer d)
-{
-  WpPipewireSimpleEndpoint *self = d;
-  const char *s;
-  guint node_id = 0;
-  g_autoptr (WpProperties) props = wp_proxy_get_global_properties (proxy);
-
-  /* Don't do anything if we are aborting */
-  if (!self->init_task)
-    return;
-
-  if ((s = wp_properties_get (props, PW_KEY_NODE_ID)))
-    node_id = atoi(s);
-
-  /* Only handle ports owned by this endpoint */
-  if (node_id != wp_proxy_get_global_id (WP_PROXY (self->proxy_node)))
-    return;
-
-  /* Augment */
-  wp_proxy_augment (proxy, WP_PROXY_FEATURE_PW_PROXY | WP_PROXY_FEATURE_INFO,
-      NULL, (GAsyncReadyCallback) on_proxy_port_augmented, self);
-}
-
-static void
-emit_endpoint_ports(WpPipewireSimpleEndpoint *self)
-{
-  enum pw_direction direction = wp_endpoint_get_direction (WP_ENDPOINT (self));
-  struct spa_audio_info_raw format = { 0, };
-  struct spa_pod *param;
-  char buf[1024];
-  struct spa_pod_builder pod_builder = SPA_POD_BUILDER_INIT(buf, sizeof(buf));
-
-  /* The default format for audio clients */
-  format.format = SPA_AUDIO_FORMAT_F32P;
-  format.flags = 1;
-  format.rate = 48000;
-  format.channels = 2;
-  format.position[0] = SPA_AUDIO_CHANNEL_FL;
-  format.position[1] = SPA_AUDIO_CHANNEL_FR;
-
-  /* Build the param profile */
-  param = spa_format_audio_raw_build(&pod_builder, SPA_PARAM_Format, &format);
-  param = spa_pod_builder_add_object(&pod_builder,
-      SPA_TYPE_OBJECT_ParamPortConfig,  SPA_PARAM_PortConfig,
-      SPA_PARAM_PORT_CONFIG_direction,  SPA_POD_Id(direction),
-      SPA_PARAM_PORT_CONFIG_mode,       SPA_POD_Id(SPA_PARAM_PORT_CONFIG_MODE_dsp),
-      SPA_PARAM_PORT_CONFIG_format,     SPA_POD_Pod(param));
-
-  /* Set the param profile to emit the ports */
-  wp_proxy_node_set_param (self->proxy_node, SPA_PARAM_PortConfig, 0, param);
-}
-
-static void
-on_proxy_node_augmented (WpProxy *proxy, GAsyncResult *res, gpointer data)
-{
-  WpPipewireSimpleEndpoint *self = data;
-  GVariantDict d;
-  g_autoptr (WpProperties) props = NULL;
-
-  if (!proxy_safe_augment_finish (self, proxy, res))
-    return;
-
-  props = wp_proxy_node_get_properties (self->proxy_node);
-
-  /* Set the role and target name */
-  self->role = g_strdup (wp_properties_get (props, PW_KEY_MEDIA_ROLE));
-  self->target = g_strdup (wp_properties_get (props, "target.name"));
-
-  /* Emit the ports */
-  emit_endpoint_ports(self);
-
-  g_signal_connect (self->proxy_node, "param", (GCallback) node_proxy_param,
-      self);
-  wp_proxy_node_subscribe_params (self->proxy_node, 1, SPA_PARAM_Props);
-
-  g_variant_dict_init (&d, NULL);
-  g_variant_dict_insert (&d, "id", "u", 0);
-  g_variant_dict_insert (&d, "name", "s", "default");
-  wp_endpoint_register_stream (WP_ENDPOINT (self), g_variant_dict_end (&d));
-
-  /* Audio streams have volume & mute controls */
-  if (g_strrstr (wp_endpoint_get_media_class (WP_ENDPOINT (self)), "Audio")) {
-    g_variant_dict_init (&d, NULL);
-    g_variant_dict_insert (&d, "id", "u", CONTROL_VOLUME);
-    g_variant_dict_insert (&d, "stream-id", "u", 0);
-    g_variant_dict_insert (&d, "name", "s", "volume");
-    g_variant_dict_insert (&d, "type", "s", "d");
-    g_variant_dict_insert (&d, "range", "(dd)", 0.0, 1.0);
-    g_variant_dict_insert (&d, "default-value", "d", 1.0);
-    wp_endpoint_register_control (WP_ENDPOINT (self), g_variant_dict_end (&d));
-
-    g_variant_dict_init (&d, NULL);
-    g_variant_dict_insert (&d, "id", "u", CONTROL_MUTE);
-    g_variant_dict_insert (&d, "stream-id", "u", 0);
-    g_variant_dict_insert (&d, "name", "s", "mute");
-    g_variant_dict_insert (&d, "type", "s", "b");
-    g_variant_dict_insert (&d, "default-value", "b", FALSE);
-    wp_endpoint_register_control (WP_ENDPOINT (self), g_variant_dict_end (&d));
-  }
-}
-
-static void
-wp_simple_endpoint_init_async (GAsyncInitable *initable, int io_priority,
-    GCancellable *cancellable, GAsyncReadyCallback callback, gpointer data)
-{
-  WpPipewireSimpleEndpoint *self = WP_PIPEWIRE_SIMPLE_ENDPOINT (initable);
-  g_autoptr (WpCore) core = wp_endpoint_get_core(WP_ENDPOINT(self));
-
-  /* Create the async task */
-  self->init_task = g_task_new (initable, cancellable, callback, data);
-
-  /* Register a port_added callback */
-  g_signal_connect_object (core, "remote-global-added::port",
-      (GCallback) on_port_added, self, 0);
-
-  /* Augment to get the info */
-  wp_proxy_augment (WP_PROXY (self->proxy_node),
-      WP_PROXY_FEATURE_PW_PROXY | WP_PROXY_FEATURE_INFO, cancellable,
-      (GAsyncReadyCallback) on_proxy_node_augmented, self);
-
-  /* Call the parent interface */
-  wp_simple_endpoint_parent_interface->init_async (initable, io_priority,
-      cancellable, callback, data);
-}
-
-static void
-wp_simple_endpoint_async_initable_init (gpointer iface, gpointer iface_data)
-{
-  GAsyncInitableIface *ai_iface = iface;
-
-  /* Set the parent interface */
-  wp_simple_endpoint_parent_interface = g_type_interface_peek_parent (iface);
-
-  /* Only set the init_async */
-  ai_iface->init_async = wp_simple_endpoint_init_async;
-}
-
-static void
-simple_endpoint_init (WpPipewireSimpleEndpoint * self)
-{
-  self->creation_time = (guint64) g_get_monotonic_time ();
-  self->proxies_port = g_ptr_array_new_full(2, (GDestroyNotify)g_object_unref);
-}
-
-static void
-simple_endpoint_finalize (GObject * object)
-{
-  WpPipewireSimpleEndpoint *self = WP_PIPEWIRE_SIMPLE_ENDPOINT (object);
-
-  /* Destroy the proxies port */
-  g_clear_pointer (&self->proxies_port, g_ptr_array_unref);
-
-  /* Destroy the proxy node */
-  g_clear_object(&self->proxy_node);
-
-  /* Destroy the done task */
-  g_clear_object(&self->init_task);
-
-  g_free (self->role);
-
-  G_OBJECT_CLASS (simple_endpoint_parent_class)->finalize (object);
-}
-
-static void
-simple_endpoint_set_property (GObject * object, guint property_id,
-    const GValue * value, GParamSpec * pspec)
-{
-  WpPipewireSimpleEndpoint *self = WP_PIPEWIRE_SIMPLE_ENDPOINT (object);
-
-  switch (property_id) {
-  case PROP_PROXY_NODE:
-    self->proxy_node = g_value_dup_object (value);
-    break;
-  case PROP_ROLE:
-    g_free (self->role);
-    self->role = g_value_dup_string (value);
-    break;
-  case PROP_TARGET:
-    g_free (self->target);
-    self->target = g_value_dup_string (value);
-    break;
-  default:
-    G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
-    break;
-  }
-}
-
-static void
-simple_endpoint_get_property (GObject * object, guint property_id,
-    GValue * value, GParamSpec * pspec)
-{
-  WpPipewireSimpleEndpoint *self = WP_PIPEWIRE_SIMPLE_ENDPOINT (object);
-
-  switch (property_id) {
-  case PROP_PROXY_NODE:
-    g_value_set_object (value, self->proxy_node);
-    break;
-  case PROP_ROLE:
-    g_value_set_string (value, self->role);
-    break;
-  case PROP_CREATION_TIME:
-    g_value_set_uint64 (value, self->creation_time);
-    break;
-  case PROP_TARGET:
-    g_value_set_string (value, self->target);
-    break;
-  default:
-    G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
-    break;
-  }
-}
-
-static void
-proxies_port_foreach_func(gpointer data, gpointer user_data)
-{
-  GVariantBuilder *b = user_data;
-  g_variant_builder_add (b, "t", data);
-}
-
-static gboolean
-simple_endpoint_prepare_link (WpEndpoint * ep, guint32 stream_id,
-    WpEndpointLink * link, GVariant ** properties, GError ** error)
-{
-  WpPipewireSimpleEndpoint *self = WP_PIPEWIRE_SIMPLE_ENDPOINT (ep);
-  GVariantBuilder b, *b_ports;
-  GVariant *v_ports;
-
-  /* Create a variant array with all the ports */
-  b_ports = g_variant_builder_new (G_VARIANT_TYPE ("at"));
-  g_ptr_array_foreach(self->proxies_port, proxies_port_foreach_func, b_ports);
-  v_ports = g_variant_builder_end (b_ports);
-
-  /* Set the properties */
-  g_variant_builder_init (&b, G_VARIANT_TYPE_VARDICT);
-  g_variant_builder_add (&b, "{sv}", "node-id", g_variant_new_uint32 (
-          wp_proxy_get_global_id (WP_PROXY (self->proxy_node))));
-  g_variant_builder_add (&b, "{sv}", "ports", v_ports);
-  *properties = g_variant_builder_end (&b);
-
-  return TRUE;
-}
-
-static GVariant *
-simple_endpoint_get_control_value (WpEndpoint * ep, guint32 control_id)
-{
-  WpPipewireSimpleEndpoint *self = WP_PIPEWIRE_SIMPLE_ENDPOINT (ep);
-
-  switch (control_id) {
-    case CONTROL_VOLUME:
-      return g_variant_new_double (self->volume);
-    case CONTROL_MUTE:
-      return g_variant_new_boolean (self->mute);
-    default:
-      g_warning ("Unknown control id %u", control_id);
-      return NULL;
-  }
-}
-
-static gboolean
-simple_endpoint_set_control_value (WpEndpoint * ep, guint32 control_id,
-    GVariant * value)
-{
-  WpPipewireSimpleEndpoint *self = WP_PIPEWIRE_SIMPLE_ENDPOINT (ep);
-  char buf[1024];
-  struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buf, sizeof(buf));
-  float volume;
-  bool mute;
-
-  switch (control_id) {
-    case CONTROL_VOLUME:
-      volume = g_variant_get_double (value);
-
-      g_debug("WpEndpoint:%p set volume control (%u) value, vol:%f", self,
-          control_id, volume);
-
-      wp_proxy_node_set_param (self->proxy_node,
-          SPA_PARAM_Props, 0,
-          spa_pod_builder_add_object (&b,
-              SPA_TYPE_OBJECT_Props, SPA_PARAM_Props,
-              SPA_PROP_volume, SPA_POD_Float(volume),
-              NULL));
-      break;
-
-    case CONTROL_MUTE:
-      mute = g_variant_get_boolean (value);
-
-      g_debug("WpEndpoint:%p set mute control (%u) value, mute:%d", self,
-          control_id, mute);
-
-      wp_proxy_node_set_param (self->proxy_node,
-          SPA_PARAM_Props, 0,
-          spa_pod_builder_add_object (&b,
-              SPA_TYPE_OBJECT_Props, SPA_PARAM_Props,
-              SPA_PROP_mute, SPA_POD_Bool(mute),
-              NULL));
-      break;
-
-    default:
-      g_warning ("Unknown control id %u", control_id);
-      return FALSE;
-  }
-
-  return TRUE;
-}
-
-static void
-simple_endpoint_class_init (WpPipewireSimpleEndpointClass * klass)
-{
-  GObjectClass *object_class = (GObjectClass *) klass;
-  WpEndpointClass *endpoint_class = (WpEndpointClass *) klass;
-
-  object_class->finalize = simple_endpoint_finalize;
-  object_class->set_property = simple_endpoint_set_property;
-  object_class->get_property = simple_endpoint_get_property;
-
-  endpoint_class->prepare_link = simple_endpoint_prepare_link;
-  endpoint_class->get_control_value = simple_endpoint_get_control_value;
-  endpoint_class->set_control_value = simple_endpoint_set_control_value;
-
-  g_object_class_install_property (object_class, PROP_PROXY_NODE,
-      g_param_spec_object ("proxy-node", "proxy-node",
-          "The node this endpoint refers to", WP_TYPE_PROXY_NODE,
-          G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
-  g_object_class_install_property (object_class, PROP_ROLE,
-      g_param_spec_string ("role", "role", "The role of the wrapped node", NULL,
-          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-  g_object_class_install_property (object_class, PROP_CREATION_TIME,
-      g_param_spec_uint64 ("creation-time", "creation-time",
-          "The time that this endpoint was created, in monotonic time",
-          0, G_MAXUINT64, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
-  g_object_class_install_property (object_class, PROP_TARGET,
-      g_param_spec_string ("target", "target", "The target of the wrapped node", NULL,
-          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-}
-
-void
-simple_endpoint_factory (WpFactory * factory, GType type,
-    GVariant * properties, GAsyncReadyCallback ready, gpointer user_data)
-{
-  g_autoptr (WpCore) core = NULL;
-  const gchar *name, *media_class;
-  guint direction;
-  guint64 node;
-
-  /* Make sure the type is correct */
-  g_return_if_fail (type == WP_TYPE_ENDPOINT);
-
-  /* Get the Core */
-  core = wp_factory_get_core (factory);
-  g_return_if_fail (core);
-
-  /* Get the properties */
-  if (!g_variant_lookup (properties, "name", "&s", &name))
-      return;
-  if (!g_variant_lookup (properties, "media-class", "&s", &media_class))
-      return;
-  if (!g_variant_lookup (properties, "direction", "u", &direction))
-      return;
-  if (!g_variant_lookup (properties, "proxy-node", "t", &node))
-      return;
-
-  g_async_initable_new_async (
-      simple_endpoint_get_type (), G_PRIORITY_DEFAULT, NULL, ready, user_data,
-      "core", core,
-      "name", name,
-      "media-class", media_class,
-      "direction", direction,
-      "proxy-node", (gpointer) node,
-      NULL);
-}
diff --git a/modules/module-pw-audio-client.c b/modules/module-pw-audio-client.c
index 089d4eb59c66a61aafba503dfd082227ffef93c9..7528a759dbc70a47f8b7b1d1319b899bf39834d4 100644
--- a/modules/module-pw-audio-client.c
+++ b/modules/module-pw-audio-client.c
@@ -95,7 +95,7 @@ on_node_added (WpCore *core, WpProxy *proxy, gpointer d)
   endpoint_props = g_variant_builder_end (&b);
 
   /* Create the endpoint async */
-  wp_factory_make (core, "pipewire-simple-endpoint", WP_TYPE_ENDPOINT,
+  wp_factory_make (core, "pw-audio-softdsp-endpoint", WP_TYPE_ENDPOINT,
       endpoint_props, on_endpoint_created, data);
 }
 
diff --git a/modules/module-pw-audio-softdsp-endpoint.c b/modules/module-pw-audio-softdsp-endpoint.c
index 81a3451d8550c80886f5a6e1160f7a5049261cd4..606c2e0f7e85ba3730f7b6f378ef0802e87d0fd8 100644
--- a/modules/module-pw-audio-softdsp-endpoint.c
+++ b/modules/module-pw-audio-softdsp-endpoint.c
@@ -34,6 +34,7 @@ struct _WpPwAudioSoftdspEndpoint
   /* Properties */
   WpProxyNode *proxy_node;
   GVariant *streams;
+  char *role;
 
   guint stream_count;
   gboolean selected;
@@ -50,6 +51,7 @@ enum {
   PROP_0,
   PROP_PROXY_NODE,
   PROP_STREAMS,
+  PROP_ROLE,
 };
 
 static GAsyncInitableIface *wp_endpoint_parent_interface = NULL;
@@ -96,6 +98,10 @@ endpoint_prepare_link (WpEndpoint * ep, guint32 stream_id,
   WpPwAudioSoftdspEndpoint *self = WP_PW_AUDIO_SOFTDSP_ENDPOINT (ep);
   WpAudioStream *stream = NULL;
 
+  /* Link with the adapter if stream id is none */
+  if (stream_id == WP_STREAM_ID_NONE)
+    return wp_audio_stream_prepare_link (self->adapter, properties, error);
+
   /* Make sure the stream Id is valid */
   g_return_val_if_fail(stream_id < self->converters->len, FALSE);
 
@@ -180,6 +186,13 @@ on_audio_adapter_created(GObject *initable, GAsyncResult *res,
     g_object_set (self, "name", name, NULL);
   }
 
+  /* Set the role */
+  self->role = g_strdup (wp_properties_get (props, PW_KEY_MEDIA_ROLE));
+
+  /* Just finish if no streams need to be created */
+  if (!self->streams)
+    return finish_endpoint_creation (self);
+
   /* Create the audio converters */
   g_variant_iter_init (&iter, self->streams);
   for (i = 0; g_variant_iter_next (&iter, "&s", &stream); i++) {
@@ -212,6 +225,7 @@ endpoint_finalize (GObject * object)
   g_clear_object(&self->init_task);
 
   g_clear_object(&self->proxy_node);
+  g_free (self->role);
 
   G_OBJECT_CLASS (endpoint_parent_class)->finalize (object);
 }
@@ -229,6 +243,10 @@ endpoint_set_property (GObject * object, guint property_id,
   case PROP_STREAMS:
     self->streams = g_value_dup_variant(value);
     break;
+  case PROP_ROLE:
+    g_free (self->role);
+    self->role = g_value_dup_string (value);
+    break;
   default:
     G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
     break;
@@ -248,6 +266,9 @@ endpoint_get_property (GObject * object, guint property_id,
   case PROP_STREAMS:
     g_value_set_variant (value, self->streams);
     break;
+  case PROP_ROLE:
+    g_value_set_string (value, self->role);
+    break;
   default:
     G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
     break;
@@ -376,6 +397,10 @@ endpoint_class_init (WpPwAudioSoftdspEndpointClass * klass)
           "The stream names for the streams to create",
           G_VARIANT_TYPE ("as"), NULL,
           G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
+
+  g_object_class_install_property (object_class, PROP_ROLE,
+      g_param_spec_string ("role", "role", "The role of the wrapped node", NULL,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 }
 
 void
@@ -404,9 +429,8 @@ endpoint_factory (WpFactory * factory, GType type, GVariant * properties,
       return;
   if (!g_variant_lookup (properties, "proxy-node", "t", &node))
       return;
-  if (!(streams = g_variant_lookup_value (properties, "streams",
-          G_VARIANT_TYPE ("as"))))
-      return;
+  streams = g_variant_lookup_value (properties, "streams",
+      G_VARIANT_TYPE ("as"));
 
   /* Create and return the softdsp endpoint object */
   g_async_initable_new_async (
diff --git a/modules/module-pw-audio-softdsp-endpoint/adapter.c b/modules/module-pw-audio-softdsp-endpoint/adapter.c
index 371d241e82811fb805f1298c5e0f943fc901feca..84cfc51269efb5d5ab34da74584d74a1ce6eccfe 100644
--- a/modules/module-pw-audio-softdsp-endpoint/adapter.c
+++ b/modules/module-pw-audio-softdsp-endpoint/adapter.c
@@ -35,49 +35,36 @@ G_DEFINE_TYPE_WITH_CODE (WpAudioAdapter, wp_audio_adapter, WP_TYPE_AUDIO_STREAM,
                            wp_audio_adapter_async_initable_init))
 
 static void
-on_proxy_enum_format_done (WpProxyNode *proxy, GAsyncResult *res,
-    WpAudioAdapter *self)
+wp_audio_adapter_init_async (GAsyncInitable *initable, int io_priority,
+    GCancellable *cancellable, GAsyncReadyCallback callback, gpointer data)
 {
-  g_autoptr (GPtrArray) formats = NULL;
-  g_autoptr (GError) error = NULL;
+  WpAudioAdapter *self = WP_AUDIO_ADAPTER(initable);
   enum pw_direction direction =
       wp_audio_stream_get_direction (WP_AUDIO_STREAM (self));
   uint8_t buf[1024];
   struct spa_pod_builder pod_builder = SPA_POD_BUILDER_INIT(buf, sizeof(buf));
   struct spa_pod *param;
-  uint32_t media_type, media_subtype;
   struct spa_audio_info_raw fmt_raw;
 
-  formats = wp_proxy_node_enum_params_collect_finish (proxy, res, &error);
-  if (error) {
-    g_message("WpAudioAdapter:%p enum format error: %s", self, error->message);
-    wp_audio_stream_init_task_finish (WP_AUDIO_STREAM (self),
-        g_steal_pointer (&error));
-    return;
-  }
-
-  if (formats->len == 0 ||
-      !(param = g_ptr_array_index (formats, 0)) ||
-      spa_format_parse (param, &media_type, &media_subtype) < 0 ||
-      media_type != SPA_MEDIA_TYPE_audio ||
-      media_subtype != SPA_MEDIA_SUBTYPE_raw) {
-    g_message("WpAudioAdapter:%p node does not support audio/raw format", self);
-    wp_audio_stream_init_task_finish (WP_AUDIO_STREAM (self),
-        g_error_new (WP_DOMAIN_LIBRARY, WP_LIBRARY_ERROR_OPERATION_FAILED,
-            "node does not support audio/raw format"));
-    return;
-  }
-
-  /* Parse the raw audio format */
-  spa_pod_fixate (param);
-  spa_format_audio_raw_parse (param, &fmt_raw);
+  /* Call the parent interface */
+  /* This will also augment the proxy and therefore bind it */
+  wp_audio_adapter_parent_interface->init_async (initable, io_priority,
+      cancellable, callback, data);
 
+  /* Emit the ports */
   if (self->convert) {
     param = spa_pod_builder_add_object(&pod_builder,
         SPA_TYPE_OBJECT_ParamPortConfig,  SPA_PARAM_PortConfig,
         SPA_PARAM_PORT_CONFIG_direction,  SPA_POD_Id(direction),
         SPA_PARAM_PORT_CONFIG_mode,       SPA_POD_Id(SPA_PARAM_PORT_CONFIG_MODE_convert));
   } else {
+    /* Use the default format */
+    fmt_raw.format = SPA_AUDIO_FORMAT_F32P;
+    fmt_raw.flags = 1;
+    fmt_raw.rate = 48000;
+    fmt_raw.channels = 2;
+    fmt_raw.position[0] = SPA_AUDIO_CHANNEL_FL;
+    fmt_raw.position[1] = SPA_AUDIO_CHANNEL_FR;
     param = spa_format_audio_raw_build(&pod_builder, SPA_PARAM_Format, &fmt_raw);
     param = spa_pod_builder_add_object(&pod_builder,
         SPA_TYPE_OBJECT_ParamPortConfig,  SPA_PARAM_PortConfig,
@@ -85,26 +72,9 @@ on_proxy_enum_format_done (WpProxyNode *proxy, GAsyncResult *res,
         SPA_PARAM_PORT_CONFIG_mode,       SPA_POD_Id(SPA_PARAM_PORT_CONFIG_MODE_dsp),
         SPA_PARAM_PORT_CONFIG_format,     SPA_POD_Pod(param));
   }
-
   wp_audio_stream_set_port_config (WP_AUDIO_STREAM (self), param);
 }
 
-static void
-wp_audio_adapter_init_async (GAsyncInitable *initable, int io_priority,
-    GCancellable *cancellable, GAsyncReadyCallback callback, gpointer data)
-{
-  WpAudioAdapter *self = WP_AUDIO_ADAPTER(initable);
-  WpProxyNode *proxy = wp_audio_stream_get_proxy_node (WP_AUDIO_STREAM (self));
-
-  /* Call the parent interface */
-  /* This will also augment the proxy and therefore bind it */
-  wp_audio_adapter_parent_interface->init_async (initable, io_priority,
-      cancellable, callback, data);
-
-  wp_proxy_node_enum_params_collect (proxy, SPA_PARAM_EnumFormat, NULL, NULL,
-      (GAsyncReadyCallback) on_proxy_enum_format_done, self);
-}
-
 static void
 wp_audio_adapter_async_initable_init (gpointer iface, gpointer iface_data)
 {
diff --git a/modules/module-simple-policy.c b/modules/module-simple-policy.c
index 7e413387bff57d7209e8368d71d257e23d616715..d02057bac2e0d91beae77665de5b95f7b0ae0da5 100644
--- a/modules/module-simple-policy.c
+++ b/modules/module-simple-policy.c
@@ -372,10 +372,10 @@ link_endpoint (WpPolicy *policy, WpEndpoint *ep, GVariant *target_props)
 
   /* Link the endpoint with the target */
   if (is_capture) {
-    wp_endpoint_link_new (core, target, stream_id, ep, 0,
+    wp_endpoint_link_new (core, target, stream_id, ep, WP_STREAM_ID_NONE,
         on_endpoint_link_created, NULL);
   } else {
-    wp_endpoint_link_new (core, ep, 0, target, stream_id,
+    wp_endpoint_link_new (core, ep, WP_STREAM_ID_NONE, target, stream_id,
         on_endpoint_link_created, NULL);
   }
 
@@ -388,7 +388,7 @@ handle_client (WpPolicy *policy, WpEndpoint *ep)
   const char *media_class = wp_endpoint_get_media_class(ep);
   GVariantDict d;
   gboolean is_capture = FALSE;
-  const gchar *role, *target_name = NULL;
+  const gchar *role;
 
   /* Detect if the client is doing capture or playback */
   is_capture = g_str_has_prefix (media_class, "Stream/Input");
@@ -424,9 +424,6 @@ handle_client (WpPolicy *policy, WpEndpoint *ep)
   g_object_get (ep, "role", &role, NULL);
   if (role)
     g_variant_dict_insert (&d, "media.role", "s", role);
-  g_object_get (ep, "target", &target_name, NULL);
-  if (target_name)
-    g_variant_dict_insert (&d, "media.name", "s", target_name);
   if (!link_endpoint (policy, ep, g_variant_dict_end (&d)))
     g_info ("Could not find alsa target endpoint for client stream");
 }
@@ -504,18 +501,6 @@ compare_client_priority (gconstpointer a, gconstpointer b, gpointer user_data)
     ret = b_priority - a_priority;
   }
 
-  /* when role priority is equal, the newest client wins */
-  if (ret == 0) {
-    guint64 a_time = 0, b_time = 0;
-
-    g_object_get (ae, "creation-time", &a_time, NULL);
-    g_object_get (be, "creation-time", &b_time, NULL);
-
-    /* since a_time and b_time are expressed in system monotonic time,
-     * there is absolutely no chance that they will be equal */
-    ret = (b_time > a_time) ? 1 : -1;
-  }
-
   return ret;
 }
 
@@ -653,7 +638,6 @@ simple_policy_find_endpoint (WpPolicy *policy, GVariant *props,
   g_autoptr (WpCore) core = NULL;
   g_autoptr (GPtrArray) ptr_array = NULL;
   const char *action = NULL;
-  const char *name = NULL;
   const char *media_class = NULL;
   const char *role = NULL;
   WpEndpoint *ep;
@@ -662,7 +646,6 @@ simple_policy_find_endpoint (WpPolicy *policy, GVariant *props,
   core = wp_policy_get_core (policy);
 
   g_variant_lookup (props, "action", "&s", &action);
-  g_variant_lookup (props, "media.name", "&s", &name);
 
   /* Get all the endpoints with the specific media class*/
   g_variant_lookup (props, "media.class", "&s", &media_class);
@@ -670,16 +653,10 @@ simple_policy_find_endpoint (WpPolicy *policy, GVariant *props,
   if (!ptr_array)
     return NULL;
 
-  /* Find the endpoint with the matching name, otherwise get the one with the
-   * "selected" flag (if it is an alsa endpoint) */
+  /* Get the endpoint with the "selected" flag (if it is an alsa endpoint) */
   for (i = 0; i < ptr_array->len; i++) {
     ep = g_ptr_array_index (ptr_array, i);
-    if (name) {
-      if (g_str_has_prefix(wp_endpoint_get_name (ep), name)) {
-        g_object_ref (ep);
-        goto select_stream;
-      }
-    } else if (g_str_has_prefix (media_class, "Alsa/")) {
+    if (g_str_has_prefix (media_class, "Alsa/")) {
       g_autoptr (GVariant) value = NULL;
       guint id;