Merge branch 'alsa-endpoints' of gitlab.freedesktop.org:julian/wireplumber
This commit is contained in:
@@ -46,7 +46,7 @@ wp_factory_class_init (WpFactoryClass * klass)
|
|||||||
WpFactory *
|
WpFactory *
|
||||||
wp_factory_new (WpCore * core, const gchar * name, WpFactoryFunc func)
|
wp_factory_new (WpCore * core, const gchar * name, WpFactoryFunc func)
|
||||||
{
|
{
|
||||||
g_autoptr (WpFactory) f = NULL;
|
WpFactory *f = NULL;
|
||||||
|
|
||||||
g_return_val_if_fail (name != NULL && *name != '\0', NULL);
|
g_return_val_if_fail (name != NULL && *name != '\0', NULL);
|
||||||
g_return_val_if_fail (func != NULL, NULL);
|
g_return_val_if_fail (func != NULL, NULL);
|
||||||
|
@@ -44,6 +44,8 @@ simple_endpoint_link_create (WpEndpointLink * self, GVariant * src_data,
|
|||||||
GVariant * sink_data, GError ** error)
|
GVariant * sink_data, GError ** error)
|
||||||
{
|
{
|
||||||
/* TODO create pw_links based on the nodes & ports described in src/sink_data */
|
/* TODO create pw_links based on the nodes & ports described in src/sink_data */
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@@ -95,6 +95,8 @@ simple_endpoint_prepare_link (WpEndpoint * self, guint32 stream_id,
|
|||||||
{
|
{
|
||||||
/* TODO: verify that the remote end supports the same media type */
|
/* TODO: verify that the remote end supports the same media type */
|
||||||
/* TODO: fill @properties with (node id, array(port ids)) */
|
/* TODO: fill @properties with (node id, array(port ids)) */
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@@ -14,7 +14,143 @@
|
|||||||
#include <wp/wp.h>
|
#include <wp/wp.h>
|
||||||
#include <pipewire/pipewire.h>
|
#include <pipewire/pipewire.h>
|
||||||
|
|
||||||
|
#define NAME "module-pw-alsa-udev"
|
||||||
|
|
||||||
|
struct impl {
|
||||||
|
WpCore *wp_core;
|
||||||
|
|
||||||
|
struct pw_remote *remote;
|
||||||
|
struct spa_hook remote_listener;
|
||||||
|
|
||||||
|
struct pw_registry_proxy *registry_proxy;
|
||||||
|
struct spa_hook registry_listener;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
handle_node(struct impl *impl, uint32_t id, uint32_t parent_id,
|
||||||
|
const struct spa_dict *props)
|
||||||
|
{
|
||||||
|
const gchar *media_class = NULL, *node_name = NULL;
|
||||||
|
struct spa_proxy *proxy = NULL;
|
||||||
|
GVariantBuilder b;
|
||||||
|
g_autoptr(GVariant) endpoint_props = NULL;
|
||||||
|
|
||||||
|
/* Make sure the node has properties */
|
||||||
|
if (!props) {
|
||||||
|
g_warning(NAME" %p: node has no properties, skipping...", impl);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make sure the media class is audio */
|
||||||
|
/* FIXME: need to handle only alsa nodes */
|
||||||
|
media_class = spa_dict_lookup(props, "media.class");
|
||||||
|
if (!g_str_has_prefix (media_class, "Audio/"))
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Get the device name */
|
||||||
|
node_name = spa_dict_lookup(props, "node.name");
|
||||||
|
|
||||||
|
/* Get the proxy */
|
||||||
|
proxy = pw_registry_proxy_bind (impl->registry_proxy, id,
|
||||||
|
PW_TYPE_INTERFACE_Node, PW_VERSION_NODE, 0);
|
||||||
|
|
||||||
|
/* Build the GVariant properties for the endpoint */
|
||||||
|
g_variant_builder_init (&b, G_VARIANT_TYPE_VARDICT);
|
||||||
|
g_variant_builder_add (&b, "{sv}", "name",
|
||||||
|
g_variant_new_take_string (g_strdup_printf ("Endpoint %u: %s", id, node_name)));
|
||||||
|
g_variant_builder_add (&b, "{sv}",
|
||||||
|
"media-class", g_variant_new_string (media_class));
|
||||||
|
g_variant_builder_add (&b, "{sv}",
|
||||||
|
"node-proxy", g_variant_new_uint64 ((guint64) proxy));
|
||||||
|
endpoint_props = g_variant_builder_end (&b);
|
||||||
|
|
||||||
|
/* Create the endpoint */
|
||||||
|
wp_factory_make (impl->wp_core, "pw-audio-softdsp-endpoint", WP_TYPE_ENDPOINT,
|
||||||
|
endpoint_props);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
registry_global(void *data,uint32_t id, uint32_t parent_id,
|
||||||
|
uint32_t permissions, uint32_t type, uint32_t version,
|
||||||
|
const struct spa_dict *props)
|
||||||
|
{
|
||||||
|
struct impl *impl = data;
|
||||||
|
|
||||||
|
/* Only handle nodes */
|
||||||
|
switch (type) {
|
||||||
|
case PW_TYPE_INTERFACE_Node:
|
||||||
|
handle_node(impl, id, parent_id, props);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct pw_registry_proxy_events registry_events = {
|
||||||
|
PW_VERSION_REGISTRY_PROXY_EVENTS,
|
||||||
|
.global = registry_global,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void on_state_changed(void *_data, enum pw_remote_state old,
|
||||||
|
enum pw_remote_state state, const char *error)
|
||||||
|
{
|
||||||
|
struct impl *impl = _data;
|
||||||
|
struct pw_core_proxy *core_proxy;
|
||||||
|
|
||||||
|
switch (state) {
|
||||||
|
case PW_REMOTE_STATE_CONNECTED:
|
||||||
|
core_proxy = pw_remote_get_core_proxy (impl->remote);
|
||||||
|
impl->registry_proxy = pw_core_proxy_get_registry (core_proxy,
|
||||||
|
PW_TYPE_INTERFACE_Registry, PW_VERSION_REGISTRY, 0);
|
||||||
|
pw_registry_proxy_add_listener(impl->registry_proxy,
|
||||||
|
&impl->registry_listener, ®istry_events, impl);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PW_REMOTE_STATE_ERROR:
|
||||||
|
/* TODO quit wireplumber */
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PW_REMOTE_STATE_UNCONNECTED:
|
||||||
|
/* TODO quit wireplumber */
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct pw_remote_events remote_events = {
|
||||||
|
PW_VERSION_REMOTE_EVENTS,
|
||||||
|
.state_changed = on_state_changed,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
module_destroy (gpointer data)
|
||||||
|
{
|
||||||
|
struct impl *impl = data;
|
||||||
|
|
||||||
|
g_debug ("module-pipewire destroy");
|
||||||
|
|
||||||
|
g_slice_free (struct impl, impl);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
wireplumber__module_init (WpModule * module, WpCore * core, GVariant * args)
|
wireplumber__module_init (WpModule * module, WpCore * core, GVariant * args)
|
||||||
{
|
{
|
||||||
|
/* This needs to create the alsa sink and alsa source nodes, but since
|
||||||
|
* this is already implemented in the alsa-module of pipewire, for now
|
||||||
|
* we just listen for the alsa nodes created by pipewire. We eventually
|
||||||
|
* need to move all the node creation logic here */
|
||||||
|
|
||||||
|
/* Create the impl */
|
||||||
|
struct impl *impl = g_new0(struct impl, 1);
|
||||||
|
impl->wp_core = core;
|
||||||
|
impl->remote = wp_core_get_global(core, WP_GLOBAL_PW_REMOTE);
|
||||||
|
|
||||||
|
/* Set destroy callback for impl */
|
||||||
|
wp_module_set_destroy_callback (module, module_destroy, impl);
|
||||||
|
|
||||||
|
/* Add a state changed listener */
|
||||||
|
pw_remote_add_listener(impl->remote, &impl->remote_listener, &remote_events, impl);
|
||||||
}
|
}
|
||||||
|
@@ -35,6 +35,7 @@ static gboolean
|
|||||||
endpoint_prepare_link (WpEndpoint * self, guint32 stream_id,
|
endpoint_prepare_link (WpEndpoint * self, guint32 stream_id,
|
||||||
WpEndpointLink * link, GVariant ** properties, GError ** error)
|
WpEndpointLink * link, GVariant ** properties, GError ** error)
|
||||||
{
|
{
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -48,13 +49,22 @@ endpoint_class_init (WpPwAudioSoftdspEndpointClass * klass)
|
|||||||
static gpointer
|
static gpointer
|
||||||
endpoint_factory (WpFactory * factory, GType type, GVariant * properties)
|
endpoint_factory (WpFactory * factory, GType type, GVariant * properties)
|
||||||
{
|
{
|
||||||
|
const gchar *name = NULL;
|
||||||
|
const gchar *media_class = NULL;
|
||||||
|
|
||||||
if (type != WP_TYPE_ENDPOINT)
|
if (type != WP_TYPE_ENDPOINT)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/* TODO: retrieve pw_node* from @properties and keep it
|
/* Get the name and media-class */
|
||||||
* TODO: populate media_class and name on the endpoint
|
if (!g_variant_lookup (properties, "name", "&s", &name))
|
||||||
*/
|
return NULL;
|
||||||
return g_object_new (endpoint_get_type (), NULL);
|
if (!g_variant_lookup (properties, "media-class", "&s", &media_class))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return g_object_new (endpoint_get_type (),
|
||||||
|
"name", name,
|
||||||
|
"media-class", media_class,
|
||||||
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
Reference in New Issue
Block a user