diff --git a/modules/module-config-endpoint/context.c b/modules/module-config-endpoint/context.c
index d11e8212dcda0d070902c9cf12f05f6bb5891fcc..809b42e70b5a5aa4cb2f07101796a9d0e38b0865 100644
--- a/modules/module-config-endpoint/context.c
+++ b/modules/module-config-endpoint/context.c
@@ -14,6 +14,8 @@
 #include "parser-streams.h"
 #include "context.h"
 
+G_DEFINE_QUARK (wp-module-config-endpoint-context-session, session);
+
 struct _WpConfigEndpointContext
 {
   GObject parent;
@@ -21,8 +23,9 @@ struct _WpConfigEndpointContext
   /* Props */
   GWeakRef core;
 
-  WpObjectManager *om;
-  GHashTable *registered_endpoints;
+  WpObjectManager *sessions_om;
+  WpObjectManager *nodes_om;
+  GHashTable *endpoints;
 };
 
 enum {
@@ -40,63 +43,52 @@ static guint signals[N_SIGNALS];
 G_DEFINE_TYPE (WpConfigEndpointContext, wp_config_endpoint_context,
     G_TYPE_OBJECT)
 
-static void
-on_endpoint_created (GObject *initable, GAsyncResult *res, gpointer d)
-{
-  WpConfigEndpointContext *self = d;
-  g_autoptr (WpBaseEndpoint) endpoint = NULL;
-  g_autoptr (WpProxy) proxy = NULL;
-  guint global_id = 0;
-  GError *error = NULL;
-
-  /* Get the endpoint */
-  endpoint = wp_base_endpoint_new_finish (initable, res, &error);
-  if (error) {
-    g_warning ("Failed to create endpoint: %s", error->message);
-    return;
-  }
-
-  /* Get the endpoint global id */
-  g_object_get (endpoint, "node", &proxy, NULL);
-  global_id = wp_proxy_get_bound_id (proxy);
-
-  /* Register the endpoint and add it to the table */
-  wp_base_endpoint_register (endpoint);
-  g_hash_table_insert (self->registered_endpoints, GUINT_TO_POINTER (global_id),
-      g_object_ref (endpoint));
-
-  /* Emit the endpoint-created signal */
-  g_signal_emit (self, signals[SIGNAL_ENDPOINT_CREATED], 0, endpoint);
-}
-
-static GVariant *
-create_streams_variant (WpConfiguration *config, const char *streams)
+static const struct WpParserStreamsData *
+get_streams_data (WpConfiguration *config, const char *file_name)
 {
   g_autoptr (WpConfigParser) parser = NULL;
-  const struct WpParserStreamsData *streams_data = NULL;
-  g_autoptr (GVariantBuilder) ba = NULL;
 
-  if (!streams || !config)
-    return NULL;
+  g_return_val_if_fail (config, 0);
+  g_return_val_if_fail (file_name, 0);
 
   /* Get the streams parser */
   parser = wp_configuration_get_parser (config, WP_PARSER_STREAMS_EXTENSION);
   if (!parser)
-    return NULL;
+    return 0;
 
   /* Get the streams data */
-  streams_data = wp_config_parser_get_matched_data (parser, (gpointer)streams);
-  if (!streams_data || streams_data->n_streams <= 0)
-    return NULL;
-
-  /* Build the variant array with the stream name and priority */
-  ba = g_variant_builder_new (G_VARIANT_TYPE ("a(su)"));
-  g_variant_builder_init (ba, G_VARIANT_TYPE_ARRAY);
-  for (guint i = 0; i < streams_data->n_streams; i++)
-    g_variant_builder_add (ba, "(su)", streams_data->streams[i].name,
-        streams_data->streams[i].priority);
-
-  return g_variant_new ("a(su)", ba);
+  return wp_config_parser_get_matched_data (parser, (gpointer)file_name);
+}
+
+static void
+endpoint_export_finish_cb (WpSessionItem * ep, GAsyncResult * res,
+    WpConfigEndpointContext * self)
+{
+  g_autoptr (GError) error = NULL;
+  gboolean export_ret = wp_session_item_export_finish (ep, res, &error);
+  g_return_if_fail (error == NULL);
+  g_return_if_fail (export_ret);
+
+  /* Emit the signal */
+  g_signal_emit (self, signals[SIGNAL_ENDPOINT_CREATED], 0, ep);
+}
+
+static void
+endpoint_activate_finish_cb (WpSessionItem * ep, GAsyncResult * res,
+    WpConfigEndpointContext * self)
+{
+  WpSession * session = NULL;
+  g_autoptr (GError) error = NULL;
+  gboolean activate_ret = wp_session_item_activate_finish (ep, res, &error);
+  g_return_if_fail (error == NULL);
+  g_return_if_fail (activate_ret);
+
+  /* Get the session */
+  session = g_object_get_qdata (G_OBJECT (ep), session_quark ());
+  g_return_if_fail (session);
+
+  wp_session_item_export (ep, WP_SESSION (session),
+      (GAsyncReadyCallback) endpoint_export_finish_cb, self);
 }
 
 static void
@@ -106,74 +98,141 @@ on_node_added (WpObjectManager *om, WpProxy *proxy, gpointer d)
   g_autoptr (WpCore) core = g_weak_ref_get (&self->core);
   g_autoptr (WpConfiguration) config = wp_configuration_get_instance (core);
   g_autoptr (WpProperties) props = wp_proxy_get_properties (proxy);
+  g_autoptr (WpSessionItem) ep = NULL;
+  g_autoptr (WpSessionItem) streams_ep = NULL;
+  g_autoptr (WpSession) session = NULL;
   g_autoptr (WpConfigParser) parser = NULL;
   const struct WpParserEndpointData *endpoint_data = NULL;
-  GVariantBuilder b;
-  g_autoptr (GVariant) endpoint_props = NULL;
-  const char *media_class = NULL, *name = NULL;
-  g_autoptr (GVariant) streams_variant = NULL;
+  const struct WpParserStreamsData *streams_data = NULL;
 
   /* Skip nodes with no media class (JACK Clients) */
-  media_class = wp_properties_get (props, PW_KEY_MEDIA_CLASS);
-  if (!media_class)
+  if (!wp_properties_get (props, PW_KEY_MEDIA_CLASS))
     return;
 
-  /* Get the linked and ep streams data */
+  /* Get the endpoint configuration data */
   parser = wp_configuration_get_parser (config, WP_PARSER_ENDPOINT_EXTENSION);
   endpoint_data = wp_config_parser_get_matched_data (parser, proxy);
   if (!endpoint_data)
     return;
 
-  /* Set the name if it is null */
-  name = endpoint_data->e.name;
-  if (!name)
-    name = wp_properties_get (props, PW_KEY_NODE_NAME);
-
-  /* Set the media class if it is null */
-  if (endpoint_data->e.media_class)
-    media_class = endpoint_data->e.media_class;
-
-  /* Create the streams variant */
-  streams_variant = create_streams_variant (config, endpoint_data->e.streams);
-
-  /* Set the properties */
-  g_variant_builder_init (&b, G_VARIANT_TYPE_VARDICT);
-  g_variant_builder_add (&b, "{sv}",
-      "name", g_variant_new_take_string (g_strdup_printf ("%s", name)));
-  g_variant_builder_add (&b, "{sv}",
-      "media-class", g_variant_new_string (media_class));
-  g_variant_builder_add (&b, "{sv}",
-      "direction", g_variant_new_uint32 (endpoint_data->e.direction));
-  g_variant_builder_add (&b, "{sv}",
-      "priority", g_variant_new_uint32 (endpoint_data->e.priority));
-  g_variant_builder_add (&b, "{sv}",
-      "node", g_variant_new_uint64 ((guint64) proxy));
-  if (streams_variant)
-    g_variant_builder_add (&b, "{sv}", "streams",
-        g_steal_pointer (&streams_variant));
-  endpoint_props = g_variant_builder_end (&b);
-
-  /* Create the endpoint async */
-  wp_factory_make (core, endpoint_data->e.type, WP_TYPE_BASE_ENDPOINT,
-      endpoint_props, on_endpoint_created, self);
+  /* Get the session */
+  session = wp_object_manager_lookup (self->sessions_om, WP_TYPE_SESSION,
+      WP_CONSTRAINT_TYPE_PW_PROPERTY, "session.name", "=s",
+      endpoint_data->e.session, NULL);
+  if (!session) {
+    wp_warning_object (self, "could not find session for endpoint");
+    return;
+  }
+
+  /* Get the streams data */
+  streams_data = endpoint_data->e.streams ?
+      get_streams_data (config, endpoint_data->e.streams) : NULL;
+
+  /* Create the endpoint */
+  ep = wp_session_item_make (core, endpoint_data->e.type);
+  if (!ep) {
+    wp_warning_object (self, "could not create endpoint of type %s",
+        endpoint_data->e.type);
+    return;
+  }
+
+  /* Configure the endpoint */
+  {
+    g_auto (GVariantBuilder) b =
+        G_VARIANT_BUILDER_INIT (G_VARIANT_TYPE_VARDICT);
+    g_variant_builder_add (&b, "{sv}", "node",
+      g_variant_new_uint64 ((guint64) proxy));
+
+    if (endpoint_data->e.c.name)
+      g_variant_builder_add (&b, "{sv}", "name",
+          g_variant_new_string (endpoint_data->e.c.name));
+
+    if (endpoint_data->e.c.media_class)
+      g_variant_builder_add (&b, "{sv}", "media-class",
+          g_variant_new_string (endpoint_data->e.c.media_class));
+
+    if (endpoint_data->e.c.role)
+      g_variant_builder_add (&b, "{sv}", "role",
+          g_variant_new_string (endpoint_data->e.c.role));
+
+    g_variant_builder_add (&b, "{sv}", "priority",
+        g_variant_new_uint32 (endpoint_data->e.c.priority));
+
+    g_variant_builder_add (&b, "{sv}", "enable-control-port",
+        g_variant_new_boolean (endpoint_data->e.c.enable_control_port));
+
+    g_variant_builder_add (&b, "{sv}", "enable-monitor",
+        g_variant_new_boolean (endpoint_data->e.c.enable_monitor));
+
+    wp_session_item_configure (ep, g_variant_builder_end (&b));
+  }
+
+  /* TODO: for now we always create softdsp audio endpoints if streams data is
+   * valid. However, this will need to change once we have video endpoints. */
+  if (streams_data) {
+    /* Create the steams endpoint */
+    streams_ep = wp_session_item_make (core, "si-audio-softdsp-endpoint");
+
+    /* Configure the streams endpoint */
+    {
+      g_auto (GVariantBuilder) b =
+          G_VARIANT_BUILDER_INIT (G_VARIANT_TYPE_VARDICT);
+      g_variant_builder_add (&b, "{sv}", "adapter",
+          g_variant_new_uint64 ((guint64) ep));
+      wp_session_item_configure (streams_ep, g_variant_builder_end (&b));
+    }
+
+    /* Add the streams */
+    for (guint i = 0; i < streams_data->n_streams; i++) {
+      const struct WpParserStreamsStreamData *sd = streams_data->streams + i;
+      g_autoptr (WpSessionItem) stream =
+          wp_session_item_make (core, "si-convert");
+      {
+        g_auto (GVariantBuilder) b =
+            G_VARIANT_BUILDER_INIT (G_VARIANT_TYPE_VARDICT);
+        g_variant_builder_add (&b, "{sv}", "target",
+            g_variant_new_uint64 ((guint64) ep));
+        g_variant_builder_add (&b, "{sv}", "name",
+            g_variant_new_string (sd->name));
+        g_variant_builder_add (&b, "{sv}", "enable-control-port",
+            g_variant_new_boolean (sd->enable_control_port));
+        wp_session_item_configure (stream, g_variant_builder_end (&b));
+      }
+
+      wp_session_bin_add (WP_SESSION_BIN (streams_ep), g_steal_pointer (&stream));
+    }
+  }
+
+  /* Activate endpoint */
+  g_object_set_qdata_full (
+      G_OBJECT (streams_data ? streams_ep : ep), session_quark (),
+      g_steal_pointer (&session), g_object_unref);
+  wp_session_item_activate (streams_data ? streams_ep : ep,
+      (GAsyncReadyCallback) endpoint_activate_finish_cb, self);
+
+  /* Insert the endpoint */
+  g_hash_table_insert (self->endpoints, proxy,
+      streams_data ? g_steal_pointer (&streams_ep) : g_steal_pointer (&ep));
 }
 
 static void
