mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-02 09:01:50 -05:00
devicemonitor: various improvements
Set the active device providers as a property on the daemon. In the device monitor we can then obsolete the already monitored devices. Copy all device properties to the source. Set the device class as a property on the monitored devices.
This commit is contained in:
parent
191909cb05
commit
1378a65fb7
2 changed files with 137 additions and 13 deletions
|
|
@ -44,35 +44,31 @@ enum
|
||||||
|
|
||||||
static GstDevice *
|
static GstDevice *
|
||||||
gst_pinos_device_new (gpointer id, const gchar * device_name,
|
gst_pinos_device_new (gpointer id, const gchar * device_name,
|
||||||
GstCaps * caps, const gchar * path, GstPinosDeviceType type)
|
GstCaps * caps, const gchar * path, const gchar *klass,
|
||||||
|
GstPinosDeviceType type, GstStructure *props)
|
||||||
{
|
{
|
||||||
GstPinosDevice *gstdev;
|
GstPinosDevice *gstdev;
|
||||||
const gchar *element = NULL;
|
const gchar *element = NULL;
|
||||||
const gchar *klass = NULL;
|
|
||||||
|
|
||||||
g_return_val_if_fail (device_name, NULL);
|
g_return_val_if_fail (device_name, NULL);
|
||||||
g_return_val_if_fail (path, NULL);
|
g_return_val_if_fail (path, NULL);
|
||||||
g_return_val_if_fail (caps, NULL);
|
g_return_val_if_fail (caps, NULL);
|
||||||
|
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case GST_PINOS_DEVICE_TYPE_SOURCE:
|
case GST_PINOS_DEVICE_TYPE_SOURCE:
|
||||||
element = "pinossrc";
|
element = "pinossrc";
|
||||||
klass = "Video/Source/Pinos";
|
|
||||||
break;
|
break;
|
||||||
case GST_PINOS_DEVICE_TYPE_SINK:
|
case GST_PINOS_DEVICE_TYPE_SINK:
|
||||||
element = "pinossink";
|
element = "pinossink";
|
||||||
klass = "Video/Sink/Pinos";
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
g_assert_not_reached ();
|
g_assert_not_reached ();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
gstdev = g_object_new (GST_TYPE_PINOS_DEVICE,
|
gstdev = g_object_new (GST_TYPE_PINOS_DEVICE,
|
||||||
"display-name", device_name, "caps", caps, "device-class", klass,
|
"display-name", device_name, "caps", caps, "device-class", klass,
|
||||||
"path", path, NULL);
|
"path", path, "properties", props, NULL);
|
||||||
|
|
||||||
gstdev->id = id;
|
gstdev->id = id;
|
||||||
gstdev->type = type;
|
gstdev->type = type;
|
||||||
|
|
@ -209,17 +205,39 @@ static GstDevice *
|
||||||
new_source (const PinosSourceInfo *info)
|
new_source (const PinosSourceInfo *info)
|
||||||
{
|
{
|
||||||
GstCaps *caps;
|
GstCaps *caps;
|
||||||
|
GstStructure *props;
|
||||||
|
gpointer state = NULL;
|
||||||
|
const gchar *klass;
|
||||||
|
|
||||||
if (info->formats)
|
if (info->formats)
|
||||||
caps = gst_caps_from_string (g_bytes_get_data (info->formats, NULL));
|
caps = gst_caps_from_string (g_bytes_get_data (info->formats, NULL));
|
||||||
else
|
else
|
||||||
caps = gst_caps_new_any();
|
caps = gst_caps_new_any();
|
||||||
|
|
||||||
|
|
||||||
|
props = gst_structure_new_empty ("pinos-proplist");
|
||||||
|
|
||||||
|
while (TRUE) {
|
||||||
|
const char *key, *val;
|
||||||
|
|
||||||
|
if (!(key = pinos_properties_iterate (info->properties, &state)))
|
||||||
|
break;
|
||||||
|
|
||||||
|
val = pinos_properties_get (info->properties, key);
|
||||||
|
gst_structure_set (props, key, G_TYPE_STRING, val, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
klass = pinos_properties_get (info->properties, "gstreamer.device.class");
|
||||||
|
if (klass == NULL)
|
||||||
|
klass = "unknown/unknown";
|
||||||
|
|
||||||
return gst_pinos_device_new (info->id,
|
return gst_pinos_device_new (info->id,
|
||||||
info->name,
|
info->name,
|
||||||
caps,
|
caps,
|
||||||
info->source_path,
|
info->source_path,
|
||||||
GST_PINOS_DEVICE_TYPE_SOURCE);
|
klass,
|
||||||
|
GST_PINOS_DEVICE_TYPE_SOURCE,
|
||||||
|
props);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
|
|
@ -317,6 +335,30 @@ list_source_info_cb (PinosContext *c,
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
get_daemon_info_cb (PinosContext *c, const PinosDaemonInfo *info, gpointer userdata)
|
||||||
|
{
|
||||||
|
GstDeviceProvider *provider = userdata;
|
||||||
|
const gchar *value;
|
||||||
|
|
||||||
|
if (info == NULL)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
value = pinos_properties_get (info->properties, "gstreamer.deviceproviders");
|
||||||
|
if (value) {
|
||||||
|
gchar **providers = g_strsplit (value, ",", -1);
|
||||||
|
gint i;
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (provider, "have obsoleted providers: %s\n", value);
|
||||||
|
|
||||||
|
for (i = 0; providers[i]; i++) {
|
||||||
|
gst_device_provider_add_obsoleted (provider, providers[i]);
|
||||||
|
}
|
||||||
|
g_strfreev (providers);
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
static GList *
|
static GList *
|
||||||
gst_pinos_device_provider_probe (GstDeviceProvider * provider)
|
gst_pinos_device_provider_probe (GstDeviceProvider * provider)
|
||||||
{
|
{
|
||||||
|
|
@ -325,6 +367,8 @@ gst_pinos_device_provider_probe (GstDeviceProvider * provider)
|
||||||
PinosContext *c = NULL;
|
PinosContext *c = NULL;
|
||||||
InfoData data;
|
InfoData data;
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (self, "starting probe");
|
||||||
|
|
||||||
if (!(m = g_main_context_new ()))
|
if (!(m = g_main_context_new ()))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
|
@ -354,6 +398,13 @@ gst_pinos_device_provider_probe (GstDeviceProvider * provider)
|
||||||
}
|
}
|
||||||
GST_DEBUG_OBJECT (self, "connected");
|
GST_DEBUG_OBJECT (self, "connected");
|
||||||
|
|
||||||
|
pinos_context_get_daemon_info (c,
|
||||||
|
PINOS_DAEMON_INFO_FLAGS_NONE,
|
||||||
|
get_daemon_info_cb,
|
||||||
|
NULL,
|
||||||
|
self);
|
||||||
|
|
||||||
|
|
||||||
data.end = FALSE;
|
data.end = FALSE;
|
||||||
data.devices = NULL;
|
data.devices = NULL;
|
||||||
pinos_context_list_source_info (c,
|
pinos_context_list_source_info (c,
|
||||||
|
|
@ -419,6 +470,8 @@ gst_pinos_device_provider_start (GstDeviceProvider * provider)
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
GMainContext *c;
|
GMainContext *c;
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (self, "starting provider");
|
||||||
|
|
||||||
c = g_main_context_new ();
|
c = g_main_context_new ();
|
||||||
|
|
||||||
if (!(self->loop = pinos_main_loop_new (c, "pinos-device-monitor"))) {
|
if (!(self->loop = pinos_main_loop_new (c, "pinos-device-monitor"))) {
|
||||||
|
|
@ -455,8 +508,32 @@ gst_pinos_device_provider_start (GstDeviceProvider * provider)
|
||||||
(GCallback) context_subscribe_cb,
|
(GCallback) context_subscribe_cb,
|
||||||
self);
|
self);
|
||||||
|
|
||||||
pinos_context_connect (self->context, PINOS_CONTEXT_FLAGS_NOFAIL);
|
pinos_context_connect (self->context, PINOS_CONTEXT_FLAGS_NONE);
|
||||||
|
for (;;) {
|
||||||
|
PinosContextState state;
|
||||||
|
|
||||||
|
state = pinos_context_get_state (self->context);
|
||||||
|
|
||||||
|
if (state <= 0) {
|
||||||
|
GST_WARNING_OBJECT (self, "Failed to connect: %s",
|
||||||
|
pinos_context_get_error (self->context)->message);
|
||||||
|
goto not_running;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state == PINOS_CONTEXT_STATE_READY)
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Wait until something happens */
|
||||||
|
pinos_main_loop_wait (self->loop);
|
||||||
|
}
|
||||||
|
GST_DEBUG_OBJECT (self, "connected");
|
||||||
|
pinos_context_get_daemon_info (self->context,
|
||||||
|
PINOS_DAEMON_INFO_FLAGS_NONE,
|
||||||
|
get_daemon_info_cb,
|
||||||
|
NULL,
|
||||||
|
self);
|
||||||
pinos_main_loop_unlock (self->loop);
|
pinos_main_loop_unlock (self->loop);
|
||||||
|
|
||||||
g_main_context_unref (c);
|
g_main_context_unref (c);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
@ -466,6 +543,14 @@ failed:
|
||||||
g_main_context_unref (c);
|
g_main_context_unref (c);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
not_running:
|
||||||
|
{
|
||||||
|
pinos_main_loop_unlock (self->loop);
|
||||||
|
pinos_main_loop_stop (self->loop);
|
||||||
|
g_clear_object (&self->context);
|
||||||
|
g_clear_object (&self->loop);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -476,8 +561,9 @@ gst_pinos_device_provider_stop (GstDeviceProvider * provider)
|
||||||
if (self->context) {
|
if (self->context) {
|
||||||
pinos_context_disconnect (self->context);
|
pinos_context_disconnect (self->context);
|
||||||
}
|
}
|
||||||
pinos_main_loop_stop (self->loop);
|
if (self->loop) {
|
||||||
|
pinos_main_loop_stop (self->loop);
|
||||||
|
}
|
||||||
g_clear_object (&self->context);
|
g_clear_object (&self->context);
|
||||||
g_clear_object (&self->loop);
|
g_clear_object (&self->loop);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,21 @@ enum
|
||||||
|
|
||||||
G_DEFINE_TYPE (PinosGstManager, pinos_gst_manager, G_TYPE_OBJECT);
|
G_DEFINE_TYPE (PinosGstManager, pinos_gst_manager, G_TYPE_OBJECT);
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
copy_properties (GQuark field_id,
|
||||||
|
const GValue *value,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
PinosProperties *properties = user_data;
|
||||||
|
|
||||||
|
if (G_VALUE_HOLDS_STRING (value))
|
||||||
|
pinos_properties_set (properties,
|
||||||
|
g_quark_to_string (field_id),
|
||||||
|
g_value_get_string (value));
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
device_added (PinosGstManager *manager,
|
device_added (PinosGstManager *manager,
|
||||||
GstDevice *device)
|
GstDevice *device)
|
||||||
|
|
@ -50,6 +65,8 @@ device_added (PinosGstManager *manager,
|
||||||
gchar *name;
|
gchar *name;
|
||||||
GstElement *element;
|
GstElement *element;
|
||||||
PinosSource *source;
|
PinosSource *source;
|
||||||
|
GstStructure *p;
|
||||||
|
PinosProperties *properties;
|
||||||
|
|
||||||
name = gst_device_get_display_name (device);
|
name = gst_device_get_display_name (device);
|
||||||
if (strcmp (name, "gst") == 0)
|
if (strcmp (name, "gst") == 0)
|
||||||
|
|
@ -57,8 +74,15 @@ device_added (PinosGstManager *manager,
|
||||||
|
|
||||||
g_print("Device added: %s\n", name);
|
g_print("Device added: %s\n", name);
|
||||||
|
|
||||||
|
properties = pinos_properties_new (NULL);
|
||||||
|
if ((p = gst_device_get_properties (device)))
|
||||||
|
gst_structure_foreach (p, copy_properties, properties);
|
||||||
|
pinos_properties_set (properties,
|
||||||
|
"gstreamer.device.class",
|
||||||
|
gst_device_get_device_class (device));
|
||||||
|
|
||||||
element = gst_device_create_element (device, NULL);
|
element = gst_device_create_element (device, NULL);
|
||||||
source = pinos_gst_source_new (priv->daemon, name, element);
|
source = pinos_gst_source_new (priv->daemon, name, properties, element);
|
||||||
g_object_set_data (G_OBJECT (device), "PinosSource", source);
|
g_object_set_data (G_OBJECT (device), "PinosSource", source);
|
||||||
g_free (name);
|
g_free (name);
|
||||||
}
|
}
|
||||||
|
|
@ -129,6 +153,9 @@ start_monitor (PinosGstManager *manager)
|
||||||
PinosGstManagerPrivate *priv = manager->priv;
|
PinosGstManagerPrivate *priv = manager->priv;
|
||||||
GstBus *bus;
|
GstBus *bus;
|
||||||
GList *devices;
|
GList *devices;
|
||||||
|
gchar **providers;
|
||||||
|
gchar *provided;
|
||||||
|
PinosProperties *props;
|
||||||
|
|
||||||
disable_pinos_provider (manager);
|
disable_pinos_provider (manager);
|
||||||
|
|
||||||
|
|
@ -139,9 +166,20 @@ start_monitor (PinosGstManager *manager)
|
||||||
gst_object_unref (bus);
|
gst_object_unref (bus);
|
||||||
|
|
||||||
gst_device_monitor_add_filter (priv->monitor, "Video/Source", NULL);
|
gst_device_monitor_add_filter (priv->monitor, "Video/Source", NULL);
|
||||||
|
gst_device_monitor_add_filter (priv->monitor, "Audio/Source", NULL);
|
||||||
gst_device_monitor_start (priv->monitor);
|
gst_device_monitor_start (priv->monitor);
|
||||||
|
|
||||||
|
providers = gst_device_monitor_get_providers (priv->monitor);
|
||||||
|
provided = g_strjoinv (",", providers);
|
||||||
|
g_strfreev (providers);
|
||||||
|
|
||||||
|
g_object_get (priv->daemon, "properties", &props, NULL);
|
||||||
|
pinos_properties_set (props, "gstreamer.deviceproviders", provided);
|
||||||
|
g_object_set (priv->daemon, "properties", props, NULL);
|
||||||
|
pinos_properties_free (props);
|
||||||
|
|
||||||
|
g_free (provided);
|
||||||
|
|
||||||
devices = gst_device_monitor_get_devices (priv->monitor);
|
devices = gst_device_monitor_get_devices (priv->monitor);
|
||||||
while (devices != NULL) {
|
while (devices != NULL) {
|
||||||
GstDevice *device = devices->data;
|
GstDevice *device = devices->data;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue