/* WirePlumber * * Copyright © 2020 Collabora Ltd. * @author George Kiagiadakis * * SPDX-License-Identifier: MIT */ #ifndef __WIREPLUMBER_PIPEWIRE_OBJECT_MIXIN_H__ #define __WIREPLUMBER_PIPEWIRE_OBJECT_MIXIN_H__ #include "proxy-interfaces.h" #include 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; guint64 CHANGE_MASK_ALL; guint64 CHANGE_MASK_PROPS; guint64 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_node) */ 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 @em 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 * @em flags: see below * @em 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) /* @em 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