Newer
Older
/* WirePlumber
*
* Copyright © 2019 Collabora Ltd.
* @author George Kiagiadakis <george.kiagiadakis@collabora.com>
*
* SPDX-License-Identifier: MIT
*/
/**
* SECTION: WpObjectManager
*
* The #WpObjectManager class provides a way to collect a set of objects
* and be notified when objects that fulfill a certain set of criteria are
* created or destroyed.
*
* There are 4 kinds of objects that can be managed by a #WpObjectManager:
* * remote PipeWire global objects that are advertised on the registry;
* these are bound locally to subclasses of #WpProxy
* * remote PipeWire global objects that are created by calling a remote
* factory through the WirePlumber API; these are very similar to other
* global objects but it should be noted that the same #WpProxy instance
* that created them appears in the #WpObjectManager (as soon as its
* %WP_PROXY_FEATURE_BOUND is enabled)
* * local PipeWire objects that are being exported to PipeWire
* (#WpImplNode, #WpImplEndpoint, etc); these appear in the #WpObjectManager
* as soon as they are exported (so, when their %WP_PROXY_FEATURE_BOUND
* is enabled)
* * WirePlumber-specific objects, such as WirePlumber factories
*
* To start an object manager, you first need to declare interest in a certain
* kind of object by calling wp_object_manager_add_interest() and then install
* it on the #WpCore with wp_core_install_object_manager().
*
* Upon installing a #WpObjectManager on a #WpCore, any pre-existing objects
* that match the interests of this #WpObjectManager will immediately become
* available to get through wp_object_manager_get_objects() and the
* #WpObjectManager::object-added signal will be emitted for all of them.
*/
#include "object-manager.h"
#include "private.h"
#include <pipewire/pipewire.h>
/* WpObjectManager */
{
GType g_type;
WpProxyFeatures wanted_features;
GVariant *constraints; // aa{sv}
};
struct _WpObjectManager
{
GObject parent;
GWeakRef core;
/* array of struct interest;
pw_array has a better API for our use case than GArray */
struct pw_array interests;
/* objects that we are interested in, without a ref */
GPtrArray *objects;
gboolean pending_objchanged;
};
enum {
PROP_0,
PROP_CORE,
};
enum {
SIGNAL_OBJECT_ADDED,
SIGNAL_OBJECT_REMOVED,
SIGNAL_OBJECTS_CHANGED,
LAST_SIGNAL,
};
static guint signals[LAST_SIGNAL] = { 0 };
G_DEFINE_TYPE (WpObjectManager, wp_object_manager, G_TYPE_OBJECT)
static void
wp_object_manager_init (WpObjectManager * self)
{
g_weak_ref_init (&self->core, NULL);
pw_array_init (&self->interests, sizeof (struct interest));
self->objects = g_ptr_array_new ();
self->pending_objchanged = FALSE;
}
static void
wp_object_manager_finalize (GObject * object)
{
WpObjectManager *self = WP_OBJECT_MANAGER (object);
struct interest *i;
g_clear_pointer (&self->objects, g_ptr_array_unref);
pw_array_for_each (i, &self->interests) {
g_clear_pointer (&i->constraints, g_variant_unref);
}
pw_array_clear (&self->interests);
g_weak_ref_clear (&self->core);
G_OBJECT_CLASS (wp_object_manager_parent_class)->finalize (object);
}
static void
wp_object_manager_set_property (GObject * object, guint property_id,
const GValue * value, GParamSpec * pspec)
{
WpObjectManager *self = WP_OBJECT_MANAGER (object);
switch (property_id) {
case PROP_CORE:
g_weak_ref_set (&self->core, g_value_get_object (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void
wp_object_manager_get_property (GObject * object, guint property_id,
GValue * value, GParamSpec * pspec)
{
WpObjectManager *self = WP_OBJECT_MANAGER (object);
switch (property_id) {
case PROP_CORE:
g_value_take_object (value, g_weak_ref_get (&self->core));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void
wp_object_manager_class_init (WpObjectManagerClass * klass)
{
GObjectClass *object_class = (GObjectClass *) klass;
object_class->finalize = wp_object_manager_finalize;
object_class->get_property = wp_object_manager_get_property;
object_class->set_property = wp_object_manager_set_property;
/* Install the properties */
g_object_class_install_property (object_class, PROP_CORE,
g_param_spec_object ("core", "core", "The WpCore", WP_TYPE_CORE,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
/**
* WpObjectManager::object-added:
* @self: the object manager
* @object: (transfer none): the managed object that was just added
*
* Emitted when an object that matches the interests of this object manager
* is made available.
*/
signals[SIGNAL_OBJECT_ADDED] = g_signal_new (
"object-added", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_FIRST,
0, NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_OBJECT);
/**
* WpObjectManager::object-removed:
* @self: the object manager
* @object: (transfer none): the managed object that is being removed
*
* Emitted when an object that was previously added on this object manager
* is now being removed (and most likely destroyed). At the time that this
* signal is emitted, the object is still alive.
*/
signals[SIGNAL_OBJECT_REMOVED] = g_signal_new (
"object-removed", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_FIRST,
0, NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_OBJECT);
/**
* WpObjectManager::objects-changed:
* @self: the object manager
*
* Emitted when one or more objects have been recently added or removed
* from this object manager. This signal is useful to get notified only once
* when multiple changes happen in a short timespan. The receiving callback
* may retrieve the updated list of objects by calling
* wp_object_manager_get_objects()
*/
signals[SIGNAL_OBJECTS_CHANGED] = g_signal_new (
"objects-changed", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_FIRST,
0, NULL, NULL, NULL, G_TYPE_NONE, 0);
}
/**
* wp_object_manager_new:
Loading
Loading full blame...