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 [private], 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_iterate() and the
* #WpObjectManager::object-added signal will be emitted for all of them.
*/
#define G_LOG_DOMAIN "wp-object-manager"
#include "object-manager.h"
#include "debug.h"
#include "private.h"
#include <pipewire/pipewire.h>
/* WpObjectManager */
struct _WpObjectManager
{
GObject parent;
GWeakRef core;

George Kiagiadakis
committed
/* element-type: WpObjectInterest* */
GPtrArray *interests;
/* element-type: <GType, WpProxyFeatures> */
GHashTable *features;
/* objects that we are interested in, without a ref */
GPtrArray *objects;

George Kiagiadakis
committed
gboolean installed;
gboolean changed;
guint pending_objects;
GSource *idle_source;
};
enum {
PROP_0,
PROP_CORE,
};
enum {
SIGNAL_OBJECT_ADDED,
SIGNAL_OBJECT_REMOVED,
SIGNAL_OBJECTS_CHANGED,

George Kiagiadakis
committed
SIGNAL_INSTALLED,
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);

George Kiagiadakis
committed
self->interests =
g_ptr_array_new_with_free_func ((GDestroyNotify) wp_object_interest_free);
self->features = g_hash_table_new (g_direct_hash, g_direct_equal);
self->objects = g_ptr_array_new ();

George Kiagiadakis
committed
self->installed = FALSE;
self->changed = FALSE;
self->pending_objects = 0;
}
static void
wp_object_manager_finalize (GObject * object)
{
WpObjectManager *self = WP_OBJECT_MANAGER (object);

George Kiagiadakis
committed
if (self->idle_source) {
g_source_destroy (self->idle_source);
g_clear_pointer (&self->idle_source, g_source_unref);
}
g_clear_pointer (&self->objects, g_ptr_array_unref);

George Kiagiadakis
committed
g_clear_pointer (&self->features, g_hash_table_unref);
g_clear_pointer (&self->interests, g_ptr_array_unref);
g_weak_ref_clear (&self->core);
G_OBJECT_CLASS (wp_object_manager_parent_class)->finalize (object);
}
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;
/* Install the properties */
g_object_class_install_property (object_class, PROP_CORE,
g_param_spec_object ("core", "core", "The WpCore", WP_TYPE_CORE,

George Kiagiadakis
committed
G_PARAM_READABLE | 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_iterate()
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);

George Kiagiadakis
committed
/**
* WpObjectManager::installed:
* @self: the object manager
*
* This is emitted once after the object manager is installed with
* wp_core_install_object_manager(). If there are objects that need
* to be prepared asynchronously internally, emission of this signal is
* delayed until all objects are ready.
*/
signals[SIGNAL_INSTALLED] = g_signal_new (
"installed", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_FIRST,
0, NULL, NULL, NULL, G_TYPE_NONE, 0);
/**
* wp_object_manager_new:
*
* Constructs a new object manager.
Loading
Loading full blame...