lib: add extensive API documentation

This commit is contained in:
George Kiagiadakis 2020-02-17 15:39:19 +02:00
parent 77bb816b52
commit d4973363ac
32 changed files with 1280 additions and 40 deletions

View file

@ -319,7 +319,7 @@ wp_base_endpoint_class_init (WpBaseEndpointClass * klass)
/**
* WpBaseEndpoint::creation-time:
* The creation time of the endpoint in monolitic time
* The creation time of the endpoint in monotonic time
*/
g_object_class_install_property (object_class, PROP_CREATION_TIME,
g_param_spec_uint64 ("creation-time", "creation-time",
@ -327,7 +327,7 @@ wp_base_endpoint_class_init (WpBaseEndpointClass * klass)
0, G_MAXUINT64, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
/**
* WpBaseEndpoint::direction:
* WpBaseEndpoint::priority:
* The priority of the endpoint:
*/
g_object_class_install_property (object_class, PROP_PRIORITY,

View file

@ -6,6 +6,15 @@
* SPDX-License-Identifier: MIT
*/
/**
* SECTION: WpClient
*
* The #WpClient class allows accessing the properties and methods of a PipeWire
* client object (`struct pw_client`). A #WpClient is constructed internally
* when a new client connects to PipeWire and it is made available through the
* #WpObjectManager API.
*/
#include "client.h"
#include "private.h"
@ -43,7 +52,7 @@ wp_client_get_info (WpProxy * self)
return WP_CLIENT (self)->info;
}
WpProperties *
static WpProperties *
wp_client_get_properties (WpProxy * self)
{
return wp_properties_new_wrap_dict (WP_CLIENT (self)->info->props);
@ -93,6 +102,17 @@ wp_client_class_init (WpClientClass * klass)
proxy_class->pw_proxy_created = wp_client_pw_proxy_created;
}
/**
* wp_client_update_permissions:
* @self: the client
* @n_perm: the number of permissions specified in the variable arguments
* @...: @n_perm pairs of #guint32 numbers; the first number is the object id
* and the second is the permissions that this client should have
* on this object
*
* Update client's permissions on a list of objects. An object id of `-1`
* can be used to set the default object permissions for this client
*/
void
wp_client_update_permissions (WpClient * self, guint n_perm, ...)
{
@ -110,6 +130,16 @@ wp_client_update_permissions (WpClient * self, guint n_perm, ...)
wp_client_update_permissions_array (self, n_perm, perm);
}
/**
* wp_client_update_permissions_array:
* @self: the client
* @n_perm: the number of permissions specified in the @permissions array
* @permissions: (array length=n_perm) (element-type pw_permission): an array
* of permissions per object id
*
* Update client's permissions on a list of objects. An object id of `-1`
* can be used to set the default object permissions for this client
*/
void
wp_client_update_permissions_array (WpClient * self,
guint n_perm, const struct pw_permission *permissions)

View file

@ -15,6 +15,11 @@ G_BEGIN_DECLS
struct pw_permission;
/**
* WP_TYPE_CLIENT:
*
* The #WpClient #GType
*/
#define WP_TYPE_CLIENT (wp_client_get_type ())
WP_API
G_DECLARE_FINAL_TYPE (WpClient, wp_client, WP, CLIENT, WpProxy)

View file

@ -6,6 +6,12 @@
* SPDX-License-Identifier: MIT
*/
/**
* SECTION: WpConfiguration
*
* The #WpConfiguration class manages configuration files and parsers
*/
#include "configuration.h"
#include "private.h"
@ -24,6 +30,16 @@ wp_config_parser_default_init (WpConfigParserInterface *klass)
{
}
/**
* wp_config_parser_add_file: (virtual add_file)
* @self: the parser
* @location: path to a configuration file
*
* Adds the file at @location on the parser and parses all the information
* from it, making it available to the code that needs this configuration
*
* Returns: %TRUE on success, %FALSE if an error occurred
*/
gboolean
wp_config_parser_add_file (WpConfigParser *self, const char *location)
{
@ -33,6 +49,13 @@ wp_config_parser_add_file (WpConfigParser *self, const char *location)
return WP_CONFIG_PARSER_GET_IFACE (self)->add_file (self, location);
}
/**
* wp_config_parser_get_matched_data: (virtual get_matched_data)
* @self: the parser
* @data: implementation-specific data
*
* Returns: the matched data
*/
gconstpointer
wp_config_parser_get_matched_data (WpConfigParser *self, gpointer data)
{
@ -42,6 +65,12 @@ wp_config_parser_get_matched_data (WpConfigParser *self, gpointer data)
return WP_CONFIG_PARSER_GET_IFACE (self)->get_matched_data (self, data);
}
/**
* wp_config_parser_reset: (virtual reset)
* @self: the parser
*
* Resets the state of the parser
*/
void
wp_config_parser_reset (WpConfigParser *self)
{
@ -80,6 +109,15 @@ wp_configuration_class_init (WpConfigurationClass * klass)
object_class->finalize = wp_configuration_finalize;
}
/**
* wp_configuration_get_instance:
* @core: the core
*
* Retrieves (and creates, the first time) the instance of #WpConfiguration
* that is registered on the specified @core
*
* Returns: (transfer full): the @core-specific instance of #WpConfiguration
*/
WpConfiguration *
wp_configuration_get_instance (WpCore *core)
{
@ -98,12 +136,21 @@ wp_configuration_get_instance (WpCore *core)
return self;
}
/**
* wp_configuration_add_path:
* @self: the configuration
* @path: path to a directory that contains configuration files
*
* Adds the specified @path in the list of directories that are being
* searched for configuration files. All files in this directory that
* have a known extension to this #WpConfiguration instance will be parsed
* and made available through their #WpConfigParser
*/
void
wp_configuration_add_path (WpConfiguration *self, const char *path)
{
guint i;
g_return_if_fail (self);
g_return_if_fail (WP_IS_CONFIGURATION (self));
/* Make sure the path is not already added */
@ -116,12 +163,20 @@ wp_configuration_add_path (WpConfiguration *self, const char *path)
g_ptr_array_add (self->paths, g_strdup (path));
}
/**
* wp_configuration_remove_path:
* @self: the configuration
* @path: path to a directory that was previously added with
* wp_configuration_add_path()
*
* Removes the specified @path from the list of directories that are being
* searched for configuration files
*/
void
wp_configuration_remove_path (WpConfiguration *self, const char *path)
{
guint i;
g_return_if_fail (self);
g_return_if_fail (WP_IS_CONFIGURATION (self));
/* Find the path index */
@ -136,15 +191,27 @@ wp_configuration_remove_path (WpConfiguration *self, const char *path)
g_ptr_array_remove_index (self->paths, i);
}
/**
* wp_configuration_add_extension:
* @self: the configuration
* @extension: a filename extension
* @parser_type: a type that implements the #WpConfigParser interface
*
* Creates a parser and associates it with the specified filename @extension.
* All configuration files that match this extension will, upon calling
* wp_configuration_reload(), be added to this parser
*
* Returns: %TRUE if the extension is new, %FALSE if it was already added
* or an error occurred
*/
gboolean
wp_configuration_add_extension (WpConfiguration *self, const gchar * extension,
GType parser_type)
{
g_return_val_if_fail (self, FALSE);
g_return_val_if_fail (WP_IS_CONFIGURATION (self), FALSE);
/* create the parser */
g_autoptr (WpConfigParser) parser = g_object_new (parser_type, FALSE);
g_autoptr (WpConfigParser) parser = g_object_new (parser_type, NULL);
g_return_val_if_fail (WP_IS_CONFIG_PARSER (parser), FALSE);
return g_hash_table_insert (self->parsers, g_strdup (extension),
@ -152,28 +219,55 @@ wp_configuration_add_extension (WpConfiguration *self, const gchar * extension,
}
/**
* wp_configuration_remove_extension:
* @self: the configuration
* @extension: a filename extension that was previously associated with a
* parser using wp_configuration_add_extension()
*
* Removes the association of @extension to a parser and destroys the parser
*
* Returns: %TRUE if the extension was indeed removed,
* %FALSE if it was not added
*/
gboolean
wp_configuration_remove_extension (WpConfiguration *self,
const gchar * extension)
{
g_return_val_if_fail (self, FALSE);
g_return_val_if_fail (WP_IS_CONFIGURATION (self), FALSE);
return g_hash_table_remove (self->parsers, extension);
}
/**
* wp_configuration_get_parser:
* @self: the configuration
* @extension: a filename extension that was previously associated with a
* parser using wp_configuration_add_extension()
*
* Returns: (transfer full) (nullable): the parser associated with @extension
*/
WpConfigParser *
wp_configuration_get_parser (WpConfiguration *self, const char *extension)
{
WpConfigParser *parser = NULL;
g_return_val_if_fail (self, NULL);
g_return_val_if_fail (WP_IS_CONFIGURATION (self), NULL);
parser = g_hash_table_lookup (self->parsers, extension);
return parser ? g_object_ref (parser) : NULL;
}
/**
* wp_configuration_reload:
* @self: the configuration
* @extension: a filename extension that was previously associated with a
* parser using wp_configuration_add_extension()
*
* Resets the parser associated with @extension and re-adds (and re-parses)
* all the configuration files that have this @extension from all the
* directories that were added with wp_configuration_add_path()
*/
void
wp_configuration_reload (WpConfiguration *self, const char *extension)
{
@ -185,7 +279,6 @@ wp_configuration_reload (WpConfiguration *self, const char *extension)
g_autofree gchar *ext = NULL;
g_autofree gchar *location = NULL;
g_return_if_fail (self);
g_return_if_fail (WP_IS_CONFIGURATION (self));
/* Get the parser for the extension */

View file

@ -15,18 +15,29 @@ G_BEGIN_DECLS
/* WpConfigParser */
/**
* WP_TYPE_CONFIG_PARSER:
*
* The #WpConfigParser #GType
*/
#define WP_TYPE_CONFIG_PARSER (wp_config_parser_get_type ())
WP_API
G_DECLARE_INTERFACE (WpConfigParser, wp_config_parser, WP,
CONFIG_PARSER, GObject)
/**
* WpConfigParserInterface:
* @add_file: See wp_config_parser_add_file()
* @get_matched_data: See wp_config_parser_get_matched_data()
* @reset: See wp_config_parser_reset()
*/
struct _WpConfigParserInterface
{
GTypeInterface parent;
gboolean (*add_file) (WpConfigParser *parser, const gchar *name);
gconstpointer (*get_matched_data) (WpConfigParser *parser, gpointer data);
void (*reset) (WpConfigParser *parser);
gboolean (*add_file) (WpConfigParser *self, const gchar *location);
gconstpointer (*get_matched_data) (WpConfigParser *self, gpointer data);
void (*reset) (WpConfigParser *self);
};
WP_API
@ -41,6 +52,11 @@ void wp_config_parser_reset (WpConfigParser *self);
/* WpConfiguration */
/**
* WP_TYPE_CONFIGURATION:
*
* The #WpConfiguration #GType
*/
#define WP_TYPE_CONFIGURATION (wp_configuration_get_type ())
WP_API
G_DECLARE_FINAL_TYPE (WpConfiguration, wp_configuration, WP, CONFIGURATION,

View file

@ -6,6 +6,24 @@
* SPDX-License-Identifier: MIT
*/
/**
* SECTION: WpCore
*
* The core is the central object around which everything operates. It is
* essential to create a #WpCore before using any other WirePlumber API.
*
* The core object has the following responsibilities:
* * it initializes the PipeWire library
* * it creates a `pw_context` and allows connecting to the PipeWire server,
* creating a local `pw_core`
* * it glues the PipeWire library's event loop system with GMainLoop
* * it maintains a list of registered objects, which other classes use
* to keep objects loaded permanently into memory
* * it watches the PipeWire registry and keeps track of remote and local
* objects that appear in the registry, making them accessible through
* the #WpObjectManager API.
*/
#include "core.h"
#include "wp.h"
#include "private.h"
@ -111,6 +129,11 @@ enum {
static guint32 signals[NUM_SIGNALS];
/**
* WP_TYPE_CORE:
*
* The #WpCore #GType
*/
G_DEFINE_TYPE (WpCore, wp_core, G_TYPE_OBJECT)
static void
@ -273,10 +296,22 @@ wp_core_class_init (WpCoreClass * klass)
g_param_spec_pointer ("pw-core", "pw-core", "The pipewire core",
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
/* Signals */
/**
* WpCore::connected:
* @self: the core
*
* Emitted when the core is successfully connected to the PipeWire server
*/
signals[SIGNAL_CONNECTED] = g_signal_new ("connected",
G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL,
G_TYPE_NONE, 0);
/**
* WpCore::disconnected:
* @self: the core
*
* Emitted when the core is disconnected from the PipeWire server
*/
signals[SIGNAL_DISCONNECTED] = g_signal_new ("disconnected",
G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL,
G_TYPE_NONE, 0);
@ -292,6 +327,14 @@ wp_core_class_init (WpCoreClass * klass)
g_type_ensure (WP_TYPE_SESSION);
}
/**
* wp_core_new:
* @context: (transfer none) (nullable): the #GMainContext to use for events
* @properties: (transfer none) (nullable): additional properties, which are
* passed to `pw_context_new` and `pw_context_connect`
*
* Returns: (transfer full): a new #WpCore
*/
WpCore *
wp_core_new (GMainContext *context, WpProperties * properties)
{
@ -301,6 +344,13 @@ wp_core_new (GMainContext *context, WpProperties * properties)
NULL);
}
/**
* wp_core_get_context:
* @self: the core
*
* Returns: (transfer none) (nullable): the #GMainContext that is in use by
* this core for events
*/
GMainContext *
wp_core_get_context (WpCore * self)
{
@ -308,6 +358,12 @@ wp_core_get_context (WpCore * self)
return self->context;
}
/**
* wp_core_get_pw_context:
* @self: the core
*
* Returns: (transfer none): the internal `pw_context` object
*/
struct pw_context *
wp_core_get_pw_context (WpCore * self)
{
@ -315,6 +371,13 @@ wp_core_get_pw_context (WpCore * self)
return self->pw_context;
}
/**
* wp_core_get_pw_core:
* @self: the core
*
* Returns: (transfer none) (nullable): the internal `pw_core` object,
* or %NULL if the core is not connected to PipeWire
*/
struct pw_core *
wp_core_get_pw_core (WpCore * self)
{
@ -322,6 +385,16 @@ wp_core_get_pw_core (WpCore * self)
return self->pw_core;
}
/**
* wp_core_connect:
* @self: the core
*
* Connects this core to the PipeWire server. When connection succeeds,
* the #WpCore::connected signal is emitted
*
* Returns: %TRUE if the core is effectively connected or %FALSE if
* connection failed
*/
gboolean
wp_core_connect (WpCore *self)
{
@ -353,6 +426,14 @@ wp_core_connect (WpCore *self)
return TRUE;
}
/**
* wp_core_disconnect:
* @self: the core
*
* Disconnects this core from the PipeWire server. This also effectively
* destroys all #WpProxy objects that were created through the registry,
* destroys the `pw_core` and finally emits the #WpCore::disconnected signal.
*/
void
wp_core_disconnect (WpCore *self)
{
@ -363,6 +444,12 @@ wp_core_disconnect (WpCore *self)
g_signal_emit (self, signals[SIGNAL_DISCONNECTED], 0);
}
/**
* wp_core_is_connected:
* @self: the core
*
* Returns: %TRUE if the core is connected to PipeWire, %FALSE otherwise
*/
gboolean
wp_core_is_connected (WpCore * self)
{
@ -370,6 +457,20 @@ wp_core_is_connected (WpCore * self)
return self->pw_core != NULL;
}
/**
* wp_core_idle_add:
* @self: the core
* @function: (scope notified): the function to call
* @data: (closure): data to pass to @function
* @destroy: (nullable): a function to destroy @data
*
* Adds an idle callback to be called in the same #GMainContext as the
* one used by this core. This is essentially the same as g_idle_add_full(),
* but it adds the created #GSource on the #GMainContext used by this core
* instead of the default context.
*
* Returns: the ID (greater than 0) of the event source
*/
guint
wp_core_idle_add (WpCore * self, GSourceFunc function, gpointer data,
GDestroyNotify destroy)
@ -384,6 +485,26 @@ wp_core_idle_add (WpCore * self, GSourceFunc function, gpointer data,
return g_source_get_id (source);
}
/**
* wp_core_sync:
* @self: the core
* @cancellable: (nullable): a #GCancellable to cancel the operation
* @callback: (scope async): a function to call when the operation is done
* @user_data: (closure): data to pass to @callback
*
* Asks the PipeWire server to call the @callback via an event.
*
* Since methods are handled in-order and events are delivered
* in-order, this can be used as a barrier to ensure all previous
* methods and the resulting events have been handled.
*
* In both success and error cases, @callback is always called. Use
* wp_core_sync_finish() from within the @callback to determine whether
* the operation completed successfully or if an error occurred.
*
* Returns: %TRUE if the sync operation was started, %FALSE if an error
* occurred before returning from this function
*/
gboolean
wp_core_sync (WpCore * self, GCancellable * cancellable,
GAsyncReadyCallback callback, gpointer user_data)
@ -415,6 +536,17 @@ wp_core_sync (WpCore * self, GCancellable * cancellable,
return TRUE;
}
/**
* wp_core_sync_finish:
* @self: the core
* @res: a #GAsyncResult
* @error: (out) (optional): the error that occurred, if any
*
* This function is meant to be called from within the callback of
* wp_core_sync() in order to determine the success or failure of the operation.
*
* Returns: %TRUE if the operation succeeded, %FALSE otherwise
*/
gboolean
wp_core_sync_finish (WpCore * self, GAsyncResult * res, GError ** error)
{

View file

@ -6,6 +6,24 @@
* SPDX-License-Identifier: MIT
*/
/**
* SECTION: WpDevice
*
* The #WpDevice class allows accessing the properties and methods of a
* PipeWire device object (`struct pw_device`).
*
* A #WpDevice is constructed internally when a new device appears on the
* PipeWire registry and it is made available through the #WpObjectManager API.
* Alternatively, a #WpDevice can also be constructed using
* wp_device_new_from_factory(), which creates a new device object
* on the remote PipeWire server by calling into a factory.
*
* A #WpSpaDevice allows running a `spa_device` object locally,
* loading the implementation from a SPA factory. This is useful to run device
* monitors inside the session manager and have control over creating the
* actual nodes that the `spa_device` requests to create.
*/
#include "device.h"
#include "node.h"
#include "error.h"

View file

@ -15,6 +15,11 @@ G_BEGIN_DECLS
/* WpDevice */
/**
* WP_TYPE_DEVICE:
*
* The #WpDevice #GType
*/
#define WP_TYPE_DEVICE (wp_device_get_type ())
WP_API
G_DECLARE_FINAL_TYPE (WpDevice, wp_device, WP, DEVICE, WpProxy)
@ -25,10 +30,22 @@ WpDevice * wp_device_new_from_factory (WpCore * core,
/* WpSpaDevice */
/**
* WpSpaDeviceFeatures:
* @WP_SPA_DEVICE_FEATURE_ACTIVE: activates the device, making it query the
* hardware and emit the #WpSpaDevice::object-info signal
*
* An extension of #WpProxyFeatures
*/
typedef enum { /*< flags >*/
WP_SPA_DEVICE_FEATURE_ACTIVE = WP_PROXY_FEATURE_LAST,
} WpSpaDeviceFeatures;
/**
* WP_TYPE_SPA_DEVICE:
*
* The #WpSpaDevice #GType
*/
#define WP_TYPE_SPA_DEVICE (wp_spa_device_get_type ())
WP_API
G_DECLARE_FINAL_TYPE (WpSpaDevice, wp_spa_device, WP, SPA_DEVICE, WpProxy)

View file

@ -6,6 +6,21 @@
* SPDX-License-Identifier: MIT
*/
/**
* SECTION: WpEndpoint
*
* The #WpEndpoint class allows accessing the properties and methods of a
* PipeWire endpoint object (`struct pw_endpoint` from the session-manager
* extension).
*
* A #WpEndpoint is constructed internally when a new endpoint appears on the
* PipeWire registry and it is made available through the #WpObjectManager API.
*
* A #WpImplEndpoint allows implementing an endpoint and exporting it to
* PipeWire, which is done by augmenting the #WpImplEndpoint with
* %WP_PROXY_FEATURE_BOUND.
*/
#include "endpoint.h"
#include "private.h"
#include "error.h"
@ -330,11 +345,24 @@ wp_endpoint_class_init (WpEndpointClass * klass)
klass->get_control = get_control;
klass->set_control = set_control;
/**
* WpEndpoint::control-changed:
* @self: the endpoint
* @control: the control that changed (a #WpEndpointControl)
*
* Emitted when an endpoint control changes value
*/
signals[SIGNAL_CONTROL_CHANGED] = g_signal_new (
"control-changed", G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_UINT);
}
/**
* wp_endpoint_get_name:
* @self: the endpoint
*
* Returns: the name of the endpoint
*/
const gchar *
wp_endpoint_get_name (WpEndpoint * self)
{
@ -344,6 +372,12 @@ wp_endpoint_get_name (WpEndpoint * self)
return WP_ENDPOINT_GET_CLASS (self)->get_name (self);
}
/**
* wp_endpoint_get_media_class:
* @self: the endpoint
*
* Returns: the media class of the endpoint (ex. "Audio/Sink")
*/
const gchar *
wp_endpoint_get_media_class (WpEndpoint * self)
{
@ -353,6 +387,12 @@ wp_endpoint_get_media_class (WpEndpoint * self)
return WP_ENDPOINT_GET_CLASS (self)->get_media_class (self);
}
/**
* wp_endpoint_get_direction:
* @self: the endpoint
*
* Returns: the direction of this endpoint
*/
WpDirection
wp_endpoint_get_direction (WpEndpoint * self)
{
@ -362,6 +402,14 @@ wp_endpoint_get_direction (WpEndpoint * self)
return WP_ENDPOINT_GET_CLASS (self)->get_direction (self);
}
/**
* wp_endpoint_get_control:
* @self: the endpoint
* @control_id: the control id (a #WpEndpointControl)
*
* Returns: (transfer none) (nullable): the `spa_pod` containing the value
* of this control, or %NULL if @control_id does not exist on this endpoint
*/
const struct spa_pod *
wp_endpoint_get_control (WpEndpoint * self, guint32 control_id)
{
@ -371,6 +419,15 @@ wp_endpoint_get_control (WpEndpoint * self, guint32 control_id)
return WP_ENDPOINT_GET_CLASS (self)->get_control (self, control_id);
}
/**
* wp_endpoint_get_control_boolean:
* @self: the endpoint
* @control_id: the control id (a #WpEndpointControl)
* @value: (out): the boolean value of this control
*
* Returns: %TRUE on success, %FALSE if the control does not exist on this
* endpoint or if it is not a boolean
*/
gboolean
wp_endpoint_get_control_boolean (WpEndpoint * self, guint32 control_id,
gboolean * value)
@ -384,6 +441,15 @@ wp_endpoint_get_control_boolean (WpEndpoint * self, guint32 control_id,
return FALSE;
}
/**
* wp_endpoint_get_control_int:
* @self: the endpoint
* @control_id: the control id (a #WpEndpointControl)
* @value: (out): the integer value of this control
*
* Returns: %TRUE on success, %FALSE if the control does not exist on this
* endpoint or if it is not an integer
*/
gboolean
wp_endpoint_get_control_int (WpEndpoint * self, guint32 control_id,
gint * value)
@ -392,6 +458,15 @@ wp_endpoint_get_control_int (WpEndpoint * self, guint32 control_id,
return (pod && spa_pod_get_int (pod, value) == 0);
}
/**
* wp_endpoint_get_control_float:
* @self: the endpoint
* @control_id: the control id (a #WpEndpointControl)
* @value: (out): the floating-point number value of this control
*
* Returns: %TRUE on success, %FALSE if the control does not exist on this
* endpoint or if it is not a floating-point number
*/
gboolean
wp_endpoint_get_control_float (WpEndpoint * self, guint32 control_id,
gfloat * value)
@ -400,6 +475,14 @@ wp_endpoint_get_control_float (WpEndpoint * self, guint32 control_id,
return (pod && spa_pod_get_float (pod, value) == 0);
}
/**
* wp_endpoint_set_control:
* @self: the endpoint
* @control_id: the control id (a #WpEndpointControl)
* @value: the new value for this control, as a `spa_pod`
*
* Returns: %TRUE on success, %FALSE if an error occurred
*/
gboolean
wp_endpoint_set_control (WpEndpoint * self, guint32 control_id,
const struct spa_pod * value)
@ -410,6 +493,14 @@ wp_endpoint_set_control (WpEndpoint * self, guint32 control_id,
return WP_ENDPOINT_GET_CLASS (self)->set_control (self, control_id, value);
}
/**
* wp_endpoint_set_control_boolean:
* @self: the endpoint
* @control_id: the control id (a #WpEndpointControl)
* @value: the new value for this control, as a boolean
*
* Returns: %TRUE on success, %FALSE if an error occurred
*/
gboolean
wp_endpoint_set_control_boolean (WpEndpoint * self, guint32 control_id,
gboolean value)
@ -419,6 +510,14 @@ wp_endpoint_set_control_boolean (WpEndpoint * self, guint32 control_id,
buffer, sizeof (buffer), SPA_POD_Bool (value), 0));
}
/**
* wp_endpoint_set_control_int:
* @self: the endpoint
* @control_id: the control id (a #WpEndpointControl)
* @value: the new value for this control, as an integer
*
* Returns: %TRUE on success, %FALSE if an error occurred
*/
gboolean
wp_endpoint_set_control_int (WpEndpoint * self, guint32 control_id,
gint value)
@ -428,6 +527,14 @@ wp_endpoint_set_control_int (WpEndpoint * self, guint32 control_id,
buffer, sizeof (buffer), SPA_POD_Int (value), 0));
}
/**
* wp_endpoint_set_control_float:
* @self: the endpoint
* @control_id: the control id (a #WpEndpointControl)
* @value: the new value for this control, as a floating-point number
*
* Returns: %TRUE on success, %FALSE if an error occurred
*/
gboolean
wp_endpoint_set_control_float (WpEndpoint * self, guint32 control_id,
gfloat value)
@ -647,6 +754,12 @@ wp_impl_endpoint_class_init (WpImplEndpointClass * klass)
endpoint_class->set_control = wp_impl_endpoint_set_control;
}
/**
* wp_impl_endpoint_new:
* @core: the #WpCore
*
* Returns: (transfer full): the newly constructed endpoint implementation
*/
WpImplEndpoint *
wp_impl_endpoint_new (WpCore * core)
{
@ -657,6 +770,18 @@ wp_impl_endpoint_new (WpCore * core)
NULL);
}
/**
* wp_impl_endpoint_set_property:
* @self: the endpoint implementation
* @key: a property key
* @value: a property value
*
* Sets the specified property on the PipeWire properties of the endpoint.
*
* If this property is set before exporting the endpoint, then it is also used
* in the construction process of the endpoint object and appears as a global
* property.
*/
void
wp_impl_endpoint_set_property (WpImplEndpoint * self,
const gchar * key, const gchar * value)
@ -677,6 +802,18 @@ wp_impl_endpoint_set_property (WpImplEndpoint * self,
}
}
/**
* wp_impl_endpoint_update_properties:
* @self: the endpoint implementation
* @updates: a set of properties to add or update in the endpoint's properties
*
* Adds or updates the values of the PipeWire properties of the endpoint
* using the properties in @updates as a source.
*
* If the properties are set before exporting the endpoint, then they are also
* used in the construction process of the endpoint object and appear as
* global properties.
*/
void
wp_impl_endpoint_update_properties (WpImplEndpoint * self,
WpProperties * updates)
@ -698,6 +835,15 @@ wp_impl_endpoint_update_properties (WpImplEndpoint * self,
}
}
/**
* wp_impl_endpoint_set_name:
* @self: the endpoint implementation
* @name: the name to set
*
* Sets the name of the endpoint to be @name.
*
* This only makes sense to set before exporting the endpoint.
*/
void
wp_impl_endpoint_set_name (WpImplEndpoint * self, const gchar * name)
{
@ -710,6 +856,15 @@ wp_impl_endpoint_set_name (WpImplEndpoint * self, const gchar * name)
priv->info.name = g_strdup (name);
}
/**
* wp_impl_endpoint_set_media_class:
* @self: the endpoint implementation
* @media_class: the media class to set
*
* Sets the media class of the endpoint to be @media_class.
*
* This only makes sense to set before exporting the endpoint.
*/
void
wp_impl_endpoint_set_media_class (WpImplEndpoint * self,
const gchar * media_class)
@ -723,6 +878,15 @@ wp_impl_endpoint_set_media_class (WpImplEndpoint * self,
priv->info.media_class = g_strdup (media_class);
}
/**
* wp_impl_endpoint_set_direction:
* @self: the endpoint implementation
* @dir: the direction to set
*
* Sets the direction of the endpoint to be @dir.
*
* This only makes sense to set before exporting the endpoint.
*/
void
wp_impl_endpoint_set_direction (WpImplEndpoint * self, WpDirection dir)
{
@ -734,6 +898,17 @@ wp_impl_endpoint_set_direction (WpImplEndpoint * self, WpDirection dir)
priv->info.direction = (enum pw_direction) dir;
}
/**
* wp_impl_endpoint_register_control:
* @self: the endpoint implementation
* @control: the control to make available
*
* Registers the specified @control as a SPA property of this endpoint,
* making it appear to remote clients.
*
* This is required to do before setting or getting a value for this control.
* This is also required to be done before exporting the endpoint.
*/
void
wp_impl_endpoint_register_control (WpImplEndpoint * self,
WpEndpointControl control)

View file

@ -25,18 +25,35 @@ typedef enum {
WP_DIRECTION_OUTPUT,
} WpDirection;
/**
* WpEndpointControl:
* @WP_ENDPOINT_CONTROL_VOLUME: a volume control (type: float)
* @WP_ENDPOINT_CONTROL_MUTE: a mute control (type: boolean)
* @WP_ENDPOINT_CONTROL_CHANNEL_VOLUMES:
*/
typedef enum {
WP_ENDPOINT_CONTROL_VOLUME = 0x10003 /* SPA_PROP_volume */,
WP_ENDPOINT_CONTROL_MUTE = 0x10004 /* SPA_PROP_mute */,
WP_ENDPOINT_CONTROL_CHANNEL_VOLUMES = 0x10008 /* SPA_PROP_channelVolumes */,
} WpEndpointControl;
/**
* WpEndpointFeatures:
* @WP_ENDPOINT_FEATURE_CONTROLS: enables the use of the
* wp_endpoint_get_control() and wp_endpoint_set_control() families of
* functions to be able to work with endpoint-specific controls
*
* An extension of #WpProxyFeatures
*/
typedef enum { /*< flags >*/
WP_ENDPOINT_FEATURE_CONTROLS = WP_PROXY_FEATURE_LAST,
} WpEndpointFeatures;
/* WpEndpoint */
/**
* WP_TYPE_ENDPOINT:
*
* The #WpEndpoint #GType
*/
#define WP_TYPE_ENDPOINT (wp_endpoint_get_type ())
WP_API
G_DECLARE_DERIVABLE_TYPE (WpEndpoint, wp_endpoint, WP, ENDPOINT, WpProxy)
@ -95,8 +112,11 @@ WP_API
gboolean wp_endpoint_set_control_float (WpEndpoint * self, guint32 control_id,
gfloat value);
/* WpImplEndpoint */
/**
* WP_TYPE_IMPL_ENDPOINT:
*
* The #WpImplEndpoint #GType
*/
#define WP_TYPE_IMPL_ENDPOINT (wp_impl_endpoint_get_type ())
WP_API
G_DECLARE_DERIVABLE_TYPE (WpImplEndpoint, wp_impl_endpoint,

View file

@ -6,6 +6,15 @@
* SPDX-License-Identifier: MIT
*/
/**
* SECTION: Error
*
* Error domain and codes for #GError
*/
#include "error.h"
/**
* wp_domain_library_quark:
*/
G_DEFINE_QUARK (wireplumber-library, wp_domain_library);

View file

@ -14,10 +14,26 @@
G_BEGIN_DECLS
/**
* WP_DOMAIN_LIBRARY:
*
* A #GError domain for errors that occurred within the context of the
* WirePlumber library.
*/
#define WP_DOMAIN_LIBRARY (wp_domain_library_quark ())
WP_API
GQuark wp_domain_library_quark (void);
#define WP_DOMAIN_LIBRARY (wp_domain_library_quark ())
/**
* WpLibraryErrorEnum:
* @WP_LIBRARY_ERROR_INVARIANT: an invariant check failed; this most likely
* indicates a programming error
* @WP_LIBRARY_ERROR_INVALID_ARGUMENT: an unexpected/invalid argument was given
* @WP_LIBRARY_ERROR_OPERATION_FAILED: an operation failed
*
* Error codes that can appear in a #GError when the error domain
* is %WP_DOMAIN_LIBRARY
*/
typedef enum {
WP_LIBRARY_ERROR_INVARIANT,
WP_LIBRARY_ERROR_INVALID_ARGUMENT,

View file

@ -6,6 +6,13 @@
* SPDX-License-Identifier: MIT
*/
/**
* SECTION: WpFactory
*
* The #WpFactory class allows associating a function that is able to construct
* objects with a well-known name that is registered on the #WpCore
*/
#include "factory.h"
#include "private.h"
@ -77,6 +84,12 @@ wp_factory_new (WpCore * core, const gchar * name, WpFactoryFunc func)
return f;
}
/**
* wp_factory_get_name:
* @self: the factory
*
* Returns: the factory name
*/
const gchar *
wp_factory_get_name (WpFactory * self)
{
@ -95,6 +108,17 @@ wp_factory_get_core (WpFactory * self)
return g_weak_ref_get (&self->core);
}
/**
* wp_factory_create_object:
* @self: the factory
* @type: the object type to construct
* @properties: a dictionary ("a{sv}") variant with additional properties
* @ready: (scope async): a callback to call when the object is constructed
* and ready
* @user_data: (closure): data to pass to @ready
*
* Calls the #WpFactoryFunc of this factory
*/
void
wp_factory_create_object (WpFactory * self, GType type,
GVariant * properties, GAsyncReadyCallback ready, gpointer user_data)
@ -129,6 +153,20 @@ wp_factory_find (WpCore * core, const gchar * name)
return f ? WP_FACTORY (f) : NULL;
}
/**
* wp_factory_make:
* @core: the #WpCore
* @name: the name of the factory to be used for constructing the object
* @type: the object type to construct
* @properties: a dictionary ("a{sv}") variant with additional properties
* @ready: (scope async): a callback to call when the object is constructed
* and ready
* @user_data: (closure): data to pass to @ready
*
* Finds the factory associated with the given @name from the @core and
* calls its #WpFactoryFunc with the rest of the arguments to create
* an object. The new object is notified through the @ready callback.
*/
void
wp_factory_make (WpCore * core, const gchar * name, GType type,
GVariant * properties, GAsyncReadyCallback ready, gpointer user_data)