-on_node_removed (WpObjectManager *om, WpProxy *proxy, gpointer d)
+on_sessions_changed (WpObjectManager *om, gpointer d)
 {
   WpConfigEndpointContext *self = d;
-  WpBaseEndpoint *endpoint = NULL;
-  guint32 id = wp_proxy_get_bound_id (proxy);
+  g_autoptr (WpCore) core = g_weak_ref_get (&self->core);
+  g_return_if_fail (core);
 
-  /* Get the endpoint */
-  endpoint = g_hash_table_lookup (self->registered_endpoints,
-      GUINT_TO_POINTER(id));
-  if (!endpoint)
-    return;
+  /* Handle node-added signal and install the nodes object manager */
+  wp_object_manager_add_interest_1 (self->nodes_om, WP_TYPE_NODE, NULL);
+  wp_object_manager_request_proxy_features (self->nodes_om, WP_TYPE_NODE,
+      WP_PROXY_FEATURES_STANDARD);
+  g_signal_connect_object (self->nodes_om, "object-added",
+      G_CALLBACK (on_node_added), self, 0);
+  wp_core_install_object_manager (core, self->nodes_om);
 
-  /* Unregister the endpoint and remove it from the table */
-  wp_base_endpoint_unregister (endpoint);
-  g_hash_table_remove (self->registered_endpoints, GUINT_TO_POINTER(id));
+  /* Remove handler */
+  g_signal_handlers_disconnect_by_func (self->sessions_om,
+      on_sessions_changed, d);
 }
 
 static void
