mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-03 09:01:54 -05:00
gst: rework device provider
Use the node and port info to enum formats when available. Use simple resync after each operation, when nothing is pending, loop over the results.
This commit is contained in:
parent
799fe7f90c
commit
82b0644e23
1 changed files with 80 additions and 74 deletions
|
|
@ -162,13 +162,6 @@ enum
|
|||
PROP_LAST
|
||||
};
|
||||
|
||||
struct pending {
|
||||
struct spa_list link;
|
||||
int seq;
|
||||
void (*callback) (void *data);
|
||||
void *data;
|
||||
};
|
||||
|
||||
struct core_data {
|
||||
int seq;
|
||||
GstPipeWireDeviceProvider *self;
|
||||
|
|
@ -176,7 +169,6 @@ struct core_data {
|
|||
struct pw_registry *registry;
|
||||
struct spa_hook registry_listener;
|
||||
struct spa_list nodes;
|
||||
struct spa_list ports;
|
||||
};
|
||||
|
||||
struct node_data {
|
||||
|
|
@ -189,17 +181,14 @@ struct node_data {
|
|||
struct pw_node_info *info;
|
||||
GstCaps *caps;
|
||||
GstDevice *dev;
|
||||
struct pending pending;
|
||||
};
|
||||
|
||||
struct port_data {
|
||||
struct spa_list link;
|
||||
struct node_data *node_data;
|
||||
struct pw_port *proxy;
|
||||
struct spa_hook proxy_listener;
|
||||
uint32_t id;
|
||||
struct spa_hook port_listener;
|
||||
struct pending pending;
|
||||
};
|
||||
|
||||
static struct node_data *find_node_data(struct core_data *rd, uint32_t id)
|
||||
|
|
@ -259,58 +248,40 @@ new_node (GstPipeWireDeviceProvider *self, struct node_data *data)
|
|||
return GST_DEVICE (gstdev);
|
||||
}
|
||||
|
||||
static void do_add_node(void *data)
|
||||
static void do_add_nodes(struct core_data *rd)
|
||||
{
|
||||
struct port_data *p = data;
|
||||
struct node_data *nd = p->node_data;
|
||||
GstPipeWireDeviceProvider *self = nd->self;
|
||||
GstPipeWireDeviceProvider *self = rd->self;
|
||||
struct node_data *nd;
|
||||
|
||||
if (nd->dev)
|
||||
return;
|
||||
|
||||
nd->dev = new_node (self, nd);
|
||||
if (nd->dev) {
|
||||
if(self->list_only)
|
||||
self->devices = g_list_prepend (self->devices, gst_object_ref_sink (nd->dev));
|
||||
else
|
||||
gst_device_provider_device_add (GST_DEVICE_PROVIDER (self), nd->dev);
|
||||
spa_list_for_each(nd, &rd->nodes, link) {
|
||||
if (nd->dev != NULL)
|
||||
continue;
|
||||
pw_log_info("add node %d", nd->id);
|
||||
nd->dev = new_node (self, nd);
|
||||
if (nd->dev) {
|
||||
if(self->list_only)
|
||||
self->devices = g_list_prepend (self->devices, gst_object_ref_sink (nd->dev));
|
||||
else
|
||||
gst_device_provider_device_add (GST_DEVICE_PROVIDER (self), nd->dev);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void add_pending(GstPipeWireDeviceProvider *self, struct pending *p,
|
||||
void (*callback) (void *data), void *data)
|
||||
static void resync(GstPipeWireDeviceProvider *self)
|
||||
{
|
||||
spa_list_append(&self->pending, &p->link);
|
||||
p->callback = callback;
|
||||
p->data = data;
|
||||
pw_log_debug("add pending %d", p->seq);
|
||||
self->seq = p->seq = pw_core_sync(self->core, 0, self->seq);
|
||||
}
|
||||
|
||||
static void remove_pending(struct pending *p)
|
||||
{
|
||||
if (p->seq != 0) {
|
||||
pw_log_debug("remove pending %d", p->seq);
|
||||
spa_list_remove(&p->link);
|
||||
p->seq = 0;
|
||||
}
|
||||
self->seq = pw_core_sync(self->core, PW_ID_CORE, self->seq);
|
||||
pw_log_debug("resync %d", self->seq);
|
||||
}
|
||||
|
||||
static void
|
||||
on_core_done (void *data, uint32_t id, int seq)
|
||||
{
|
||||
GstPipeWireDeviceProvider *self = data;
|
||||
struct pending *p, *t;
|
||||
struct core_data *rd = data;
|
||||
GstPipeWireDeviceProvider *self = rd->self;
|
||||
|
||||
spa_list_for_each_safe(p, t, &self->pending, link) {
|
||||
if (p->seq == seq) {
|
||||
remove_pending(p);
|
||||
if (p->callback)
|
||||
p->callback(p->data);
|
||||
}
|
||||
}
|
||||
pw_log_debug("check %d %d", seq, self->seq);
|
||||
if (seq == self->seq) {
|
||||
if (id == PW_ID_CORE && seq == self->seq) {
|
||||
do_add_nodes(rd);
|
||||
self->end = true;
|
||||
if (self->loop)
|
||||
pw_thread_loop_signal (self->loop, FALSE);
|
||||
|
|
@ -321,7 +292,8 @@ on_core_done (void *data, uint32_t id, int seq)
|
|||
static void
|
||||
on_core_error(void *data, uint32_t id, int seq, int res, const char *message)
|
||||
{
|
||||
GstPipeWireDeviceProvider *self = data;
|
||||
struct core_data *rd = data;
|
||||
GstPipeWireDeviceProvider *self = rd->self;
|
||||
|
||||
pw_log_error("error id:%u seq:%d res:%d (%s): %s",
|
||||
id, seq, res, spa_strerror(res), message);
|
||||
|
|
@ -341,7 +313,24 @@ static const struct pw_core_events core_events = {
|
|||
static void port_event_info(void *data, const struct pw_port_info *info)
|
||||
{
|
||||
struct port_data *port_data = data;
|
||||
struct node_data *node_data = port_data->node_data;
|
||||
uint32_t i;
|
||||
|
||||
pw_log_debug("%p", port_data);
|
||||
|
||||
if (info->change_mask & PW_PORT_CHANGE_MASK_PARAMS) {
|
||||
for (i = 0; i < info->n_params; i++) {
|
||||
uint32_t id = info->params[i].id;
|
||||
|
||||
if (id == SPA_PARAM_EnumFormat &&
|
||||
info->params[i].flags & SPA_PARAM_INFO_READ &&
|
||||
node_data->caps == NULL) {
|
||||
node_data->caps = gst_caps_new_empty ();
|
||||
pw_port_enum_params(port_data->proxy, 0, id, 0, UINT32_MAX, NULL);
|
||||
resync(node_data->self);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void port_event_param(void *data, int seq, uint32_t id,
|
||||
|
|
@ -351,8 +340,6 @@ static void port_event_param(void *data, int seq, uint32_t id,
|
|||
struct node_data *node_data = port_data->node_data;
|
||||
GstCaps *c1;
|
||||
|
||||
pw_log_debug("%p", port_data);
|
||||
|
||||
c1 = gst_caps_from_format (param);
|
||||
if (c1 && node_data->caps)
|
||||
gst_caps_append (node_data->caps, c1);
|
||||
|
|
@ -367,13 +354,42 @@ static const struct pw_port_events port_events = {
|
|||
static void node_event_info(void *data, const struct pw_node_info *info)
|
||||
{
|
||||
struct node_data *node_data = data;
|
||||
uint32_t i;
|
||||
|
||||
pw_log_debug("%p", node_data->proxy);
|
||||
node_data->info = pw_node_info_update(node_data->info, info);
|
||||
|
||||
info = node_data->info = pw_node_info_update(node_data->info, info);
|
||||
|
||||
if (info->change_mask & PW_NODE_CHANGE_MASK_PARAMS) {
|
||||
for (i = 0; i < info->n_params; i++) {
|
||||
uint32_t id = info->params[i].id;
|
||||
|
||||
if (id == SPA_PARAM_EnumFormat &&
|
||||
info->params[i].flags & SPA_PARAM_INFO_READ &&
|
||||
node_data->caps == NULL) {
|
||||
node_data->caps = gst_caps_new_empty ();
|
||||
pw_node_enum_params(node_data->proxy, 0, id, 0, UINT32_MAX, NULL);
|
||||
resync(node_data->self);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void node_event_param(void *data, int seq, uint32_t id,
|
||||
uint32_t index, uint32_t next, const struct spa_pod *param)
|
||||
{
|
||||
struct node_data *node_data = data;
|
||||
GstCaps *c1;
|
||||
|
||||
c1 = gst_caps_from_format (param);
|
||||
if (c1 && node_data->caps)
|
||||
gst_caps_append (node_data->caps, c1);
|
||||
}
|
||||
|
||||
static const struct pw_node_events node_events = {
|
||||
PW_VERSION_NODE_EVENTS,
|
||||
.info = node_event_info
|
||||
.info = node_event_info,
|
||||
.param = node_event_param
|
||||
};
|
||||
|
||||
static void
|
||||
|
|
@ -392,8 +408,6 @@ destroy_node (void *data)
|
|||
|
||||
pw_log_debug("destroy %p", nd);
|
||||
|
||||
remove_pending(&nd->pending);
|
||||
|
||||
if (nd->dev != NULL) {
|
||||
gst_device_provider_device_remove (provider, GST_DEVICE (nd->dev));
|
||||
}
|
||||
|
|
@ -423,14 +437,12 @@ destroy_port (void *data)
|
|||
{
|
||||
struct port_data *pd = data;
|
||||
pw_log_debug("destroy %p", pd);
|
||||
remove_pending(&pd->pending);
|
||||
spa_list_remove(&pd->link);
|
||||
}
|
||||
|
||||
static const struct pw_proxy_events proxy_port_events = {
|
||||
PW_VERSION_PROXY_EVENTS,
|
||||
.removed = removed_port,
|
||||
.destroy = destroy_port,
|
||||
PW_VERSION_PROXY_EVENTS,
|
||||
.removed = removed_port,
|
||||
.destroy = destroy_port,
|
||||
};
|
||||
|
||||
static void registry_event_global(void *data, uint32_t id, uint32_t permissions,
|
||||
|
|
@ -465,11 +477,10 @@ static void registry_event_global(void *data, uint32_t id, uint32_t permissions,
|
|||
nd->self = self;
|
||||
nd->proxy = node;
|
||||
nd->id = id;
|
||||
nd->caps = gst_caps_new_empty ();
|
||||
spa_list_append(&rd->nodes, &nd->link);
|
||||
pw_node_add_listener(node, &nd->node_listener, &node_events, nd);
|
||||
pw_proxy_add_listener((struct pw_proxy*)node, &nd->proxy_listener, &proxy_node_events, nd);
|
||||
add_pending(self, &nd->pending, NULL, NULL);
|
||||
resync(self);
|
||||
}
|
||||
else if (strcmp(type, PW_TYPE_INTERFACE_Port) == 0) {
|
||||
struct pw_port *port;
|
||||
|
|
@ -490,12 +501,9 @@ static void registry_event_global(void *data, uint32_t id, uint32_t permissions,
|
|||
pd->node_data = nd;
|
||||
pd->proxy = port;
|
||||
pd->id = id;
|
||||
spa_list_append(&rd->ports, &pd->link);
|
||||
pw_port_add_listener(port, &pd->port_listener, &port_events, pd);
|
||||
pw_proxy_add_listener((struct pw_proxy*)port, &pd->proxy_listener, &proxy_port_events, pd);
|
||||
pw_port_enum_params((struct pw_port*)port,
|
||||
0, SPA_PARAM_EnumFormat, 0, 0, NULL);
|
||||
add_pending(self, &pd->pending, do_add_node, pd);
|
||||
resync(self);
|
||||
}
|
||||
|
||||
return;
|
||||
|
|
@ -534,7 +542,6 @@ gst_pipewire_device_provider_probe (GstDeviceProvider * provider)
|
|||
data = pw_context_get_user_data(c);
|
||||
data->self = self;
|
||||
spa_list_init(&data->nodes);
|
||||
spa_list_init(&data->ports);
|
||||
|
||||
spa_list_init(&self->pending);
|
||||
self->core = pw_context_connect (c, NULL, 0);
|
||||
|
|
@ -542,7 +549,7 @@ gst_pipewire_device_provider_probe (GstDeviceProvider * provider)
|
|||
goto failed;
|
||||
|
||||
GST_DEBUG_OBJECT (self, "connected");
|
||||
pw_core_add_listener(self->core, &data->core_listener, &core_events, self);
|
||||
pw_core_add_listener(self->core, &data->core_listener, &core_events, data);
|
||||
|
||||
self->end = FALSE;
|
||||
self->list_only = TRUE;
|
||||
|
|
@ -551,7 +558,7 @@ gst_pipewire_device_provider_probe (GstDeviceProvider * provider)
|
|||
data->registry = pw_core_get_registry(self->core, PW_VERSION_REGISTRY, 0);
|
||||
pw_registry_add_listener(data->registry, &data->registry_listener, ®istry_events, data);
|
||||
|
||||
pw_core_sync(self->core, 0, self->seq++);
|
||||
resync(self);
|
||||
|
||||
for (;;) {
|
||||
if (self->error < 0)
|
||||
|
|
@ -612,15 +619,14 @@ gst_pipewire_device_provider_start (GstDeviceProvider * provider)
|
|||
data = pw_context_get_user_data(self->context);
|
||||
data->self = self;
|
||||
spa_list_init(&data->nodes);
|
||||
spa_list_init(&data->ports);
|
||||
|
||||
pw_core_add_listener(self->core, &data->core_listener, &core_events, self);
|
||||
pw_core_add_listener(self->core, &data->core_listener, &core_events, data);
|
||||
|
||||
self->registry = pw_core_get_registry(self->core, PW_VERSION_REGISTRY, 0);
|
||||
data->registry = self->registry;
|
||||
pw_registry_add_listener(self->registry, &data->registry_listener, ®istry_events, data);
|
||||
|
||||
pw_core_sync(self->core, 0, self->seq++);
|
||||
resync(self);
|
||||
|
||||
for (;;) {
|
||||
if (self->error < 0)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue