Files
wireplumber/lib/wp/private/pipewire-object-mixin.h
George Kiagiadakis bd65517b7d pw-object-mixin: refactor, implement param caching and features for impl objects
Now the WpPipewireObject interface is directly implemented by the mixin
and there is another interface that users of the mixin must implement
in order for the mixin to work proprely.

A lot of manual stuff that proxy classes had to do before are now
in the mixin. Also most of the data that would normally reside in Private
structures is now in the mixin data structure (stored as qdata on the object).
This is achieving the best amount of code reuse so far.

For impl objects (WpImpl*) there are also default implementations of the
standard pipewire object methods and the INFO & PARAM_* features are
more coherently enabled during the whole lifetime of these objects.
2020-11-25 22:44:29 +02:00

248 lines
8.6 KiB
C

/* WirePlumber
*
* Copyright © 2020 Collabora Ltd.
* @author George Kiagiadakis <george.kiagiadakis@collabora.com>
*
* SPDX-License-Identifier: MIT
*/
#ifndef __WIREPLUMBER_PIPEWIRE_OBJECT_MIXIN_H__
#define __WIREPLUMBER_PIPEWIRE_OBJECT_MIXIN_H__
#include "proxy-interfaces.h"
#include <pipewire/pipewire.h>
G_BEGIN_DECLS
enum {
/* this is the same STEP_BIND as in WpGlobalProxy */
WP_PW_OBJECT_MIXIN_STEP_BIND = WP_TRANSITION_STEP_CUSTOM_START,
WP_PW_OBJECT_MIXIN_STEP_WAIT_INFO,
WP_PW_OBJECT_MIXIN_STEP_CACHE_PARAMS,
WP_PW_OBJECT_MIXIN_STEP_CUSTOM_START,
};
enum {
WP_PW_OBJECT_MIXIN_PROP_0,
// WpPipewireObject
WP_PW_OBJECT_MIXIN_PROP_NATIVE_INFO,
WP_PW_OBJECT_MIXIN_PROP_PROPERTIES,
WP_PW_OBJECT_MIXIN_PROP_PARAM_INFO,
WP_PW_OBJECT_MIXIN_PROP_CUSTOM_START,
};
#define WP_TYPE_PW_OBJECT_MIXIN_PRIV (wp_pw_object_mixin_priv_get_type ())
G_DECLARE_INTERFACE (WpPwObjectMixinPriv, wp_pw_object_mixin_priv,
WP, PW_OBJECT_MIXIN_PRIV, WpProxy)
struct _WpPwObjectMixinPrivInterface
{
GTypeInterface parent;
/* WpPwObjectMixinPriv-specific flags */
#define WP_PW_OBJECT_MIXIN_PRIV_NO_PARAM_CACHE (1 << 0)
guint32 flags;
/* pipewire info struct abstraction layer */
gsize info_size;
gsize change_mask_offset;
gsize props_offset;
gsize param_info_offset;
gsize n_params_offset;
guint32 CHANGE_MASK_ALL;
guint32 CHANGE_MASK_PROPS;
guint32 CHANGE_MASK_PARAMS;
gpointer (*update_info) (gpointer info, gconstpointer update);
void (*free_info) (gpointer info);
/* to further process info struct updates - for proxy objects only */
void (*process_info) (gpointer instance, gpointer old_info, gpointer info);
/* pipewire interface methods - proxy & impl */
gint (*enum_params) (gpointer instance, guint32 id,
guint32 start, guint32 num, WpSpaPod *filter);
GPtrArray * (*enum_params_sync) (gpointer instance, guint32 id,
guint32 start, guint32 num, WpSpaPod *filter);
gint (*set_param) (gpointer instance, guint32 id, guint32 flags,
WpSpaPod *param /* transfer full */);
/* pipewire interface events - for impl objects only */
void (*emit_info) (struct spa_hook_list * hooks, gconstpointer info);
void (*emit_param) (struct spa_hook_list * hooks, int seq,
guint32 id, guint32 index, guint32 next, const struct spa_pod *param);
};
/* fills in info struct abstraction layer in WpPwObjectMixinPrivInterface */
#define wp_pw_object_mixin_priv_interface_info_init(iface, type, TYPE) \
({ \
iface->info_size = sizeof (struct pw_ ## type ## _info); \
iface->change_mask_offset = G_STRUCT_OFFSET (struct pw_ ## type ## _info, change_mask); \
iface->props_offset = G_STRUCT_OFFSET (struct pw_ ## type ## _info, props); \
iface->param_info_offset = G_STRUCT_OFFSET (struct pw_ ## type ## _info, params); \
iface->n_params_offset = G_STRUCT_OFFSET (struct pw_ ## type ## _info, n_params); \
iface->CHANGE_MASK_ALL = PW_ ## TYPE ## _CHANGE_MASK_ALL; \
iface->CHANGE_MASK_PROPS = PW_ ## TYPE ## _CHANGE_MASK_PROPS; \
iface->CHANGE_MASK_PARAMS = PW_ ## TYPE ## _CHANGE_MASK_PARAMS; \
iface->update_info = (gpointer (*)(gpointer, gconstpointer)) pw_ ## type ## _info_update; \
iface->free_info = (void (*)(gpointer)) pw_ ## type ## _info_free; \
})
/* same as above, for types that don't have params */
#define wp_pw_object_mixin_priv_interface_info_init_no_params(iface, type, TYPE) \
({ \
iface->flags = WP_PW_OBJECT_MIXIN_PRIV_NO_PARAM_CACHE; \
iface->info_size = sizeof (struct pw_ ## type ## _info); \
iface->change_mask_offset = G_STRUCT_OFFSET (struct pw_ ## type ## _info, change_mask); \
iface->props_offset = G_STRUCT_OFFSET (struct pw_ ## type ## _info, props); \
iface->param_info_offset = 0; \
iface->n_params_offset = 0; \
iface->CHANGE_MASK_ALL = PW_ ## TYPE ## _CHANGE_MASK_ALL; \
iface->CHANGE_MASK_PROPS = PW_ ## TYPE ## _CHANGE_MASK_PROPS; \
iface->CHANGE_MASK_PARAMS = 0; \
iface->update_info = (gpointer (*)(gpointer, gconstpointer)) pw_ ## type ## _info_update; \
iface->free_info = (void (*)(gpointer)) pw_ ## type ## _info_free; \
})
/*************/
/* INTERFACE */
/* implements WpPipewireObject for an object that implements WpPwObjectMixinPriv */
void wp_pw_object_mixin_object_interface_init (WpPipewireObjectInterface * iface);
/********/
/* DATA */
typedef struct _WpPwObjectMixinData WpPwObjectMixinData;
struct _WpPwObjectMixinData
{
gpointer info; /* pointer to the info struct */
gpointer iface; /* pointer to the interface (ex. pw_endpoint) */
struct spa_hook listener;
struct spa_hook_list hooks;
WpProperties *properties;
GList *enum_params_tasks; /* element-type: GTask* */
GList *params; /* element-type: WpPwObjectMixinParamStore* */
GArray *subscribed_ids; /* element-type: guint32 */
};
/* get mixin data (stored as qdata on the @instance) */
WpPwObjectMixinData * wp_pw_object_mixin_get_data (gpointer instance);
/****************/
/* PARAMS STORE */
/* param store access; (transfer container) */
GPtrArray * wp_pw_object_mixin_get_stored_params (WpPwObjectMixinData * data,
guint32 id);
/* param store manipulation
* @flags: see below
* @param: (transfer full): WpSpaPod* or GPtrArray* */
void wp_pw_object_mixin_store_param (WpPwObjectMixinData * data, guint32 id,
guint32 flags, gpointer param);
/* set the index at which to store the new param */
#define WP_PW_OBJECT_MIXIN_STORE_PARAM_SET(x) ((x) & 0x7fff)
#define WP_PW_OBJECT_MIXIN_STORE_PARAM_APPEND (0xffff)
#define WP_PW_OBJECT_MIXIN_STORE_PARAM_PREPEND (0)
/* @param is a GPtrArray* */
#define WP_PW_OBJECT_MIXIN_STORE_PARAM_ARRAY (1 << 16)
/* clear the existing array of params before storing */
#define WP_PW_OBJECT_MIXIN_STORE_PARAM_CLEAR (1 << 17)
/* completely remove stored params for @id */
#define WP_PW_OBJECT_MIXIN_STORE_PARAM_REMOVE (1 << 18)
/******************/
/* PROPERTIES API */
/* assign to get_property or chain it from there */
void wp_pw_object_mixin_get_property (GObject * object, guint property_id,
GValue * value, GParamSpec * pspec);
/* call from class_init */
void wp_pw_object_mixin_class_override_properties (GObjectClass * klass);
/****************/
/* FEATURES API */
/* call from get_supported_features */
WpObjectFeatures wp_pw_object_mixin_get_supported_features (WpObject * object);
/* assign directly to activate_get_next_step */
guint wp_pw_object_mixin_activate_get_next_step (WpObject * object,
WpFeatureActivationTransition * transition, guint step,
WpObjectFeatures missing);
/* call from activate_execute_step when
step == WP_PW_OBJECT_MIXIN_STEP_CACHE_PARAMS */
void wp_pw_object_mixin_cache_params (WpObject * object,
WpObjectFeatures missing);
/* handle deactivation of PARAM_* caching features */
void wp_pw_object_mixin_deactivate (WpObject * object,
WpObjectFeatures features);
/************************/
/* PROXY EVENT HANDLERS */
/* (for proxy objects) */
#define wp_pw_object_mixin_handle_pw_proxy_created(instance, pw_proxy, type, events) \
({ \
WpPwObjectMixinData *d = wp_pw_object_mixin_get_data (instance); \
d->iface = pw_proxy; \
pw_ ## type ## _add_listener ((struct pw_ ## type *) pw_proxy, \
&d->listener, events, instance); \
})
void wp_pw_object_mixin_handle_pw_proxy_destroyed (WpProxy * proxy);
/***************************/
/* PIPEWIRE EVENT HANDLERS */
/* (for proxy objects) */
#define HandleEventInfoFunc(type) \
void (*)(void *, const struct pw_ ## type ## _info *)
void wp_pw_object_mixin_handle_event_info (gpointer instance, gconstpointer info);
/* assign as the param event callback */
void wp_pw_object_mixin_handle_event_param (gpointer instance, int seq,
guint32 id, guint32 index, guint32 next, const struct spa_pod *param);
/***********************************/
/* PIPEWIRE METHOD IMPLEMENTATIONS */
/* (for impl objects) */
#define ImplAddListenerFunc(type) \
int (*)(void *, struct spa_hook *, const struct pw_ ## type ## _events *, void *)
int wp_pw_object_mixin_impl_add_listener (gpointer instance,
struct spa_hook *listener, gconstpointer events, gpointer data);
int wp_pw_object_mixin_impl_enum_params (gpointer instance, int seq,
guint32 id, guint32 start, guint32 num, const struct spa_pod *filter);
int wp_pw_object_mixin_impl_subscribe_params (gpointer instance,
guint32 *ids, guint32 n_ids);
int wp_pw_object_mixin_impl_set_param (gpointer instance, guint32 id,
guint32 flags, const struct spa_pod *param);
/**********************/
/* NOTIFIERS */
/* (for impl objects) */
void wp_pw_object_mixin_notify_info (gpointer instance, guint32 change_mask);
void wp_pw_object_mixin_notify_params_changed (gpointer instance, guint32 id);
G_END_DECLS
#endif