@@ -195,8 +254,13 @@ wp_config_endpoint_context_constructed (GObject * object)
   wp_configuration_reload (config, WP_PARSER_ENDPOINT_EXTENSION);
   wp_configuration_reload (config, WP_PARSER_STREAMS_EXTENSION);
 
-  /* Install the object manager */
-  wp_core_install_object_manager (core, self->om);
+  /* Handle sessions-changed signal and install the session object manager */
+  wp_object_manager_add_interest_1 (self->sessions_om, WP_TYPE_SESSION, NULL);
+  wp_object_manager_request_proxy_features (self->sessions_om, WP_TYPE_SESSION,
+      WP_PROXY_FEATURES_STANDARD);
+  g_signal_connect_object (self->sessions_om, "objects-changed",
+      G_CALLBACK (on_sessions_changed), self, 0);
+  wp_core_install_object_manager (core, self->sessions_om);
 
   G_OBJECT_CLASS (wp_config_endpoint_context_parent_class)->constructed (object);
 }
@@ -246,8 +310,9 @@ wp_config_endpoint_context_finalize (GObject *object)
   }
   g_weak_ref_clear (&self->core);
 
-  g_clear_object (&self->om);
-  g_clear_pointer (&self->registered_endpoints, g_hash_table_unref);
+  g_clear_pointer (&self->endpoints, g_hash_table_unref);
+  g_clear_object (&self->sessions_om);
+  g_clear_object (&self->nodes_om);
 
   G_OBJECT_CLASS (wp_config_endpoint_context_parent_class)->finalize (object);
 }
@@ -255,20 +320,10 @@ wp_config_endpoint_context_finalize (GObject *object)
 static void
 wp_config_endpoint_context_init (WpConfigEndpointContext *self)
 {
-  self->om = wp_object_manager_new ();
-  self->registered_endpoints = g_hash_table_new_full (g_direct_hash,
-      g_direct_equal, NULL, (GDestroyNotify) g_object_unref);
-
-  /* Only handle augmented nodes with info set */
-  wp_object_manager_add_interest_1 (self->om, WP_TYPE_NODE, NULL);
-  wp_object_manager_request_proxy_features (self->om, WP_TYPE_NODE,
-      WP_PROXY_FEATURES_STANDARD);
-
-  /* Register the global added/removed callbacks */
-  g_signal_connect(self->om, "object-added",
-      (GCallback) on_node_added, self);
-  g_signal_connect(self->om, "object-removed",
-      (GCallback) on_node_removed, self);
+  self->nodes_om = wp_object_manager_new ();
+  self->sessions_om = wp_object_manager_new ();
+  self->endpoints = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL,
+      (GDestroyNotify) g_object_unref);
 }
 
 static void
@@ -290,7 +345,7 @@ wp_config_endpoint_context_class_init (WpConfigEndpointContextClass *klass)
   /* Signals */
   signals[SIGNAL_ENDPOINT_CREATED] = g_signal_new ("endpoint-created",
       G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL,
-      G_TYPE_NONE, 1, WP_TYPE_ENDPOINT);
+      G_TYPE_NONE, 1, WP_TYPE_SESSION_ITEM);
 }
 
 WpConfigEndpointContext *
@@ -300,10 +355,3 @@ wp_config_endpoint_context_new (WpCore *core)
     "core", core,
     NULL);
 }
-
-guint
-wp_config_endpoint_context_get_length (WpConfigEndpointContext *self)
-{
-  g_return_val_if_fail (WP_IS_CONFIG_ENDPOINT_CONTEXT (self), 0);
-  return g_hash_table_size (self->registered_endpoints);
-}
diff --git a/modules/module-config-endpoint/context.h b/modules/module-config-endpoint/context.h
index 1336546c29dfac1cd877603a1ab0d714def83b84..b09e98ab4660d9343894673ef94fe9060dc2be4c 100644
--- a/modules/module-config-endpoint/context.h
+++ b/modules/module-config-endpoint/context.h
@@ -19,8 +19,6 @@ G_DECLARE_FINAL_TYPE (WpConfigEndpointContext, wp_config_endpoint_context,
 
 WpConfigEndpointContext * wp_config_endpoint_context_new (WpCore *core);
 
-guint wp_config_endpoint_context_get_length (WpConfigEndpointContext *self);
-
 G_END_DECLS
 
 #endif
diff --git a/modules/module-config-endpoint/parser-endpoint.c b/modules/module-config-endpoint/parser-endpoint.c
index c9c5d5d85ebd9f6f61d5e4ec00f82ab7eb2c394b..32b3afea9de03b4cdeda1691f427ca3a58eec81e 100644
--- a/modules/module-config-endpoint/parser-endpoint.c
+++ b/modules/module-config-endpoint/parser-endpoint.c
@@ -32,14 +32,14 @@ wp_parser_endpoint_data_destroy (gpointer p)
 {
   struct WpParserEndpointData *data = p;
 
-  /* Free the strings */
   g_clear_pointer (&data->filename, g_free);
   g_clear_pointer (&data->mn.props, wp_properties_unref);
-  g_clear_pointer (&data->e.name, g_free);
-  g_clear_pointer (&data->e.media_class, g_free);
-  g_clear_pointer (&data->e.props, wp_properties_unref);
+  g_clear_pointer (&data->e.session, g_free);
   g_clear_pointer (&data->e.type, g_free);
   g_clear_pointer (&data->e.streams, g_free);
+  g_clear_pointer (&data->e.c.name, g_free);
+  g_clear_pointer (&data->e.c.media_class, g_free);
+  g_clear_pointer (&data->e.c.role, g_free);
 
   g_slice_free (struct WpParserEndpointData, data);
 }
@@ -76,25 +76,12 @@ parse_properties (WpTomlTable *table, const char *name)
   return props;
 }
 
