1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223
|
/* WirePlumber
*
* Copyright © 2019 Collabora Ltd.
* @author George Kiagiadakis <george.kiagiadakis@collabora.com>
*
* SPDX-License-Identifier: MIT
*/
#include "client.h"
#include "log.h"
#include "private/pipewire-object-mixin.h"
WP_DEFINE_LOCAL_LOG_TOPIC ("wp-client")
/*! \defgroup wpclient WpClient */
/*!
* \struct 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.
*/
struct _WpClient
{
WpGlobalProxy parent;
};
static void wp_client_pw_object_mixin_priv_interface_init (
WpPwObjectMixinPrivInterface * iface);
G_DEFINE_TYPE_WITH_CODE (WpClient, wp_client, WP_TYPE_GLOBAL_PROXY,
G_IMPLEMENT_INTERFACE (WP_TYPE_PIPEWIRE_OBJECT,
wp_pw_object_mixin_object_interface_init)
G_IMPLEMENT_INTERFACE (WP_TYPE_PW_OBJECT_MIXIN_PRIV,
wp_client_pw_object_mixin_priv_interface_init))
static void
wp_client_init (WpClient * self)
{
}
static void
wp_client_activate_execute_step (WpObject * object,
WpFeatureActivationTransition * transition, guint step,
WpObjectFeatures missing)
{
switch (step) {
case WP_PW_OBJECT_MIXIN_STEP_BIND:
case WP_TRANSITION_STEP_ERROR:
/* base class can handle BIND and ERROR */
WP_OBJECT_CLASS (wp_client_parent_class)->
activate_execute_step (object, transition, step, missing);
break;
case WP_PW_OBJECT_MIXIN_STEP_WAIT_INFO:
/* just wait, info will be emitted anyway after binding */
break;
default:
g_assert_not_reached ();
}
}
static const struct pw_client_events client_events = {
PW_VERSION_CLIENT_EVENTS,
.info = (HandleEventInfoFunc(client)) wp_pw_object_mixin_handle_event_info,
};
static void
wp_client_pw_proxy_created (WpProxy * proxy, struct pw_proxy * pw_proxy)
{
wp_pw_object_mixin_handle_pw_proxy_created (proxy, pw_proxy,
client, &client_events);
}
static void
wp_client_pw_proxy_destroyed (WpProxy * proxy)
{
wp_pw_object_mixin_handle_pw_proxy_destroyed (proxy);
WP_PROXY_CLASS (wp_client_parent_class)->pw_proxy_destroyed (proxy);
}
static void
wp_client_class_init (WpClientClass * klass)
{
GObjectClass *object_class = (GObjectClass *) klass;
WpObjectClass *wpobject_class = (WpObjectClass *) klass;
WpProxyClass *proxy_class = (WpProxyClass *) klass;
object_class->get_property = wp_pw_object_mixin_get_property;
wpobject_class->get_supported_features =
wp_pw_object_mixin_get_supported_features;
wpobject_class->activate_get_next_step =
wp_pw_object_mixin_activate_get_next_step;
wpobject_class->activate_execute_step = wp_client_activate_execute_step;
proxy_class->pw_iface_type = PW_TYPE_INTERFACE_Client;
proxy_class->pw_iface_version = PW_VERSION_CLIENT;
proxy_class->pw_proxy_created = wp_client_pw_proxy_created;
proxy_class->pw_proxy_destroyed = wp_client_pw_proxy_destroyed;
wp_pw_object_mixin_class_override_properties (object_class);
}
static void
wp_client_pw_object_mixin_priv_interface_init (
WpPwObjectMixinPrivInterface * iface)
{
wp_pw_object_mixin_priv_interface_info_init_no_params (iface, client, CLIENT);
}
/*!
* \brief Send an error to the client
*
* \ingroup wpclient
* \param self the client
* \param id the global id to report the error on
* \param res an errno style error code
* \param message the error message string
*/
void
wp_client_send_error (WpClient * self, guint32 id, int res,
const gchar * message)
{
struct pw_client *pwp;
g_return_if_fail (WP_IS_CLIENT (self));
pwp = (struct pw_client *) wp_proxy_get_pw_proxy (WP_PROXY (self));
g_return_if_fail (pwp != NULL);
pw_client_error (pwp, id, res, message);
}
/*!
* \brief 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
*
* \ingroup wpclient
* \param self the client
* \param n_perm the number of permissions specified in the variable arguments
* \param ... \a 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
*/
void
wp_client_update_permissions (WpClient * self, guint n_perm, ...)
{
va_list args;
struct pw_permission *perm =
g_alloca (n_perm * sizeof (struct pw_permission));
va_start (args, n_perm);
for (guint i = 0; i < n_perm; i++) {
perm[i].id = va_arg (args, guint32);
perm[i].permissions = va_arg (args, guint32);
}
va_end (args);
wp_client_update_permissions_array (self, n_perm, perm);
}
/*!
* \brief 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
*
* \ingroup wpclient
* \param self the client
* \param n_perm the number of permissions specified in the \a permissions array
* \param permissions (array length=n_perm) (element-type pw_permission): an array
* of permissions per object id
*/
void
wp_client_update_permissions_array (WpClient * self,
guint n_perm, const struct pw_permission *permissions)
{
struct pw_client *pwp;
int client_update_permissions_result;
g_return_if_fail (WP_IS_CLIENT (self));
pwp = (struct pw_client *) wp_proxy_get_pw_proxy (WP_PROXY (self));
g_return_if_fail (pwp != NULL);
client_update_permissions_result = pw_client_update_permissions (
pwp, n_perm, permissions);
g_warn_if_fail (client_update_permissions_result >= 0);
}
/*!
* \brief Updates the properties of \a self
*
* This requires W and X permissions on the client.
*
* \ingroup wpclient
* \param self the client
* \param updates (transfer full): updates to apply to the properties of
* \a self; this does not need to include properties that have not changed
*/
void
wp_client_update_properties (WpClient * self, WpProperties * updates)
{
g_autoptr (WpProperties) upd = updates;
struct pw_client *pwp;
int client_update_properties_result;
g_return_if_fail (WP_IS_CLIENT (self));
g_return_if_fail (updates != NULL);
pwp = (struct pw_client *) wp_proxy_get_pw_proxy (WP_PROXY (self));
g_return_if_fail (pwp != NULL);
client_update_properties_result = pw_client_update_properties (
pwp, wp_properties_peek_dict (upd));
g_warn_if_fail (client_update_properties_result >= 0);
}
|