gst: deviceprodiver: Sort devices by session priority

Applications using the device provider typically list devices in the
order they were added. In order to ensure that apps pick nodes like cameras
with the highest priority by default, sort devices accordingly.

This unfortunately does not not have an effect on nodes added later,
e.g. on hotplug.

Closes https://gitlab.freedesktop.org/pipewire/pipewire/-/issues/3072
This commit is contained in:
Robert Mader 2023-03-10 23:21:13 +01:00
parent fe1b9c2d49
commit 8fff69353b
2 changed files with 42 additions and 5 deletions

View file

@ -210,6 +210,7 @@ new_node (GstPipeWireDeviceProvider *self, struct node_data *data)
const struct pw_node_info *info = data->info;
const gchar *element = NULL;
GstPipeWireDevice *gstdev;
int priority = 0;
if (info->max_input_ports > 0 && info->max_output_ports == 0) {
type = GST_PIPEWIRE_DEVICE_TYPE_SINK;
@ -224,11 +225,16 @@ new_node (GstPipeWireDeviceProvider *self, struct node_data *data)
props = gst_structure_new_empty ("pipewire-proplist");
if (info->props) {
const struct spa_dict_item *item;
const char *str;
spa_dict_for_each (item, info->props)
gst_structure_set (props, item->key, G_TYPE_STRING, item->value, NULL);
klass = spa_dict_lookup (info->props, PW_KEY_MEDIA_CLASS);
name = spa_dict_lookup (info->props, PW_KEY_NODE_DESCRIPTION);
if ((str = spa_dict_lookup(info->props, PW_KEY_PRIORITY_SESSION)))
priority = atoi(str);
}
if (klass == NULL)
klass = "unknown/unknown";
@ -244,26 +250,56 @@ new_node (GstPipeWireDeviceProvider *self, struct node_data *data)
gstdev->serial = data->serial;
gstdev->type = type;
gstdev->element = element;
gstdev->priority = priority;
if (props)
gst_structure_free (props);
return GST_DEVICE (gstdev);
}
static int
compare_device_session_priority (const void *a,
const void *b)
{
const GstPipeWireDevice *dev_a = a;
const GstPipeWireDevice *dev_b = b;
if (dev_a->priority < dev_b->priority)
return 1;
else if (dev_a->priority > dev_b->priority)
return -1;
else
return 0;
}
static void do_add_nodes(GstPipeWireDeviceProvider *self)
{
struct node_data *nd;
GList *new_devices = NULL;
GList *l;
spa_list_for_each(nd, &self->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);
if (nd->dev)
new_devices = g_list_prepend (new_devices, nd->dev);
}
if (!new_devices)
return;
new_devices = g_list_sort (new_devices,
compare_device_session_priority);
for (l = new_devices; l != NULL; l = l->next) {
GstDevice *device = l->data;
if(self->list_only) {
self->devices = g_list_insert_sorted (self->devices,
gst_object_ref_sink (device),
compare_device_session_priority);
} else {
gst_device_provider_device_add (GST_DEVICE_PROVIDER (self), device);
}
}
}

View file

@ -39,6 +39,7 @@ struct _GstPipeWireDevice {
uint64_t serial;
int fd;
const gchar *element;
int priority;
};
struct _GstPipeWireDeviceClass {