-static guint
-parse_endpoint_direction (const char *direction)
-{
-  if (g_strcmp0 (direction, "sink") == 0)
-    return PW_DIRECTION_INPUT;
-  else if (g_strcmp0 (direction, "source") == 0)
-    return PW_DIRECTION_OUTPUT;
-
-  g_return_val_if_reached (PW_DIRECTION_INPUT);
-}
-
 static struct WpParserEndpointData *
 wp_parser_endpoint_data_new (const gchar *location)
 {
   g_autoptr (WpTomlFile) file = NULL;
-  g_autoptr (WpTomlTable) table = NULL, mn = NULL, e = NULL;
-  g_autoptr (WpTomlArray) streams = NULL;
+  g_autoptr (WpTomlTable) table = NULL, mn = NULL, e = NULL, c = NULL;
   struct WpParserEndpointData *res = NULL;
-  g_autofree char *direction = NULL;
 
   /* File format:
    * ------------
@@ -102,13 +89,17 @@ wp_parser_endpoint_data_new (const gchar *location)
    * properties (WpProperties)
    *
    * [endpoint]
+   * session (string)
+   * type (string)
+   * streams (string)
+   *
+   * [endpoint.config]
    * name (string)
    * media_class (string)
-   * direction (string)
+   * role (string)
    * priority (uint32)
-   * properties (WpProperties)
-   * type (string)
-   * streams (string)
+   * enable_control_port (bool)
+   * enable_monitor (bool)
    */
 
   /* Get the TOML file */
@@ -140,33 +131,33 @@ wp_parser_endpoint_data_new (const gchar *location)
   if (!e)
     goto error;
 
-  /* Get the name from the endpoint table */
-  res->e.name = wp_toml_table_get_string (e, "name");
-
-  /* Get the media class from the endpoint table */
-  res->e.media_class = wp_toml_table_get_string (e, "media_class");
-
-  /* Get the direction from the endpoint table */
-  direction = wp_toml_table_get_string (e, "direction");
-  if (!direction)
+  /* Get the endpoint session */
+  res->e.session = wp_toml_table_get_string (e, "session");
+  if (!res->e.session)
     goto error;
-  res->e.direction = parse_endpoint_direction (direction);
-
-  /* Get the priority from the endpoint table */
-  res->e.priority = 0;
-  wp_toml_table_get_uint32 (e, "priority", &res->e.priority);
-
-  /* Get the endpoint properties */
-  res->e.props = parse_properties (e, "properties");
 
   /* Get the endpoint type */
   res->e.type = wp_toml_table_get_string (e, "type");
   if (!res->e.type)
     goto error;
 
-  /* Get the endpoint streams */
+  /* Get the optional streams */
   res->e.streams = wp_toml_table_get_string (e, "streams");
 
+  /* Get the optional endpoint config table */
+  c = wp_toml_table_get_table (e, "config");
+  if (c) {
+    res->e.c.name = wp_toml_table_get_string (c, "name");
+    res->e.c.media_class = wp_toml_table_get_string (c, "media_class");
+    res->e.c.role = wp_toml_table_get_string (c, "role");
+    res->e.c.priority = 0;
+    wp_toml_table_get_uint32 (c, "priority", &res->e.c.priority);
+    res->e.c.enable_control_port = FALSE;
+    wp_toml_table_get_boolean (c, "enable-control-port", &res->e.c.enable_control_port);
+    res->e.c.enable_monitor = FALSE;
+    wp_toml_table_get_boolean (c, "enable-monitor", &res->e.c.enable_monitor);
+  }
+
   return res;
 
 error:
@@ -193,7 +184,7 @@ wp_parser_endpoint_add_file (WpConfigParser *parser,
   /* Parse the file */
   data = wp_parser_endpoint_data_new (name);
   if (!data) {
-    g_warning ("Failed to parse configuration file '%s'", name);
+    wp_warning_object (parser, "Failed to parse configuration file '%s'", name);
     return FALSE;
   }
 
diff --git a/modules/module-config-endpoint/parser-endpoint.h b/modules/module-config-endpoint/parser-endpoint.h
index a24a41d7fdc0fc983b83e1560424adbdc2f5345f..bdc93805098858f4ef642fd7f7b357408752df66 100644
--- a/modules/module-config-endpoint/parser-endpoint.h
+++ b/modules/module-config-endpoint/parser-endpoint.h
@@ -21,13 +21,18 @@ struct WpParserEndpointData {
     WpProperties *props;
   } mn;
   struct Endpoint {
-    char *name;
-    char *media_class;
-    guint direction;
-    guint priority;
-    WpProperties *props;
+    char *session;
     char *type;
     char *streams;
+    struct Config {
+      char *name;
+      char *media_class;
+      char *role;
+      guint priority;
+      gboolean enable_control_port;
+      gboolean enable_monitor;
+      guint direction;
+    } c;
   } e;
 };
 
diff --git a/modules/module-config-endpoint/parser-streams.c b/modules/module-config-endpoint/parser-streams.c
index b1c718aa53484e1c8a66e9301e90b2b4ef20de74..a611a73be17e94c2d517d5ac208d59c29275469e 100644
--- a/modules/module-config-endpoint/parser-streams.c
+++ b/modules/module-config-endpoint/parser-streams.c
@@ -97,6 +97,11 @@ streams_for_each (const WpTomlTable *table, gpointer user_data)
   stream->priority = 0;
   wp_toml_table_get_uint32 (table, "priority", &stream->priority);
 
+  /* Parse the optional enable_control_port */
+  stream->enable_control_port = FALSE;
+  wp_toml_table_get_boolean (table, "enable_control_port",
+      &stream->enable_control_port);
+
   /* Increment the number of streams */
   data->n_streams++;
 }
@@ -115,6 +120,7 @@ wp_parser_streams_data_new (const gchar *location)
    * [[streams]]
    * name (string)
    * priority (uint32)
+   * enable_control_port (bool)
    */
 
   /* Get the TOML file */