View file

@ -15,10 +15,27 @@
G_BEGIN_DECLS
/**
* WP_TYPE_FACTORY:
*
* The #WpFactory #GType
*/
#define WP_TYPE_FACTORY (wp_factory_get_type ())
WP_API
G_DECLARE_FINAL_TYPE (WpFactory, wp_factory, WP, FACTORY, GObject)
/**
* WpFactoryFunc:
* @self: the factory
* @type: the object type to construct
* @properties: a dictionary ("a{sv}") variant with additional properties
* @ready: (scope async): a callback to call when the object is constructed
* and ready
* @user_data: (closure): data to pass to @ready
*
* A function that constructs an object. Object creation is meant to be
* asynchronous and notified through the @ready callback.
*/
typedef void (*WpFactoryFunc) (WpFactory * self, GType type,
GVariant * properties, GAsyncReadyCallback ready, gpointer user_data);

View file

@ -6,6 +6,19 @@
* SPDX-License-Identifier: MIT
*/
/**
* SECTION: WpLink
*
* The #WpLink class allows accessing the properties and methods of a
* PipeWire link object (`struct pw_link`).
*
* A #WpLink is constructed internally when a new link appears on the
* PipeWire registry and it is made available through the #WpObjectManager API.
* Alternatively, a #WpLink can also be constructed using
* wp_link_new_from_factory(), which creates a new link object
* on the remote PipeWire server by calling into a factory.
*/
#include "link.h"
#include "private.h"

