/* WirePlumber * * Copyright © 2020 Collabora Ltd. * @author George Kiagiadakis * * SPDX-License-Identifier: MIT */ #include "si-interfaces.h" #include "wpenums.h" #include "log.h" WP_DEFINE_LOCAL_LOG_TOPIC ("wp-si-interfaces") /*! \defgroup wpsiinterfaces Session Item Interfaces */ /*! * \struct WpSiAdapter * An interface for port adapters * * \gsignals * * \par adapter-ports-state-changed * \parblock * \code * void * adapter_ports_state_changed_callback (WpSiAdapter * self, * gpointer user_data) * \endcode * Emitted when the ports state changes * * Flags: G_SIGNAL_RUN_LAST * \endparblock */ G_DEFINE_INTERFACE (WpSiAdapter, wp_si_adapter, WP_TYPE_SESSION_ITEM) static void wp_si_adapter_default_init (WpSiAdapterInterface * iface) { g_signal_new ("adapter-ports-state-changed", G_TYPE_FROM_INTERFACE (iface), G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 2, WP_TYPE_SI_ADAPTER_PORTS_STATE, WP_TYPE_SI_ADAPTER_PORTS_STATE); } /** * \brief Gets the ports state * * \ingroup wpsiinterfaces * \param self the session item * \returns The state of the ports * \since 0.4.10 */ WpSiAdapterPortsState wp_si_adapter_get_ports_state (WpSiAdapter * self) { g_return_val_if_fail (WP_IS_SI_ADAPTER (self), WP_SI_ADAPTER_PORTS_STATE_NONE); g_return_val_if_fail (WP_SI_ADAPTER_GET_IFACE (self)->get_ports_state, WP_SI_ADAPTER_PORTS_STATE_NONE); return WP_SI_ADAPTER_GET_IFACE (self)->get_ports_state (self); } /** * \brief Gets the format used to configure the adapter session item's ports * * \ingroup wpsiinterfaces * \param self the session item * \param mode (out) (nullable): the mode * \returns (transfer full): The format used to configure the ports of the * adapter session item. Some items automatically choose a format when being * activated, others never set a format on activation and the user needs to * manually set it externally with wp_si_adapter_set_ports_format(). */ WpSpaPod * wp_si_adapter_get_ports_format (WpSiAdapter * self, const gchar **mode) { g_return_val_if_fail (WP_IS_SI_ADAPTER (self), NULL); g_return_val_if_fail (WP_SI_ADAPTER_GET_IFACE (self)->get_ports_format, NULL); return WP_SI_ADAPTER_GET_IFACE (self)->get_ports_format (self, mode); } /*! * \brief Sets the format and configures the adapter session item ports using * the given format. * * The result of the operation can be checked using the * wp_si_adapter_set_ports_format_finish() API. If format is NULL, the adapter * will be configured with the default format. If mode is NULL, the adapter * will use "dsp" mode. * * \ingroup wpsiinterfaces * \param self the session item * \param format (transfer full) (nullable): the format to be set * \param mode (nullable): the mode * \param callback (scope async): the callback to call when the operation is done * \param data (closure): user data for \a callback */ void wp_si_adapter_set_ports_format (WpSiAdapter * self, WpSpaPod *format, const gchar *mode, GAsyncReadyCallback callback, gpointer data) { g_return_if_fail (WP_IS_SI_ADAPTER (self)); g_return_if_fail (WP_SI_ADAPTER_GET_IFACE (self)->set_ports_format); WP_SI_ADAPTER_GET_IFACE (self)->set_ports_format (self, format, mode, callback, data); } /*! * \brief Finishes the operation started by wp_si_adapter_set_format(). * This is meant to be called in the callback that was passed to that method. * * \ingroup wpsiinterfaces * \param self the session item * \param res the async result * \param error (out) (optional): the operation's error, if it occurred * \returns TRUE on success, FALSE if there was an error */ gboolean wp_si_adapter_set_ports_format_finish (WpSiAdapter * self, GAsyncResult * res, GError ** error) { g_return_val_if_fail (WP_IS_SI_ADAPTER (self), FALSE); g_return_val_if_fail (WP_SI_ADAPTER_GET_IFACE (self)->set_ports_format_finish, FALSE); return WP_SI_ADAPTER_GET_IFACE (self)->set_ports_format_finish (self, res, error); } /*! * \struct WpSiLinkable * * An interface for retrieving PipeWire port information from a session item. * This information is used to create links in the nodes graph. */ G_DEFINE_INTERFACE (WpSiLinkable, wp_si_linkable, WP_TYPE_SESSION_ITEM) static WpSiAcquisition * wp_si_linkable_default_get_acquisition (WpSiLinkable * self) { return NULL; } static void wp_si_linkable_default_init (WpSiLinkableInterface * iface) { iface->get_acquisition = wp_si_linkable_default_get_acquisition; } /*! * \brief This method returns a variant of type "a(uuu)", where each tuple in * the array contains the following information: * - u: (guint32) node id * - u: (guint32) port id (the port must belong on the node specified above) * - u: (guint32) the audio channel (enum spa_audio_channel) that this port * makes available, or 0 for non-audio content * * The order in which ports appear in this array is important when no channel * information is available. The link implementation should link the ports * in the order they appear. This is normally a good enough substitute for * channel matching. * * The \a context argument can be used to get different sets of ports from * the item. The following well-known contexts are defined: * - NULL: get the standard ports to be linked * - "monitor": get the monitor ports * - "control": get the control port * - "reverse": get the reverse direction ports, if this item controls a * filter node, which would have ports on both directions * * Contexts other than NULL may only be used internally to ease the * implementation of more complex item relationships. For example, a * WpSessionItem that is in control of an input (sink) adapter node may * implement WpSiLinkable where the NULL context will return the standard * input ports and the "monitor" context will return the adapter's monitor * ports. When linking this item to another item, the NULL context * will always be used, but the item may internally spawn a secondary * WpSessionItem that implements the "monitor" item. That secondary item * may implement WpSiLinkable, chaining calls to the WpSiLinkable * of the original item using the "monitor" context. This way, the monitor * WpSessionItem does not need to share control of the * underlying node; it only proxies calls to satisfy the API. * * \ingroup wpsiinterfaces * \param self the session item * \param context (nullable): an optional context for the ports * \returns (transfer full): a GVariant containing information about the * ports of this item */ GVariant * wp_si_linkable_get_ports (WpSiLinkable * self, const gchar * context) { g_return_val_if_fail (WP_IS_SI_LINKABLE (self), NULL); g_return_val_if_fail (WP_SI_LINKABLE_GET_IFACE (self)->get_ports, NULL); return WP_SI_LINKABLE_GET_IFACE (self)->get_ports (self, context); } /*! * \brief Gets the acquisition interface associated with the item * * \ingroup wpsiinterfaces * \param self the session item * * \returns (transfer none) (nullable): the acquisition interface associated * with this item, or NULL if this item does not require acquiring items * before linking them */ WpSiAcquisition * wp_si_linkable_get_acquisition (WpSiLinkable * self) { g_return_val_if_fail (WP_IS_SI_LINKABLE (self), NULL); g_return_val_if_fail ( WP_SI_LINKABLE_GET_IFACE (self)->get_acquisition, NULL); return WP_SI_LINKABLE_GET_IFACE (self)->get_acquisition (self); } /*! * \struct WpSiLink * * An interface for session items that provide a PipeWire link. * * \gsignals * * \par link-properties-changed * \parblock * \code * void * link_properties_changed_callback (WpSiLink * self, * gpointer user_data) * \endcode * Emitted when the properties of the link change * * Flags: G_SIGNAL_RUN_LAST * \endparblock */ G_DEFINE_INTERFACE (WpSiLink, wp_si_link, WP_TYPE_SESSION_ITEM) static WpProperties * wp_si_link_default_get_properties (WpSiLink * self) { return NULL; } static void wp_si_link_default_init (WpSiLinkInterface * iface) { iface->get_properties = wp_si_link_default_get_properties; g_signal_new ("link-properties-changed", G_TYPE_FROM_INTERFACE (iface), G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 0); } /*! * \brief This should return information that is used for registering the link, * as a GVariant of type a{ss} that contains additional properties to be * added to the list of global properties * * \ingroup wpsiinterfaces * \param self the session item * \returns (transfer full): registration info for the link */ GVariant * wp_si_link_get_registration_info (WpSiLink * self) { g_return_val_if_fail (WP_IS_SI_LINK (self), NULL); g_return_val_if_fail (WP_SI_LINK_GET_IFACE (self)->get_registration_info, NULL); return WP_SI_LINK_GET_IFACE (self)->get_registration_info (self); } /*! * \brief Gets the properties of the link * * \ingroup wpsiinterfaces * \param self the session item * \returns (transfer full) (nullable): the properties of the link */ WpProperties * wp_si_link_get_properties (WpSiLink * self) { g_return_val_if_fail (WP_IS_SI_LINK (self), NULL); g_return_val_if_fail (WP_SI_LINK_GET_IFACE (self)->get_properties, NULL); return WP_SI_LINK_GET_IFACE (self)->get_properties (self); } /*! * \brief Gets the output item linked by the link * * \ingroup wpsiinterfaces * \param self the session item * \returns (transfer none): the output item that is linked by this link */ WpSiLinkable * wp_si_link_get_out_item (WpSiLink * self) { g_return_val_if_fail (WP_IS_SI_LINK (self), NULL); g_return_val_if_fail (WP_SI_LINK_GET_IFACE (self)->get_out_item, NULL); return WP_SI_LINK_GET_IFACE (self)->get_out_item (self); } /*! * \brief Gets the input item linked by the link * * \ingroup wpsiinterfaces * \param self the session item * \returns (transfer none): the input item that is linked by this link */ WpSiLinkable * wp_si_link_get_in_item (WpSiLink * self) { g_return_val_if_fail (WP_IS_SI_LINK (self), NULL); g_return_val_if_fail (WP_SI_LINK_GET_IFACE (self)->get_in_item, NULL); return WP_SI_LINK_GET_IFACE (self)->get_in_item (self); } /*! * \struct WpSiAcquisition * * This interface provides a way to request an item for linking before doing * so. This allows item implementations to apply internal policy rules. * * A WpSiAcquisition is associated directly with a WpSiLinkable via * wp_si_linkable_get_acquisition(). In order to allow switching * policies, it is recommended that port info implementations use a separate * session item to implement this interface and allow replacing it. */ G_DEFINE_INTERFACE (WpSiAcquisition, wp_si_acquisition, WP_TYPE_SESSION_ITEM) static void wp_si_acquisition_default_init (WpSiAcquisitionInterface * iface) { } /*! * \brief Acquires the \a item for linking by \a acquisitor. * * When a link is not allowed by policy, this operation should return * an error. * * When a link needs to be delayed for a short amount of time (ex. to apply * a fade out effect on another item), this operation should finish with a * delay. It is safe to assume that after this operation completes, * the item will be linked immediately. * * \ingroup wpsiinterfaces * \param self the session item * \param acquisitor the link that is trying to acquire a port info item * \param item the item that is being acquired * \param callback (scope async): the callback to call when the operation is done * \param data (closure): user data for \a callback */ void wp_si_acquisition_acquire (WpSiAcquisition * self, WpSiLink * acquisitor, WpSiLinkable * item, GAsyncReadyCallback callback, gpointer data) { g_return_if_fail (WP_IS_SI_ACQUISITION (self)); g_return_if_fail (WP_SI_ACQUISITION_GET_IFACE (self)->acquire); WP_SI_ACQUISITION_GET_IFACE (self)->acquire (self, acquisitor, item, callback, data); } /*! * \brief Finishes the operation started by wp_si_acquisition_acquire(). * This is meant to be called in the callback that was passed to that method. * * \ingroup wpsiinterfaces * \param self the session item * \param res the async result * \param error (out) (optional): the operation's error, if it occurred * \returns TRUE on success, FALSE if there was an error */ gboolean wp_si_acquisition_acquire_finish (WpSiAcquisition * self, GAsyncResult * res, GError ** error) { g_return_val_if_fail (WP_IS_SI_ACQUISITION (self), FALSE); g_return_val_if_fail (WP_SI_ACQUISITION_GET_IFACE (self)->acquire_finish, FALSE); return WP_SI_ACQUISITION_GET_IFACE (self)->acquire_finish (self, res, error); } /*! * \brief Releases the \a item, which means that it is being unlinked. * * \ingroup wpsiinterfaces * \param self the session item * \param acquisitor the link that had previously acquired the item * \param item the port info that is being released */ void wp_si_acquisition_release (WpSiAcquisition * self, WpSiLink * acquisitor, WpSiLinkable * item) { g_return_if_fail (WP_IS_SI_ACQUISITION (self)); g_return_if_fail (WP_SI_ACQUISITION_GET_IFACE (self)->release); WP_SI_ACQUISITION_GET_IFACE (self)->release (self, acquisitor, item); }