@@ -152,7 +158,7 @@ wp_parser_streams_add_file (WpConfigParser *parser,
   /* Parse the file */
   data = wp_parser_streams_data_new (name);
   if (!data) {
-    g_warning ("Failed to parse configuration file '%s'", name);
+    wp_warning_object (parser, "Failed to parse configuration file '%s'", name);
     return FALSE;
   }
 
diff --git a/modules/module-config-endpoint/parser-streams.h b/modules/module-config-endpoint/parser-streams.h
index 75c6209bf63844f0ea29ea347fb432e0823fa3ef..821e1db1b88ba420885afa8bd84d29bbecb48237 100644
--- a/modules/module-config-endpoint/parser-streams.h
+++ b/modules/module-config-endpoint/parser-streams.h
@@ -21,6 +21,7 @@ G_BEGIN_DECLS
 struct WpParserStreamsStreamData {
   char *name;
   guint priority;
+  gboolean enable_control_port;
 };
 
 struct WpParserStreamsData {
diff --git a/tests/modules/config-endpoint.c b/tests/modules/config-endpoint.c
index 94ad755d65e14dd0ac8e231989d1a3d30e8b0513..bd3411bad193cc0c396e155e53ad9bc631a0c861 100644
--- a/tests/modules/config-endpoint.c
+++ b/tests/modules/config-endpoint.c
@@ -7,7 +7,6 @@
  */
 
 #include "../common/base-test-fixture.h"
-#include "config-endpoint/endpoint-audiotestsrc.h"
 #include "../../modules/module-config-endpoint/context.h"
 
 typedef struct {
@@ -15,64 +14,183 @@ typedef struct {
 } TestConfigEndpointFixture;
 
 static void
-config_endpoint_setup (TestConfigEndpointFixture *self, gconstpointer data)
+config_endpoint_setup (TestConfigEndpointFixture *f, gconstpointer data)
 {
-  wp_base_test_fixture_setup (&self->base, 0);
-
-  /* load audiotestsrc */
-  pw_thread_loop_lock (self->base.server.thread_loop);
-  pw_context_add_spa_lib (self->base.server.context, "audiotestsrc",
-      "audiotestsrc/libspa-audiotestsrc");
-  if (!pw_context_load_module (self->base.server.context,
-        "libpipewire-module-spa-node", "audiotestsrc", NULL)) {
-    pw_thread_loop_unlock (self->base.server.thread_loop);
-    g_test_skip ("audiotestsrc SPA plugin is not installed");
-    return;
-  }
-  pw_thread_loop_unlock (self->base.server.thread_loop);
+  wp_base_test_fixture_setup (&f->base, 0);
+
+  /* load modules */
+  {
+    g_autoptr (WpTestServerLocker) lock =
+        wp_test_server_locker_new (&f->base.server);
 
-  /* Register the wp-endpoint-audiotestsrc */
-  wp_factory_new (self->base.core, "wp-endpoint-audiotestsrc",
-      wp_endpoint_audiotestsrc_factory);
+    g_assert_cmpint (pw_context_add_spa_lib (f->base.server.context,
+            "audiotestsrc", "audiotestsrc/libspa-audiotestsrc"), ==, 0);
+    g_assert_nonnull (pw_context_load_module (f->base.server.context,
+            "libpipewire-module-spa-node-factory", NULL, NULL));
+    g_assert_nonnull (pw_context_load_module (f->base.server.context,
+            "libpipewire-module-adapter", NULL, NULL));
+  }
+  {
+    g_autoptr (GError) error = NULL;
+    WpModule *module = wp_module_load (f->base.core, "C",
+        "libwireplumber-module-si-simple-node-endpoint", NULL, &error);
+    g_assert_no_error (error);
+    g_assert_nonnull (module);
+  }
+  {
+    g_autoptr (GError) error = NULL;
+    WpModule *module = wp_module_load (f->base.core, "C",
+        "libwireplumber-module-si-adapter", NULL, &error);
+    g_assert_no_error (error);
+    g_assert_nonnull (module);
+  }
+  {
+    g_autoptr (GError) error = NULL;
+    WpModule *module = wp_module_load (f->base.core, "C",
+        "libwireplumber-module-si-convert", NULL, &error);
+    g_assert_no_error (error);
+    g_assert_nonnull (module);
+  }
+  {
+    g_autoptr (GError) error = NULL;
+    WpModule *module = wp_module_load (f->base.core, "C",
+        "libwireplumber-module-si-audio-softdsp-endpoint", NULL, &error);
+    g_assert_no_error (error);
+    g_assert_nonnull (module);
+  }
 }
 
 static void
-config_endpoint_teardown (TestConfigEndpointFixture *self, gconstpointer data)
+config_endpoint_teardown (TestConfigEndpointFixture *f, gconstpointer data)
 {
-  wp_base_test_fixture_teardown (&self->base);
+  wp_base_test_fixture_teardown (&f->base);
 }
 
 static void
-on_audiotestsrc_created (WpConfigEndpointContext *ctx, WpEndpoint *ep,
+on_default_session_exported (WpProxy * session, GAsyncResult * res,
     TestConfigEndpointFixture *f)
 {
+  g_autoptr (GError) error = NULL;
+  g_assert_true (wp_proxy_augment_finish (session, res, &error));
+  g_assert_no_error (error);
+  g_assert_true (WP_IS_IMPL_SESSION (session));
+  g_main_loop_quit (f->base.loop);
+}
+
+static void
+on_audiotestsrc_simple_endpoint_created (WpConfigEndpointContext *ctx,
+    WpSessionItem *ep, TestConfigEndpointFixture *f)
+{
+  g_autoptr (WpNode) node = NULL;
+  g_autoptr (WpProperties) props = NULL;
   g_assert_nonnull (ep);
+
+  g_autoptr (GVariant) v = wp_session_item_get_configuration (ep);
+  const gchar *str;
+  guint32 prio;
+  g_assert_true (g_variant_lookup (v, "name", "&s", &str));
+  g_assert_cmpstr (str, ==, "audiotestsrc-endpoint");
+  g_assert_true (g_variant_lookup (v, "media-class", "&s", &str));
+  g_assert_cmpstr (str, ==, "Audio/Source");
+  g_assert_true (g_variant_lookup (v, "role", "&s", &str));
+  g_assert_cmpstr (str, ==, "Multimedia");
+  g_assert_true (g_variant_lookup (v, "priority", "u", &prio));
+  g_assert_cmpuint (prio, ==, 0);
+
   g_main_loop_quit (f->base.loop);
 }
 
 static void
-basic (TestConfigEndpointFixture *f, gconstpointer data)
+on_audiotestsrc_streams_endpoint_created (WpConfigEndpointContext *ctx,
+    WpSessionItem *ep, TestConfigEndpointFixture *f)
+{
+  g_assert_nonnull (ep);
+  g_assert_cmpuint (5, ==, wp_session_bin_get_n_children (WP_SESSION_BIN (ep)));
+
+  g_autoptr (GVariant) v = wp_session_item_get_configuration (ep);
+  guint64 p_i;
+  g_assert_true (g_variant_lookup (v, "adapter", "t", &p_i));
+  g_assert_nonnull ((gpointer)p_i);
+
+  g_autoptr (GVariant) v2 = wp_session_item_get_configuration ((gpointer)p_i);
+  const gchar *str;
+  guint32 prio;
+  g_assert_true (g_variant_lookup (v2, "name", "&s", &str));
+  g_assert_cmpstr (str, ==, "audiotestsrc-endpoint");
+  g_assert_true (g_variant_lookup (v2, "media-class", "&s", &str));
+  g_assert_cmpstr (str, ==, "Audio/Source");
+  g_assert_true (g_variant_lookup (v2, "role", "&s", &str));
+  g_assert_cmpstr (str, ==, "Multimedia");
+  g_assert_true (g_variant_lookup (v2, "priority", "u", &prio));
+  g_assert_cmpuint (prio, ==, 0);
+
+  g_main_loop_quit (f->base.loop);
+}
+
+static void
+simple (TestConfigEndpointFixture *f, gconstpointer data)
 {
   /* Set the configuration path */
   g_autoptr (WpConfiguration) config = wp_configuration_get_instance (f->base.core);
   g_assert_nonnull (config);
-  wp_configuration_add_path (config, "config-endpoint/basic");
+  wp_configuration_add_path (config, "config-endpoint/simple");
 
-  /* Create the context and handle the endpoint-created callback */
+  /* Create the endpoint context and handle the endpoint-created callback */
   g_autoptr (WpConfigEndpointContext) ctx =
       wp_config_endpoint_context_new (f->base.core);
   g_assert_nonnull (ctx);
-  g_assert_cmpint (wp_config_endpoint_context_get_length (ctx), ==, 0);
+  g_signal_connect (ctx, "endpoint-created",
+      (GCallback) on_audiotestsrc_simple_endpoint_created, f);
+
+  /* Create and export the default session */
+  g_autoptr (WpImplSession) session = wp_impl_session_new (f->base.core);
+  wp_impl_session_set_property (session, "session.name", "default");
+  wp_proxy_augment (WP_PROXY (session), WP_PROXY_FEATURE_BOUND, NULL,
+      (GAsyncReadyCallback) on_default_session_exported, f);
+  g_main_loop_run (f->base.loop);
 
-  /* Add a handler to stop the main loop when the endpoint is created */
+  /* Create the audiotestsrc node and run until the endpoint is created */
+  g_autoptr (WpNode) node = wp_node_new_from_factory (f->base.core,
+      "spa-node-factory",
+      wp_properties_new (
+          "factory.name", "audiotestsrc",
+          "node.name", "audiotestsrc0",
+          NULL));
+  g_assert_nonnull (node);
+  g_main_loop_run (f->base.loop);
+}
+
+static void
+streams (TestConfigEndpointFixture *f, gconstpointer data)
+{
+  /* Set the configuration path */
+  g_autoptr (WpConfiguration) config = wp_configuration_get_instance (f->base.core);
+  g_assert_nonnull (config);
+  wp_configuration_add_path (config, "config-endpoint/streams");
+
+  /* Create the endpoint context and handle the endpoint-created callback */
+  g_autoptr (WpConfigEndpointContext) ctx =
+      wp_config_endpoint_context_new (f->base.core);
+  g_assert_nonnull (ctx);
   g_signal_connect (ctx, "endpoint-created",
-      (GCallback) on_audiotestsrc_created, f);
+      (GCallback) on_audiotestsrc_streams_endpoint_created, f);
 
-  /* Run the main loop */
+  /* Create and export the default session */
+  g_autoptr (WpImplSession) session = wp_impl_session_new (f->base.core);
+  wp_impl_session_set_property (session, "session.name", "default");
+  wp_proxy_augment (WP_PROXY (session), WP_PROXY_FEATURE_BOUND, NULL,
+      (GAsyncReadyCallback) on_default_session_exported, f);
   g_main_loop_run (f->base.loop);
 
-  /* Check if the endpoint was created */
-  g_assert_cmpint (wp_config_endpoint_context_get_length (ctx), ==, 1);
+  /* create audiotestsrc adapter node and run until the endpoint is created */
+  g_autoptr (WpNode) node = wp_node_new_from_factory (f->base.core,
+      "adapter",
+      wp_properties_new (
+          "factory.name", "audiotestsrc",
+          "node.name", "adapter-audiotestsrc0",
+          NULL));
+  g_assert_nonnull (node);
+  g_main_loop_run (f->base.loop);
 }
 
 int
@@ -82,8 +200,10 @@ main (int argc, char *argv[])
   pw_init (NULL, NULL);
   g_log_set_writer_func (wp_log_writer_default, NULL, NULL);
 
-  g_test_add ("/modules/config-endpoint/basic", TestConfigEndpointFixture,
-      NULL, config_endpoint_setup, basic, config_endpoint_teardown);
+  g_test_add ("/modules/config-endpoint/simple", TestConfigEndpointFixture,
+      NULL, config_endpoint_setup, simple, config_endpoint_teardown);
+  g_test_add ("/modules/config-endpoint/streams", TestConfigEndpointFixture,
+      NULL, config_endpoint_setup, streams, config_endpoint_teardown);
 
   return g_test_run ();
 }
diff --git a/tests/modules/config-endpoint/basic/audio-source.endpoint b/tests/modules/config-endpoint/basic/audio-source.endpoint
deleted file mode 100644
index bf9fb7d11171840ed90291665065c790a09a0289..0000000000000000000000000000000000000000
--- a/tests/modules/config-endpoint/basic/audio-source.endpoint
+++ /dev/null
@@ -1,9 +0,0 @@
-[match-node]
-properties = [
-  { name = "media.class", value = "Audio/Source" },
-]
-
-[endpoint]
-direction = "source"
-type = "wp-endpoint-audiotestsrc"
-streams = "default.streams"
diff --git a/tests/modules/config-endpoint/endpoint-audiotestsrc.c b/tests/modules/config-endpoint/endpoint-audiotestsrc.c
deleted file mode 100644
index 034c086907e504adf6344196571fd81fd7336594..0000000000000000000000000000000000000000
--- a/tests/modules/config-endpoint/endpoint-audiotestsrc.c
+++ /dev/null
@@ -1,254 +0,0 @@
-/* WirePlumber
- *
- * Copyright © 2019 Collabora Ltd.
- *    @author Julian Bouzas <julian.bouzas@collabora.com>
- *
- * SPDX-License-Identifier: MIT
- */
-
-#include <wp/wp.h>
-
-#include "endpoint-audiotestsrc.h"
-
-struct _WpEndpointAudiotestsrc
-{
-  WpBaseEndpoint parent;
-  GTask *init_task;
-  guint id;
-
-  /* Props */
-  WpNode *node;
-  GVariant *streams;
-};
-
-enum {
-  PROP_0,
-  PROP_PROXY_NODE,
-  PROP_STREAMS,
-};
-
-static GAsyncInitableIface *wp_endpoint_audiotestsrc_parent_interface = NULL;
-static void wp_endpoint_audiotestsrc_async_initable_init (gpointer iface,
-    gpointer iface_data);
-
-G_DEFINE_TYPE_WITH_CODE (WpEndpointAudiotestsrc, wp_endpoint_audiotestsrc,
-    WP_TYPE_BASE_ENDPOINT,
-    G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE,
-        wp_endpoint_audiotestsrc_async_initable_init))
-
-static WpProperties *
-wp_endpoint_audiotestsrc_get_properties (WpBaseEndpoint * ep)
-{
-  WpEndpointAudiotestsrc *self = WP_ENDPOINT_AUDIOTESTSRC (ep);
-  return wp_proxy_get_properties (WP_PROXY (self->node));
-}
-
-static const char *
-wp_endpoint_audiotestsrc_get_role (WpBaseEndpoint * ep)
-{
-  return NULL;
-}
-
-static guint32
-wp_endpoint_audiotestsrc_get_global_id (WpBaseEndpoint * ep)
-{
-  WpEndpointAudiotestsrc *self = WP_ENDPOINT_AUDIOTESTSRC (ep);
-  return self->id;
-}
-
-static gboolean
-wp_endpoint_audiotestsrc_prepare_link (WpBaseEndpoint * ep, guint32 stream_id,
-    WpBaseEndpointLink * link, GVariant ** properties, GError ** error)
-{
-  return TRUE;
-}
-
-static const char *
-wp_endpoint_audiotestsrc_get_endpoint_link_factory (WpBaseEndpoint * ep)
-{
-  return NULL;
-}
-
-static void
-wp_endpoint_audiotestsrc_constructed (GObject * object)
-{
-  WpEndpointAudiotestsrc *self = WP_ENDPOINT_AUDIOTESTSRC (object);
-  GVariantDict d;
-  GVariantIter iter;
-  const gchar *stream;
-  guint priority;
-  int i;
-
-  if (self->streams) {
-    g_variant_iter_init (&iter, self->streams);
-    for (i = 0; g_variant_iter_next (&iter, "(&su)", &stream, &priority); i++) {
-      g_variant_dict_init (&d, NULL);
-      g_variant_dict_insert (&d, "id", "u", i);
-      g_variant_dict_insert (&d, "name", "s", stream);
-      g_variant_dict_insert (&d, "priority", "u", priority);
-      wp_base_endpoint_register_stream (WP_BASE_ENDPOINT (self), g_variant_dict_end (&d));
-    }
-  }
-
-  G_OBJECT_CLASS (wp_endpoint_audiotestsrc_parent_class)->constructed (object);
-}
-
-static void
-wp_endpoint_audiotestsrc_set_property (GObject * object, guint property_id,
-    const GValue * value, GParamSpec * pspec)
-{
-  WpEndpointAudiotestsrc *self = WP_ENDPOINT_AUDIOTESTSRC (object);
-
-  switch (property_id) {
-  case PROP_PROXY_NODE:
-    self->node = g_value_dup_object (value);
-    break;
-  case PROP_STREAMS:
-    self->streams = g_value_dup_variant(value);
-    break;
-  default:
-    G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
-    break;
-  }
-}
-
-static void
-wp_endpoint_audiotestsrc_get_property (GObject * object, guint property_id,
-    GValue * value, GParamSpec * pspec)
-{
-  WpEndpointAudiotestsrc *self = WP_ENDPOINT_AUDIOTESTSRC (object);
-
-  switch (property_id) {
-  case PROP_PROXY_NODE:
-    g_value_set_object (value, self->node);
-    break;
-  case PROP_STREAMS:
-    g_value_set_variant (value, self->streams);
-    break;
-  default:
-    G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
-    break;
-  }
-}
-
-static void
-wp_endpoint_audiotestsrc_finalize (GObject * object)
-{
-  WpEndpointAudiotestsrc *self = WP_ENDPOINT_AUDIOTESTSRC (object);
-
-  g_clear_object(&self->node);
-  g_clear_pointer(&self->streams, g_variant_unref);
-
-  G_OBJECT_CLASS (wp_endpoint_audiotestsrc_parent_class)->finalize (object);
-}
-
-static void
-wp_endpoint_audiotestsrc_finish_creation (WpCore *core, GAsyncResult *res,
-    WpEndpointAudiotestsrc *self)
-{
-  g_task_return_boolean (self->init_task, TRUE);
-  g_clear_object (&self->init_task);
-}
-
-static void
-wp_endpoint_audiotestsrc_init_async (GAsyncInitable *initable, int io_priority,
-    GCancellable *cancellable, GAsyncReadyCallback callback, gpointer data)
-{
-  WpEndpointAudiotestsrc *self = WP_ENDPOINT_AUDIOTESTSRC (initable);
-
-  self->init_task = g_task_new (initable, cancellable, callback, data);
-
-  wp_endpoint_audiotestsrc_parent_interface->init_async (initable, io_priority,
-      cancellable, callback, data);
-
-  g_autoptr (WpCore) core = wp_base_endpoint_get_core (WP_BASE_ENDPOINT(self));
-  g_return_if_fail (core);
-
-  wp_core_sync (core, NULL,
-      (GAsyncReadyCallback) wp_endpoint_audiotestsrc_finish_creation, self);
-}
-
-static void
-wp_endpoint_audiotestsrc_async_initable_init (gpointer iface,
-    gpointer iface_data)
-{
-  GAsyncInitableIface *ai_iface = iface;
-  wp_endpoint_audiotestsrc_parent_interface =
-      g_type_interface_peek_parent (iface);
-  ai_iface->init_async = wp_endpoint_audiotestsrc_init_async;
-}
-
-static void
-wp_endpoint_audiotestsrc_init (WpEndpointAudiotestsrc * self)
-{
-  static guint id = 0;
-  self->id = id++;
-}
-
-static void
-wp_endpoint_audiotestsrc_class_init (WpEndpointAudiotestsrcClass * klass)
-{
-  GObjectClass *object_class = (GObjectClass *) klass;
-  WpBaseEndpointClass *endpoint_class = (WpBaseEndpointClass *) klass;
-
-  object_class->constructed = wp_endpoint_audiotestsrc_constructed;
-  object_class->finalize = wp_endpoint_audiotestsrc_finalize;
-  object_class->set_property = wp_endpoint_audiotestsrc_set_property;
-  object_class->get_property = wp_endpoint_audiotestsrc_get_property;
-
-  endpoint_class->get_properties = wp_endpoint_audiotestsrc_get_properties;
-  endpoint_class->get_role = wp_endpoint_audiotestsrc_get_role;
-  endpoint_class->get_global_id = wp_endpoint_audiotestsrc_get_global_id;
-  endpoint_class->prepare_link = wp_endpoint_audiotestsrc_prepare_link;
-  endpoint_class->get_endpoint_link_factory =
-      wp_endpoint_audiotestsrc_get_endpoint_link_factory;
-
-  g_object_class_install_property (object_class, PROP_PROXY_NODE,
-      g_param_spec_object ("node", "node",
-          "The node this endpoint refers to", WP_TYPE_NODE,
-          G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
-
-  g_object_class_install_property (object_class, PROP_STREAMS,
-      g_param_spec_variant ("streams", "streams",
-          "The stream names for the streams to register",
-          G_VARIANT_TYPE ("a(su)"), NULL,
-          G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
-}
-
-void
-wp_endpoint_audiotestsrc_factory (WpFactory * factory, GType type,
-    GVariant * properties, GAsyncReadyCallback ready, gpointer data)
-{
-  g_autoptr (WpCore) core = NULL;
-  const gchar *name, *media_class;
-  guint direction, priority;
-  guint64 node;
-  g_autoptr (GVariant) streams = NULL;
-
-  core = wp_factory_get_core(factory);
-  g_return_if_fail (core);
-
-  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, "priority", "u", &priority))
-      return;
-  if (!g_variant_lookup (properties, "node", "t", &node))
-      return;
-  streams = g_variant_lookup_value (properties, "streams",
-      G_VARIANT_TYPE ("a(su)"));
-
-  g_async_initable_new_async (wp_endpoint_audiotestsrc_get_type (),
-        G_PRIORITY_DEFAULT, NULL, ready, data,
-        "core", core,
-        "name", name,
-        "media-class", media_class,
-        "direction", direction,
-        "priority", priority,
-        "node", (gpointer) node,
-        "streams", streams,
-        NULL);
-}
diff --git a/tests/modules/config-endpoint/endpoint-audiotestsrc.h b/tests/modules/config-endpoint/endpoint-audiotestsrc.h
deleted file mode 100644
index 5fa96dd7f6d7ba018e2fa64014005b201929457a..0000000000000000000000000000000000000000
--- a/tests/modules/config-endpoint/endpoint-audiotestsrc.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/* WirePlumber
- *
- * Copyright © 2019 Collabora Ltd.
- *    @author Julian Bouzas <julian.bouzas@collabora.com>
- *
- * SPDX-License-Identifier: MIT
- */
-
-#ifndef __WIREPLUMBER_ENDPOINT_AUDIOTESTSRC_H__
-#define __WIREPLUMBER_ENDPOINT_AUDIOTESTSRC_H__
-
-#include <wp/wp.h>
-
-G_BEGIN_DECLS
-
-G_DECLARE_FINAL_TYPE (WpEndpointAudiotestsrc, wp_endpoint_audiotestsrc, WP,
-    ENDPOINT_AUDIOTESTSRC, WpBaseEndpoint)
-
-void wp_endpoint_audiotestsrc_factory (WpFactory * factory, GType type,
-    GVariant * properties, GAsyncReadyCallback ready, gpointer data);
-
-G_END_DECLS
-
-#endif
diff --git a/tests/modules/config-endpoint/simple/audio-source.endpoint b/tests/modules/config-endpoint/simple/audio-source.endpoint
new file mode 100644
index 0000000000000000000000000000000000000000..3421e343587ef3ee25267ac171b3cd3bde90d984
--- /dev/null
+++ b/tests/modules/config-endpoint/simple/audio-source.endpoint
@@ -0,0 +1,14 @@
+[match-node]
+properties = [
+  { name = "media.class", value = "Audio/Source" },
+]
+
+[endpoint]
+session = "default"
+type = "si-simple-node-endpoint"
+
+[endpoint.config]
+name = "audiotestsrc-endpoint"
+media_class = "Audio/Source"
+role = "Multimedia"
+priority = 0
diff --git a/tests/modules/config-endpoint/streams/audio-source.endpoint b/tests/modules/config-endpoint/streams/audio-source.endpoint
new file mode 100644
index 0000000000000000000000000000000000000000..938cad58988a5f6e0409c26fca44a91abccb0bc7
--- /dev/null
+++ b/tests/modules/config-endpoint/streams/audio-source.endpoint
@@ -0,0 +1,15 @@
+[match-node]
+properties = [
+  { name = "media.class", value = "Audio/Source" },
+]
+
+[endpoint]
+session = "default"
+type = "si-adapter"
+streams = "default.streams"
+
+[endpoint.config]
+name = "audiotestsrc-endpoint"
+media_class = "Audio/Source"
+role = "Multimedia"
+priority = 0
diff --git a/tests/modules/config-endpoint/basic/default.streams b/tests/modules/config-endpoint/streams/default.streams
similarity index 56%
rename from tests/modules/config-endpoint/basic/default.streams
rename to tests/modules/config-endpoint/streams/default.streams
index 50cd23c79cda3678cbd094d4db3edcd756006c86..d4264c09cc1ccf747e847e4bc1e401618c97319e 100644
--- a/tests/modules/config-endpoint/basic/default.streams
+++ b/tests/modules/config-endpoint/streams/default.streams
@@ -1,15 +1,19 @@
 [[streams]]
 name = "0"
 priority = 0
+enable_control_port = false
 
 [[streams]]
 name = "2"
 priority = 2
+enable_control_port = false
 
 [[streams]]
 name = "3"
 priority = 3
+enable_control_port = false
 
 [[streams]]
 name = "4"
 priority = 4
+enable_control_port = false
diff --git a/tests/modules/meson.build b/tests/modules/meson.build
index 79f8679497345c32af4108af1bef30b4166ea40e..452e6bf543e4b5c847b67eac4f83084404db0463 100644
--- a/tests/modules/meson.build
+++ b/tests/modules/meson.build
@@ -38,7 +38,6 @@ test(
   executable('test-config-endpoint',
     [
       'config-endpoint.c',
-      'config-endpoint/endpoint-audiotestsrc.c',
       '../../modules/module-config-endpoint/parser-endpoint.c',
       '../../modules/module-config-endpoint/parser-streams.c',
       '../../modules/module-config-endpoint/context.c',