View file

@ -13,6 +13,11 @@
G_BEGIN_DECLS
/**
* WP_TYPE_LINK:
*
* The #WpLink #GType
*/
#define WP_TYPE_LINK (wp_link_get_type ())
WP_API
G_DECLARE_FINAL_TYPE (WpLink, wp_link, WP, LINK, WpProxy)

View file

@ -6,6 +6,39 @@
* SPDX-License-Identifier: MIT
*/
/**
* SECTION: WpModule
*
* A module is a shared library that can be loaded dynamically in the
* WirePlumber daemon process, adding functionality to the daemon.
*
* For every module that is loaded, WirePlumber constructs a #WpModule object
* that gets registered on the #WpCore and can be retrieved through the
* #WpObjectManager API.
*
* Every module has to conform to a certain interface in order for WirePlumber
* to know how to load it. This interface is called "ABI" in #WpModule.
* Currently there is only one possible ABI, the "C" one.
*
* ### Writing modules in C
*
* In order to define a module in C, you need to implement a function in
* your shared library that has this signature:
*
* |[
* WP_PLUGIN_EXPORT void
* wireplumber__module_init (WpModule * module, WpCore * core, GVariant * args)
* ]|
*
* This function will be called once at the time of loading the module. The
* @args parameter is a dictionary ("a{sv}") #GVariant that contains arguments
* for this module that were specified in WirePlumber's configuration file.
* The @module parameter is useful for registering a destroy callback (using
* wp_module_set_destroy_callback()), which will be called at the time the
* module is destroyed (when WirePlumber quits) and allows you to free any
* resources that the module has allocated.
*/
#include "module.h"
#include "error.h"
#include "private.h"
@ -114,7 +147,7 @@ wp_module_load_c (WpModule * self, WpCore * core,
* @core: the core
* @abi: the abi name of the module
* @module_name: the module name
* @args: the args passed to the module
* @args: additional properties passed to the module ("a{sv}")
* @error: return location for errors, or NULL to ignore
*
* Returns: (transfer none): the loaded module
@ -145,6 +178,12 @@ wp_module_load (WpCore * core, const gchar * abi, const gchar * module_name,
return module;
}
/**
* wp_module_get_properties:
* @self: the module
*
* Returns: (transfer none): the properties of the module ("a{sv}")
*/
GVariant *
wp_module_get_properties (WpModule * self)
{
@ -163,6 +202,14 @@ wp_module_get_core (WpModule * self)
return g_weak_ref_get (&self->core);
}
/**
* wp_module_set_destroy_callback:
* @self: the module
* @callback: (scope async): a function to call when the module is destroyed
* @data: (closure): data to pass to @callback
*
* Registers a @callback to call when the module object is destroyed
*/
void
wp_module_set_destroy_callback (WpModule * self, GDestroyNotify callback,
gpointer data)

View file

@ -13,6 +13,11 @@
G_BEGIN_DECLS
/**
* WP_TYPE_MODULE:
*
* The #WpModule #GType
*/
#define WP_TYPE_MODULE (wp_module_get_type ())
WP_API
G_DECLARE_FINAL_TYPE (WpModule, wp_module, WP, MODULE, GObject)
@ -22,13 +27,13 @@ WpModule * wp_module_load (WpCore * core, const gchar * abi,
const gchar * module_name, GVariant * args, GError ** error);
WP_API
GVariant * wp_module_get_properties (WpModule * module);
GVariant * wp_module_get_properties (WpModule * self);
WP_API
WpCore * wp_module_get_core (WpModule * self);
WP_API
void wp_module_set_destroy_callback (WpModule * module, GDestroyNotify callback,
void wp_module_set_destroy_callback (WpModule * self, GDestroyNotify callback,
gpointer data);
G_END_DECLS

View file

@ -6,6 +6,25 @@
* SPDX-License-Identifier: MIT
*/
/**
* SECTION: WpNode
*
* The #WpNode class allows accessing the properties and methods of a
* PipeWire node object (`struct pw_node`).
*
* A #WpNode is constructed internally when a new node appears on the
* PipeWire registry and it is made available through the #WpObjectManager API.
* Alternatively, a #WpNode can also be constructed using
* wp_node_new_from_factory(), which creates a new node object
* on the remote PipeWire server by calling into a factory.
*
* A #WpImplNode allows running a node implementation (`struct pw_impl_node`)
* locally, loading the implementation from factory or wrapping a manually
* constructed `pw_impl_node`. This object can then be exported to PipeWire
* by requesting %WP_PROXY_FEATURE_BOUND and be used as if it was a #WpNode
* proxy to a remote object.
*/
#include "node.h"
#include "error.h"
#include "private.h"

View file

@ -15,6 +15,11 @@ G_BEGIN_DECLS
struct pw_impl_node;
/**
* WP_TYPE_NODE:
*
* The #WpNode #GType
*/
#define WP_TYPE_NODE (wp_node_get_type ())
WP_API
G_DECLARE_DERIVABLE_TYPE (WpNode, wp_node, WP, NODE, WpProxy)
@ -28,7 +33,11 @@ WP_API
WpNode * wp_node_new_from_factory (WpCore * core,
const gchar * factory_name, WpProperties * properties);
/**
* WP_TYPE_IMPL_NODE:
*
* The #WpImplNode #GType
*/
#define WP_TYPE_IMPL_NODE (wp_impl_node_get_type ())
WP_API
G_DECLARE_FINAL_TYPE (WpImplNode, wp_impl_node, WP, IMPL_NODE, WpNode)

View file

@ -6,6 +6,37 @@
* 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>
@ -125,25 +156,112 @@ wp_object_manager_class_init (WpObjectManagerClass * klass)
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:
*
* Constructs a new object manager.
*
* Returns: (transfer full): the newly constructed object manager
*/
WpObjectManager *
wp_object_manager_new (void)
{
return g_object_new (WP_TYPE_OBJECT_MANAGER, NULL);
}
/**
* wp_object_manager_add_interest:
* @self: the object manager
* @gtype: the #GType of the objects that we are declaring interest in
* @constraints: (nullable): a variant of type "aa{sv}" (array of dictionaries)
* with additional constraints on the managed objects
* @wanted_features: a set of features that will automatically be enabled
* on managed objects, if they are subclasses of #WpProxy
*
* Declares interest in a certain kind of object. Interest consists of a #GType
* that the object must be an ancestor of (g_type_is_a must match) and
* optionally, a set of additional constraints on certain properties of the
* object.
*
* The @constraints #GVariant should contain an array of dictionaries ("aa{sv}").
* Each dictionary must have the following fields:
* - "type" (i): The constraint type, #WpObjectManagerConstraintType
* - "name" (s): The name of the constrained property
* - "value" (s): The value that the property must have
*
* For example, to discover all the 'node' objects in the PipeWire graph,
* the following code can be used:
* |[
* WpObjectManager *om = wp_object_manager_new ();
* wp_object_manager_add_interest (om, WP_TYPE_NODE, NULL,
* WP_PROXY_FEATURES_STANDARD);
* wp_core_install_object_manager (core, om);
* GPtrArray *nodes = wp_object_manager_get_objects (om, 0);
* ]|
*
* and to discover all 'port' objects that belong to a specific 'node':
* |[
* WpObjectManager *om = wp_object_manager_new ();
*
* GVariantBuilder b;
* g_variant_builder_init (&b, G_VARIANT_TYPE ("aa{sv}"));
* g_variant_builder_open (&b, G_VARIANT_TYPE_VARDICT);
* g_variant_builder_add (&b, "{sv}", "type",
* g_variant_new_int32 (WP_OBJECT_MANAGER_CONSTRAINT_PW_GLOBAL_PROPERTY));
* g_variant_builder_add (&b, "{sv}", "name",
* g_variant_new_string (PW_KEY_NODE_ID));
* g_variant_builder_add (&b, "{sv}", "value",
* g_variant_new_string (node_id));
* g_variant_builder_close (&b);
*
* wp_object_manager_add_interest (om, WP_TYPE_PORT,
* g_variant_builder_end (&b),
* WP_PROXY_FEATURES_STANDARD);
*
* wp_core_install_object_manager (core, om);
* GPtrArray *ports = wp_object_manager_get_objects (om, 0);
* ]|
*/
void
wp_object_manager_add_interest (WpObjectManager *self,
GType gtype, GVariant * constraints,
@ -166,7 +284,7 @@ wp_object_manager_add_interest (WpObjectManager *self,
* wp_object_manager_get_objects:
* @self: the object manager
* @type_filter: a #GType filter to get only the objects that are of this type,
* or 0 to return all the objects
* or 0 ( %G_TYPE_INVALID ) to return all the objects
*
* Returns: (transfer full) (element-type GObject*): all the objects managed
* by this #WpObjectManager that match the @type_filter
@ -863,8 +981,8 @@ wp_registry_remove_object (WpRegistry *reg, gpointer obj)
}
/**
* wp_core_install_object_manager: (method)
* @core: the core
* wp_core_install_object_manager:
* @self: the core
* @om: (transfer none): a #WpObjectManager
*
* Installs the object manager on this core, activating its internal management
@ -872,19 +990,19 @@ wp_registry_remove_object (WpRegistry *reg, gpointer obj)
* if objects that the @om is interested in were in existence already.
*/
void
wp_core_install_object_manager (WpCore * core, WpObjectManager * om)
wp_core_install_object_manager (WpCore * self, WpObjectManager * om)
{
WpRegistry *reg;
guint i;
g_return_if_fail (WP_IS_CORE (core));
g_return_if_fail (WP_IS_CORE (self));
g_return_if_fail (WP_IS_OBJECT_MANAGER (om));
reg = wp_core_get_registry (core);
reg = wp_core_get_registry (self);
g_object_weak_ref (G_OBJECT (om), object_manager_destroyed, reg);
g_ptr_array_add (reg->object_managers, om);
g_object_set (om, "core", core, NULL);
g_object_set (om, "core", self, NULL);
/* add pre-existing objects to the object manager,
in case it's interested in them */

View file

@ -14,12 +14,28 @@
G_BEGIN_DECLS
/**
* WpObjectManagerConstraintType:
* @WP_OBJECT_MANAGER_CONSTRAINT_PW_GLOBAL_PROPERTY: constraint applies
* to a PipeWire global property of an object (the ones returned by
* wp_proxy_get_global_properties())
* @WP_OBJECT_MANAGER_CONSTRAINT_PW_PROPERTY: constraint applies
* to a PipeWire property of the object (the ones returned by
* wp_proxy_get_properties())
* @WP_OBJECT_MANAGER_CONSTRAINT_G_PROPERTY: constraint applies to a #GObject
* property of the managed object
*/
typedef enum {
WP_OBJECT_MANAGER_CONSTRAINT_PW_GLOBAL_PROPERTY,
WP_OBJECT_MANAGER_CONSTRAINT_PW_PROPERTY,
WP_OBJECT_MANAGER_CONSTRAINT_G_PROPERTY,
} WpObjectManagerConstraintType;
/**
* WP_TYPE_OBJECT_MANAGER:
*
* The #WpObjectManager #GType
*/
#define WP_TYPE_OBJECT_MANAGER (wp_object_manager_get_type ())
WP_API
G_DECLARE_FINAL_TYPE (WpObjectManager, wp_object_manager, WP, OBJECT_MANAGER, GObject)

View file

@ -6,6 +6,10 @@
* SPDX-License-Identifier: MIT
*/
/**
* SECTION: WpPolicy
*/
#include <pipewire/pipewire.h>
#include "policy.h"
@ -134,6 +138,12 @@ wp_policy_manager_get_instance (WpCore *core)
return mgr;
}
/**
* wp_policy_manager_get_session:
* @self: the policy manager
*
* Returns: (transfer full) (nullable): the active session
*/
WpSession *
wp_policy_manager_get_session (WpPolicyManager *self)
{

View file

@ -34,10 +34,20 @@ typedef enum {
WP_POLICY_RANK_VENDOR = 256,
} WpPolicyRank;
/**
* WP_TYPE_POLICY_MANAGER:
*
* The #WpPolicyManager #GType
*/
#define WP_TYPE_POLICY_MANAGER (wp_policy_manager_get_type ())
WP_API
G_DECLARE_FINAL_TYPE (WpPolicyManager, wp_policy_manager, WP, POLICY_MANAGER, GObject)
/**
* WP_TYPE_POLICY:
*
* The #WpPolicy #GType
*/
#define WP_TYPE_POLICY (wp_policy_get_type ())
WP_API
G_DECLARE_DERIVABLE_TYPE (WpPolicy, wp_policy, WP, POLICY, GObject)

View file

@ -6,11 +6,24 @@
* SPDX-License-Identifier: MIT
*/
/**
* SECTION: WpPort
*
* The #WpPort class allows accessing the properties and methods of a
* PipeWire port object (`struct pw_port`).
*
* A #WpPort is constructed internally when a new port appears on the
* PipeWire registry and it is made available through the #WpObjectManager API.
*/
#include "port.h"
#include "private.h"
#include <pipewire/pipewire.h>
/**
* WpPort:
*/
struct _WpPort
{
WpProxy parent;

View file

@ -13,6 +13,11 @@
G_BEGIN_DECLS
/**
* WP_TYPE_PORT:
*
* The #WpPort #GType
*/
#define WP_TYPE_PORT (wp_port_get_type ())
WP_API
G_DECLARE_FINAL_TYPE (WpPort, wp_port, WP, PORT, WpProxy)

View file

@ -6,6 +6,37 @@
* SPDX-License-Identifier: MIT
*/
/**
* SECTION: WpProperties
*
* #WpProperties is a data structure that contains string key-value pairs,
* which are used to send/receive/attach arbitrary properties to PipeWire
* objects.
*
* This could be thought of as a hash table with strings as both keys and
* values. However, the reason that this class exists instead of using
* #GHashTable directly is that in reality it wraps the PipeWire native
* `struct spa_dict` and `struct pw_properties` and therefore it can be
* easily passed to PipeWire function calls that require a `struct spa_dict *`
* or a `struct pw_properties *` as arguments. Or alternatively, it can easily
* wrap a `struct spa_dict *` or a `struct pw_properties *` that was given
* from the PipeWire API without necessarily doing an expensive copy operation.
*
* #WpProperties normally wraps a `struct pw_properties`, unless it was created
* with wp_properties_new_wrap_dict(), in which case it wraps a
* `struct spa_dict` and it is immutable (you cannot add/remove/modify any
* key-value pair).
*
* In most cases, it actually owns the `struct pw_properties`
* internally and manages its lifetime. The exception to that rule is when
* #WpProperties is constructed with wp_properties_new_wrap(), in which case
* the ownership of the `struct pw_properties` remains outside. This must
* be used with care, as the `struct pw_properties` may be free'ed externally.
*
* #WpProperties is reference-counted with wp_properties_ref() and
* wp_properties_unref().
*/
#include "properties.h"
#include <errno.h>
@ -27,6 +58,13 @@ struct _WpProperties
G_DEFINE_BOXED_TYPE(WpProperties, wp_properties, wp_properties_ref, wp_properties_unref)
/**
* wp_properties_new_empty:
*
* Creates a new empty properties set
*
* Returns: (transfer full): the newly constructed properties set
*/
WpProperties *
wp_properties_new_empty (void)
{
@ -36,6 +74,16 @@ wp_properties_new_empty (void)
return self;
}
/**
* wp_properties_new:
* @key: a property name
* @...: a property value, followed by any number of further property
* key-value pairs, followed by %NULL
*
* Constructs a new properties set that contains the given properties
*
* Returns: (transfer full): the newly constructed properties set
*/
WpProperties *
wp_properties_new (const gchar * key, ...)
{
@ -49,22 +97,41 @@ wp_properties_new (const gchar * key, ...)
return self;
}
/**
* wp_properties_new_valist:
* @key: a property name
* @args: the variable arguments passed to wp_properties_new()
*
* This is the `va_list` version of wp_properties_new()
*
* Returns: (transfer full): the newly constructed properties set
*/
WpProperties *
wp_properties_new_valist (const gchar * key, va_list varargs)
wp_properties_new_valist (const gchar * key, va_list args)
{
WpProperties * self = wp_properties_new_empty ();
const gchar *value;
while (key != NULL) {
value = va_arg(varargs, gchar *);
value = va_arg(args, gchar *);
if (value && key[0])
wp_properties_set (self, key, value);
key = va_arg(varargs, gchar *);
key = va_arg(args, gchar *);
}
return self;
}
/**
* wp_properties_new_string:
* @str: a string containing a whitespace separated list of key=value pairs
* (ex. "key1=value1 key2=value2")
*
* Constructs a new properties set that contains the properties that can
* be parsed from the given string
*
* Returns: (transfer full): the newly constructed properties set
*/
WpProperties *
wp_properties_new_string (const gchar * str)
{
@ -78,6 +145,21 @@ wp_properties_new_string (const gchar * str)
return self;
}
/**
* wp_properties_new_wrap:
* @props: a native `pw_properties` structure to wrap
*
* Constructs a new #WpProperties that wraps the given @props structure,
* allowing reading & writing properties on that @props structure through
* the #WpProperties API.
*
* Care must be taken when using this function, since the returned #WpProperties
* object does not own the @props structure. Therefore, if the owner decides
* to free @props, the returned #WpProperties will crash when used. In addition,
* the returned #WpProperties object will not try to free @props when destroyed.
*
* Returns: (transfer full): the newly constructed properties set
*/
WpProperties *
wp_properties_new_wrap (struct pw_properties * props)
{
@ -91,6 +173,19 @@ wp_properties_new_wrap (struct pw_properties * props)
return self;
}
/**
* wp_properties_new_take:
* @props: a native `pw_properties` structure to wrap
*
* Constructs a new #WpProperties that wraps the given @props structure,
* allowing reading & writing properties on that @props structure through
* the #WpProperties API.
*
* In constrast with wp_properties_new_wrap(), this function assumes ownership
* of the @props structure, so it will try to free @props when it is destroyed.
*
* Returns: (transfer full): the newly constructed properties set
*/
WpProperties *
wp_properties_new_take (struct pw_properties * props)
{
@ -104,6 +199,15 @@ wp_properties_new_take (struct pw_properties * props)
return self;
}
/**
* wp_properties_new_copy:
* @props: a native `pw_properties` structure to copy
*
* Constructs a new #WpProperties that contains a copy of all the properties
* contained in the given @props structure.
*
* Returns: (transfer full): the newly constructed properties set
*/
WpProperties *
wp_properties_new_copy (const struct pw_properties * props)
{
@ -117,6 +221,23 @@ wp_properties_new_copy (const struct pw_properties * props)
return self;
}
/**
* wp_properties_new_wrap_dict:
* @dict: a native `spa_dict` structure to wrap
*
* Constructs a new #WpProperties that wraps the given @dict structure,
* allowing reading properties from that @dict through the #WpProperties API.
*
* Note that the returned object does not own the @dict, so care must be taken
* not to free it externally while this #WpProperties object is alive.
*
* In addition, note that the returned #WpProperties object is immutable. That
* means that you cannot add or modify any properties on it, since there is
* no defined method for modifying a `struct spa_dict`. If you need to change
* this properties set later, you should make a copy with wp_properties_copy().
*
* Returns: (transfer full): the newly constructed properties set
*/
WpProperties *
wp_properties_new_wrap_dict (const struct spa_dict * dict)
{
@ -130,6 +251,15 @@ wp_properties_new_wrap_dict (const struct spa_dict * dict)
return self;
}
/**
* wp_properties_new_copy_dict:
* @dict: a native `spa_dict` structure to copy
*
* Constructs a new #WpProperties that contains a copy of all the properties
* contained in the given @dict structure.
*
* Returns: (transfer full): the newly constructed properties set
*/
WpProperties *
wp_properties_new_copy_dict (const struct spa_dict * dict)
{
@ -143,6 +273,15 @@ wp_properties_new_copy_dict (const struct spa_dict * dict)
return self;
}
/**
* wp_properties_copy:
* @other: a properties object
*
* Constructs and returns a new #WpProperties object that contains a copy
* of all the properties contained in @other.
*
* Returns: (transfer full): the newly constructed properties set
*/
WpProperties *
wp_properties_copy (WpProperties * other)
{
@ -156,18 +295,42 @@ wp_properties_free (WpProperties * self)
pw_properties_free (self->props);
}
/**
* wp_properties_ref:
* @self: a properties object
*
* Returns: (transfer full): @self with an additional reference count on it
*/
WpProperties *
wp_properties_ref (WpProperties * self)
{
return g_rc_box_acquire (self);
}
/**
* wp_properties_unref:
* @self: (transfer full): a properties object
*
* Decreases the reference count on @self and frees it when the ref count
* reaches zero.
*/
void
wp_properties_unref (WpProperties * self)
{
g_rc_box_release_full (self, (GDestroyNotify) wp_properties_free);
}
/**
* wp_properties_update_from_dict:
* @self: a properties object
* @dict: a `spa_dict` that contains properties to update
*
* Updates (adds new or modifies existing) properties in @self, using the
* given @dict as a source. Any properties that are not contained in @dict
* are left untouched.
*
* Returns: the number of properties that were changed
*/
gint
wp_properties_update_from_dict (WpProperties * self,
const struct spa_dict * dict)
@ -178,6 +341,17 @@ wp_properties_update_from_dict (WpProperties * self,
return pw_properties_update (self->props, dict);
}
/**
* wp_properties_copy_keys:
* @src: the source properties set
* @dst: the destination properties set
* @key1: a property to copy
* @...: a list of additional properties to copy, followed by %NULL
*
* Copies the specified properties from @src to @dst.
*
* Returns: the number of properties that were changed
*/
gint
wp_properties_copy_keys (WpProperties * src, WpProperties * dst,
const gchar *key1, ...)
@ -190,6 +364,17 @@ wp_properties_copy_keys (WpProperties * src, WpProperties * dst,
return ret;
}
/**
* wp_properties_copy_keys_valist:
* @src: the source properties set
* @dst: the destination properties set
* @key1: a property to copy
* @args: the variable arguments passed to wp_properties_copy_keys()
*
* This is the `va_list` version of wp_properties_copy_keys()
*
* Returns: the number of properties that were changed
*/
gint
wp_properties_copy_keys_valist (WpProperties * src, WpProperties * dst,
const gchar *key1, va_list args)
@ -204,6 +389,14 @@ wp_properties_copy_keys_valist (WpProperties * src, WpProperties * dst,
return changed;
}
/**
* wp_properties_copy_all:
* @src: the source properties set
* @dst: the destination properties set
*
* Copies all the properties contained in @src into @dst
*/
void
wp_properties_copy_all (WpProperties * src, WpProperties * dst)
{
@ -219,6 +412,14 @@ wp_properties_copy_all (WpProperties * src, WpProperties * dst)
}
}
/**
* wp_properties_get:
* @self: a properties object
* @key: a property key
*
* Returns: (transfer none) (nullable): the value of the property identified
* with @key, or %NULL if this property is not contained in @self
*/
const gchar *
wp_properties_get (WpProperties * self, const gchar * key)
{
@ -228,6 +429,21 @@ wp_properties_get (WpProperties * self, const gchar * key)
return spa_dict_lookup (wp_properties_peek_dict (self), key);
}
/**
* wp_properties_set:
* @self: a properties object
* @key: a property key
* @value: (nullable): a property value
*
* Sets the given property @key - @value pair on @self. If the property
* already existed, the value is overwritten with the new one.
*
* If the @value is %NULL, then the specified property is removed from @self
*
* Returns: %1 if the property was changed. %0 if nothing was changed because
* the property already existed with the same value or because the key to
* remove did not exist.
*/
gint
wp_properties_set (WpProperties * self, const gchar * key,
const gchar * value)
@ -238,6 +454,20 @@ wp_properties_set (WpProperties * self, const gchar * key,
return pw_properties_set (self->props, key, value);
}
/**
* wp_properties_setf:
* @self: a properties object
* @key: a property key
* @format: a printf-style format to be formatted and set as a value for
* this property @key
* @...: arguments for @format
*
* Formats the given @format string with the specified arguments and sets the
* result as a value of the property specified with @key
*
* Returns: %1 if the property was changed. %0 if nothing was changed because
* the property already existed with the same value
*/
gint
wp_properties_setf (WpProperties * self, const gchar * key,
const gchar * format, ...)
@ -252,6 +482,19 @@ wp_properties_setf (WpProperties * self, const gchar * key,
return res;
}
/**
* wp_properties_setf_valist:
* @self: a properties object
* @key: a property key
* @format: a printf-style format to be formatted and set as a value for
* this property @key
* @args: the variable arguments passed to wp_properties_setf()
*
* This is the `va_list` version of wp_properties_setf()
*
* Returns: %1 if the property was changed. %0 if nothing was changed because
* the property already existed with the same value
*/
gint
wp_properties_setf_valist (WpProperties * self, const gchar * key,
const gchar * format, va_list args)
@ -262,6 +505,12 @@ wp_properties_setf_valist (WpProperties * self, const gchar * key,
return pw_properties_setva (self->props, key, format, args);
}
/**
* wp_properties_peek_dict:
* @self: a properties object
*
* Returns: (transfer none): the internal properties set as a `struct spa_dict *`
*/
const struct spa_dict *
wp_properties_peek_dict (WpProperties * self)
{
@ -270,6 +519,13 @@ wp_properties_peek_dict (WpProperties * self)
return (self->flags & FLAG_IS_DICT) ? self->dict : &self->props->dict;
}
/**
* wp_properties_to_pw_properties:
* @self: a properties object
*
* Returns: (transfer full): a copy of the properties in @self
* as a `struct pw_properties`
*/
struct pw_properties *
wp_properties_to_pw_properties (WpProperties * self)
{
@ -278,6 +534,23 @@ wp_properties_to_pw_properties (WpProperties * self)
return pw_properties_new_dict (wp_properties_peek_dict (self));
}
/**
* wp_properties_matches:
* @self: a properties object
* @other: a set of properties to match
*
* Checks if the property values contained in @other are matching with the
* values in @self.
*
* If a property is contained in one set and not the other, the result is not
* affected. If a property is contained in both sets, then the value of the
* property in @other is interpreted as a glob-style pattern
* (using g_pattern_match_simple()) and the value in @self is checked to
* see if it matches with this pattern.
*
* Returns: %TRUE if all matches were successfull, %FALSE if at least one
* property value did not match
*/
gboolean
wp_properties_matches (WpProperties * self, WpProperties *other)
{
@ -287,7 +560,7 @@ wp_properties_matches (WpProperties * self, WpProperties *other)
g_return_val_if_fail (self != NULL, FALSE);
/* Check if the property vakues matches the ones from 'other' */
/* Check if the property values match the ones from 'other' */
dict = wp_properties_peek_dict (self);
spa_dict_for_each(item, dict) {
value = wp_properties_get (other, item->key);

View file

@ -17,6 +17,11 @@ G_BEGIN_DECLS
struct pw_properties;
struct spa_dict;
/**
* WP_TYPE_PROPERTIES:
*
* The #WpProperties #GType
*/
#define WP_TYPE_PROPERTIES (wp_properties_get_type ())
WP_API
GType wp_properties_get_type (void);

View file

@ -7,6 +7,11 @@
* SPDX-License-Identifier: MIT
*/
/**
* SECTION: WpProxy
*
*/
#include "proxy.h"
#include "core.h"
#include "error.h"

View file

@ -50,12 +50,22 @@ typedef enum { /*< flags >*/
#define WP_PROXY_FEATURES_STANDARD \
(WP_PROXY_FEATURE_PW_PROXY | WP_PROXY_FEATURE_INFO | WP_PROXY_FEATURE_BOUND)
/**
* WP_TYPE_PROXY:
*
* The #WpProxy #GType
*/
#define WP_TYPE_PROXY (wp_proxy_get_type ())
WP_API
G_DECLARE_DERIVABLE_TYPE (WpProxy, wp_proxy, WP, PROXY, GObject)
/* The proxy base class */
/**
* WpProxyClass:
* @pw_iface_type: the PipeWire type of the interface that is being proxied by
* this class (ex. `PW_TYPE_INTERFACE_Node` for #WpNode)
* @pw_iface_version: the PipeWire version of the interface that is being
* proxied by this class
*/
struct _WpProxyClass
{
GObjectClass parent_class;

View file

@ -6,6 +6,20 @@
* SPDX-License-Identifier: MIT
*/
/**
* SECTION: WpSession
*
* The #WpSession class allows accessing the properties and methods of a
* PipeWire session object (`struct pw_session` from the session-manager
* extension).
*
* A #WpSession is constructed internally when a new session appears on the
* PipeWire registry and it is made available through the #WpObjectManager API.
*
* A #WpImplSession allows implementing a session and exporting it to PipeWire,
* which is done by augmenting the #WpImplSession with %WP_PROXY_FEATURE_BOUND.
*/
#include "session.h"
#include "private.h"
#include "error.h"
@ -298,12 +312,29 @@ wp_session_class_init (WpSessionClass * klass)
klass->get_default_endpoint = get_default_endpoint;
klass->set_default_endpoint = set_default_endpoint;
/**
* WpSession::default-endpoint-changed:
* @self: the session
* @type: the endpoint type
* @id: the endpoint's bound id
*
* Emitted when the default endpoint of a specific type changes.
* The passed @id is the bound id (wp_proxy_get_bound_id()) of the new
* default endpoint.
*/
signals[SIGNAL_DEFAULT_ENDPOINT_CHANGED] = g_signal_new (
"default-endpoint-changed", G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 2,
WP_TYPE_DEFAULT_ENDPOINT_TYPE, G_TYPE_UINT);
}
/**
* wp_session_get_default_endpoint:
* @self: the session
* @type: the endpoint type
*
* Returns: the bound id of the default endpoint of this @type
*/
guint32
wp_session_get_default_endpoint (WpSession * self,
WpDefaultEndpointType type)
@ -315,6 +346,14 @@ wp_session_get_default_endpoint (WpSession * self,
return WP_SESSION_GET_CLASS (self)->get_default_endpoint (self, type);
}
/**
* wp_session_set_default_endpoint:
* @self: the session
* @type: the endpoint type
* @id: the bound id of the endpoint to set as the default for this @type
*
* Sets the default endpoint for this @type to be the one identified with @id
*/
void
wp_session_set_default_endpoint (WpSession * self,
WpDefaultEndpointType type, guint32 id)
@ -542,6 +581,12 @@ wp_impl_session_class_init (WpImplSessionClass * klass)
session_class->set_default_endpoint = wp_impl_session_set_default_endpoint;
}
/**
* wp_impl_session_new:
* @core: the #WpCore
*
* Returns: (transfer full): the newly constructed session implementation
*/
WpImplSession *
wp_impl_session_new (WpCore * core)
{
@ -552,6 +597,18 @@ wp_impl_session_new (WpCore * core)
NULL);
}
/**
* wp_impl_session_set_property:
* @self: the session implementation
* @key: a property key
* @value: a property value
*
* Sets the specified property on the PipeWire properties of the session.
*
* If this property is set before exporting the session, then it is also used
* in the construction process of the session object and appears as a global
* property.
*/
void
wp_impl_session_set_property (WpImplSession * self,
const gchar * key, const gchar * value)
@ -572,6 +629,18 @@ wp_impl_session_set_property (WpImplSession * self,
}
}
/**
* wp_impl_session_update_properties:
* @self: the session implementation
* @updates: a set of properties to add or update in the session's properties
*
* Adds or updates the values of the PipeWire properties of the session
* using the properties in @updates as a source.
*
* If the properties are set before exporting the session, then they are also
* used in the construction process of the session object and appear as
* global properties.
*/
void
wp_impl_session_update_properties (WpImplSession * self,
WpProperties * updates)

View file

@ -13,18 +13,37 @@
G_BEGIN_DECLS
/**
* WpDefaultEndpointType:
* @WP_DEFAULT_ENDPOINT_TYPE_AUDIO_SOURCE: the default audio source (capture)
* endpoint
* @WP_DEFAULT_ENDPOINT_TYPE_AUDIO_SINK: the default audio sink (playback)
* endpoint
* @WP_DEFAULT_ENDPOINT_TYPE_VIDEO_SOURCE: the default video source endpoint
*/
typedef enum {
WP_DEFAULT_ENDPOINT_TYPE_AUDIO_SOURCE = 0x1000000 /* SPA_PROP_START_CUSTOM */,
WP_DEFAULT_ENDPOINT_TYPE_AUDIO_SINK,
WP_DEFAULT_ENDPOINT_TYPE_VIDEO_SOURCE,
} WpDefaultEndpointType;
/**
* WpSessionFeatures:
* @WP_SESSION_FEATURE_DEFAULT_ENDPOINT: enables the use of
* wp_session_get_default_endpoint() and wp_session_set_default_endpoint()
* to store default endpoint preferences on the session
*
* An extension of #WpProxyFeatures
*/
typedef enum { /*< flags >*/
WP_SESSION_FEATURE_DEFAULT_ENDPOINT = WP_PROXY_FEATURE_LAST,
} WpSessionFeatures;
/* WpSession */
/**
* WP_TYPE_SESSION:
*
* The #WpSession #GType
*/
#define WP_TYPE_SESSION (wp_session_get_type ())
WP_API
G_DECLARE_DERIVABLE_TYPE (WpSession, wp_session, WP, SESSION, WpProxy)
@ -47,8 +66,11 @@ WP_API
void wp_session_set_default_endpoint (WpSession * self,
WpDefaultEndpointType type, guint32 id);
/* WpImplSession */
/**
* WP_TYPE_IMPL_SESSION:
*
* The #WpImplSession #GType
*/
#define WP_TYPE_IMPL_SESSION (wp_impl_session_get_type ())
WP_API
G_DECLARE_DERIVABLE_TYPE (WpImplSession, wp_impl_session, WP, IMPL_SESSION, WpSession)