object-manager: replace GPtrArray API with WpIterator

+ add the useful _find_proxy() method
This commit is contained in:
George Kiagiadakis 2020-04-21 13:21:03 +03:00
parent fbddccd5bf
commit 1dccdcf415
11 changed files with 304 additions and 173 deletions

View file

@ -579,50 +579,41 @@ wp_endpoint_get_n_streams (WpEndpoint * self)
}
/**
* wp_endpoint_get_stream:
* wp_endpoint_find_stream:
* @self: the endpoint
* @bound_id: the bound id of the stream object to get
* @bound_id: the bound id of the stream object to find
*
* Returns: (transfer full) (nullable): the endpoint stream that has the given
* @bound_id, or %NULL if there is no such stream
*/
WpEndpointStream *
wp_endpoint_get_stream (WpEndpoint * self, guint32 bound_id)
wp_endpoint_find_stream (WpEndpoint * self, guint32 bound_id)
{
g_return_val_if_fail (WP_IS_ENDPOINT (self), NULL);
g_return_val_if_fail (wp_proxy_get_features (WP_PROXY (self)) &
WP_ENDPOINT_FEATURE_STREAMS, NULL);
WpEndpointPrivate *priv = wp_endpoint_get_instance_private (self);
g_autoptr (GPtrArray) streams =
wp_object_manager_get_objects (priv->streams_om, 0);
for (guint i = 0; i < streams->len; i++) {
gpointer proxy = g_ptr_array_index (streams, i);
g_return_val_if_fail (WP_IS_ENDPOINT_STREAM (proxy), NULL);
if (wp_proxy_get_bound_id (WP_PROXY (proxy)) == bound_id)
return WP_ENDPOINT_STREAM (g_object_ref (proxy));
}
return NULL;
return (WpEndpointStream *)
wp_object_manager_find_proxy (priv->streams_om, bound_id);
}
/**
* wp_endpoint_get_all_streams:
* wp_endpoint_iterate_streams:
* @self: the endpoint
*
* Returns: (transfer full) (element-type WpEndpointStream): array with all
* Returns: (transfer full): a #WpIterator that iterates over all
* the endpoint streams that belong to this endpoint
*/
GPtrArray *
wp_endpoint_get_all_streams (WpEndpoint * self)
WpIterator *
wp_endpoint_iterate_streams (WpEndpoint * self)
{
g_return_val_if_fail (WP_IS_ENDPOINT (self), NULL);
g_return_val_if_fail (wp_proxy_get_features (WP_PROXY (self)) &
WP_ENDPOINT_FEATURE_STREAMS, NULL);
WpEndpointPrivate *priv = wp_endpoint_get_instance_private (self);
return wp_object_manager_get_objects (priv->streams_om, 0);
return wp_object_manager_iterate (priv->streams_om);
}
/* WpImplEndpoint */
@ -864,18 +855,20 @@ impl_create_link (void *object, const struct spa_dict *props)
g_autoptr (WpEndpoint) peer_ep_proxy = NULL;
g_autoptr (WpEndpointStream) peer_stream_proxy = NULL;
peer_ep_proxy = wp_session_get_endpoint (session, peer_ep_id);
peer_ep_proxy = wp_session_find_endpoint (session, peer_ep_id);
if (!peer_ep_proxy) {
wp_warning_object (self, "endpoint %d not found in session", peer_ep_id);
return -EINVAL;
}
if (peer_stream_id != SPA_ID_INVALID) {
peer_stream_proxy = wp_endpoint_get_stream (peer_ep_proxy, peer_stream_id);
peer_stream_proxy = wp_endpoint_find_stream (peer_ep_proxy,
peer_stream_id);
} else {
g_autoptr (GPtrArray) s = wp_endpoint_get_all_streams (peer_ep_proxy);
peer_stream_proxy = (s->len > 0) ?
g_object_ref (g_ptr_array_index (s, 0)) : NULL;
g_autoptr (WpIterator) it = wp_endpoint_iterate_streams (peer_ep_proxy);
g_auto (GValue) val = G_VALUE_INIT;
if (wp_iterator_next (it, &val))
peer_stream_proxy = g_value_dup_object (&val);
}
if (!peer_stream_proxy) {

View file

@ -11,6 +11,7 @@
#include "proxy.h"
#include "endpoint-stream.h"
#include "iterator.h"
G_BEGIN_DECLS
@ -44,8 +45,8 @@ typedef enum {
* wp_endpoint_get_control() and wp_endpoint_set_control() families of
* functions to be able to work with endpoint-specific controls
* @WP_ENDPOINT_FEATURE_STREAMS: caches information about streams, enabling
* the use of wp_endpoint_get_n_streams(), wp_endpoint_get_stream() and
* wp_endpoint_get_all_streams()
* the use of wp_endpoint_get_n_streams(), wp_endpoint_find_stream() and
* wp_endpoint_iterate_streams()
*
* An extension of #WpProxyFeatures
*/
@ -132,10 +133,10 @@ WP_API
guint wp_endpoint_get_n_streams (WpEndpoint * self);
WP_API
WpEndpointStream * wp_endpoint_get_stream (WpEndpoint * self, guint32 bound_id);
WpEndpointStream * wp_endpoint_find_stream (WpEndpoint * self, guint32 bound_id);
WP_API
GPtrArray * wp_endpoint_get_all_streams (WpEndpoint * self);
WpIterator * wp_endpoint_iterate_streams (WpEndpoint * self);
G_END_DECLS

View file

@ -149,8 +149,8 @@ wp_iterator_next (WpIterator *self, GValue *item)
* wp_iterator_fold:
* @self: the iterator
* @func: (scope call): the fold function
* @ret: the accumulator data
* @data: the user data
* @ret: (inout): the accumulator data
* @data: (closure): the user data
*
* Iterates over all items of the iterator calling a function.
*
@ -172,7 +172,7 @@ wp_iterator_fold (WpIterator *self, WpIteratorFoldFunc func, GValue *ret,
* wp_iterator_foreach:
* @self: the iterator
* @func: (scope call): the foreach function
* @data: the user data
* @data: (closure): the user data
*
* Fold a function over the items of the iterator.
*

View file

@ -33,7 +33,7 @@
*
* 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
* available to get through wp_object_manager_iterate() and the
* #WpObjectManager::object-added signal will be emitted for all of them.
*/
@ -192,7 +192,7 @@ wp_object_manager_class_init (WpObjectManagerClass * klass)
* 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()
* wp_object_manager_iterate()
*/
signals[SIGNAL_OBJECTS_CHANGED] = g_signal_new (
"objects-changed", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_FIRST,
@ -239,7 +239,7 @@ wp_object_manager_new (void)
* 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);
* WpIterator *nodes_it = wp_object_manager_iterate (om);
* ]|
*
* and to discover all 'port' objects that belong to a specific 'node':
@ -262,7 +262,7 @@ wp_object_manager_new (void)
* WP_PROXY_FEATURES_STANDARD);
*
* wp_core_install_object_manager (core, om);
* GPtrArray *ports = wp_object_manager_get_objects (om, 0);
* WpIterator *ports_it = wp_object_manager_iterate (om);
* ]|
*/
void
@ -296,29 +296,125 @@ wp_object_manager_get_n_objects (WpObjectManager * self)
return self->objects->len;
}
/**
* 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 ( %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
*/
GPtrArray *
wp_object_manager_get_objects (WpObjectManager *self, GType type_filter)
struct om_iterator_data
{
GPtrArray *result = g_ptr_array_new_with_free_func (g_object_unref);
guint i;
WpObjectManager *om;
guint index;
};
for (i = 0; i < self->objects->len; i++) {
gpointer obj = g_ptr_array_index (self->objects, i);
if (type_filter == 0 || g_type_is_a (G_OBJECT_TYPE (obj), type_filter)) {
g_ptr_array_add (result, g_object_ref (obj));
}
static void
om_iterator_reset (WpIterator *it)
{
struct om_iterator_data *it_data = wp_iterator_get_user_data (it);
it_data->index = 0;
}
static gboolean
om_iterator_next (WpIterator *it, GValue *item)
{
struct om_iterator_data *it_data = wp_iterator_get_user_data (it);
GPtrArray *objects = it_data->om->objects;
if (G_LIKELY (it_data->index < objects->len)) {
g_value_init_from_instance (item,
g_ptr_array_index (objects, it_data->index++));
return TRUE;
}
return FALSE;
}
static gboolean
om_iterator_fold (WpIterator *it, WpIteratorFoldFunc func, GValue *ret,
gpointer data)
{
struct om_iterator_data *it_data = wp_iterator_get_user_data (it);
gpointer *obj, *base;
guint len;
obj = base = it_data->om->objects->pdata;
len = it_data->om->objects->len;
while ((obj - base) < len) {
g_auto (GValue) item = G_VALUE_INIT;
g_value_init_from_instance (&item, *obj);
if (!func (&item, ret, data))
return FALSE;
obj++;
}
return result;
return TRUE;
}
static void
om_iterator_finalize (WpIterator *it)
{
struct om_iterator_data *it_data = wp_iterator_get_user_data (it);
g_object_unref (it_data->om);
}
static const WpIteratorMethods om_iterator_methods = {
.reset = om_iterator_reset,
.next = om_iterator_next,
.fold = om_iterator_fold,
.finalize = om_iterator_finalize,
};
/**
* wp_object_manager_iterate:
* @self: the object manager
*
* Returns: (transfer full): a #WpIterator that iterates over all the managed
* objects of this object manager
*/
WpIterator *
wp_object_manager_iterate (WpObjectManager * self)
{
WpIterator *it;
struct om_iterator_data *it_data;
g_return_val_if_fail (WP_IS_OBJECT_MANAGER (self), NULL);
it = wp_iterator_new (&om_iterator_methods, sizeof (struct om_iterator_data));
it_data = wp_iterator_get_user_data (it);
it_data->om = g_object_ref (self);
it_data->index = 0;
return it;
}
static gboolean
find_proxy_fold_func (const GValue *item, GValue *ret, gpointer data)
{
if (g_type_is_a (G_VALUE_TYPE (item), WP_TYPE_PROXY)) {
WpProxy *proxy = g_value_get_object (item);
if (wp_proxy_get_bound_id (proxy) == GPOINTER_TO_UINT (data)) {
g_value_init_from_instance (ret, proxy);
return FALSE;
}
}
return TRUE;
}
/**
* wp_object_manager_find_proxy:
* @self: the object manager
* @bound_id: the bound id of the proxy to get
*
* Searches the managed objects to find a #WpProxy that has the given @bound_id
*
* Returns: (transfer full) (nullable): the proxy that has the given @bound_id,
* or %NULL if there is no such proxy managed by this object manager
*/
WpProxy *
wp_object_manager_find_proxy (WpObjectManager *self, guint bound_id)
{
g_autoptr (WpIterator) it = wp_object_manager_iterate (self);
g_auto (GValue) ret = G_VALUE_INIT;
if (!wp_iterator_fold (it, find_proxy_fold_func, &ret,
GUINT_TO_POINTER (bound_id)))
return g_value_dup_object (&ret);
return NULL;
}
static gboolean

View file

@ -11,6 +11,7 @@
#include <glib-object.h>
#include "proxy.h"
#include "iterator.h"
G_BEGIN_DECLS
@ -51,8 +52,10 @@ WP_API
guint wp_object_manager_get_n_objects (WpObjectManager * self);
WP_API
GPtrArray * wp_object_manager_get_objects (WpObjectManager *self,
GType type_filter);
WpIterator * wp_object_manager_iterate (WpObjectManager * self);
WP_API
WpProxy * wp_object_manager_find_proxy (WpObjectManager *self, guint bound_id);
G_END_DECLS

View file

@ -150,12 +150,15 @@ wp_policy_manager_get_instance (WpCore *core)
WpSession *
wp_policy_manager_get_session (WpPolicyManager *self)
{
g_autoptr (GPtrArray) arr = NULL;
g_autoptr (WpIterator) it = NULL;
g_auto (GValue) val = G_VALUE_INIT;
g_return_val_if_fail (WP_IS_POLICY_MANAGER (self), NULL);
arr = wp_object_manager_get_objects (self->sessions_om, 0);
return (arr->len > 0) ? g_object_ref (g_ptr_array_index (arr, 0)) : NULL;
it = wp_object_manager_iterate (self->sessions_om);
if (wp_iterator_next (it, &val))
return g_value_dup_object (&val);
return NULL;
}
static inline gboolean
@ -193,6 +196,17 @@ media_class_matches (const gchar * media_class, const gchar * lookup)
return TRUE;
}
static gboolean
list_endpoints_fold_func (const GValue *item, GValue *ret, gpointer data)
{
GPtrArray *ret_arr = g_value_get_boxed (ret);
WpBaseEndpoint *ep = g_value_get_object (item);
if (media_class_matches (wp_base_endpoint_get_media_class (ep),
(const gchar *) data))
g_ptr_array_add (ret_arr, g_object_ref (ep));
return TRUE;
}
/**
* wp_policy_manager_list_endpoints:
* @self: the policy manager
@ -205,18 +219,20 @@ GPtrArray *
wp_policy_manager_list_endpoints (WpPolicyManager * self,
const gchar * media_class)
{
GPtrArray * ret;
guint i;
g_autoptr (WpIterator) it = NULL;
g_auto (GValue) val = G_VALUE_INIT;
GPtrArray *ret_arr;
g_return_val_if_fail (WP_IS_POLICY_MANAGER (self), NULL);
ret = wp_object_manager_get_objects (self->endpoints_om, 0);
for (i = ret->len; i > 0; i--) {
WpBaseEndpoint *ep = g_ptr_array_index (ret, i-1);
if (!media_class_matches (wp_base_endpoint_get_media_class (ep), media_class))
g_ptr_array_remove_index_fast (ret, i-1);
}
return ret;
ret_arr = g_ptr_array_new_with_free_func (g_object_unref);
g_value_init (&val, G_TYPE_PTR_ARRAY);
g_value_set_boxed (&val, ret_arr);
it = wp_object_manager_iterate (self->endpoints_om);
wp_iterator_fold (it, list_endpoints_fold_func, &val, (gpointer) media_class);
return ret_arr;
}
/* WpPolicy */

View file

@ -470,50 +470,41 @@ wp_session_get_n_endpoints (WpSession * self)
}
/**
* wp_session_get_endpoint:
* wp_session_find_endpoint:
* @self: the session
* @bound_id: the bound id of the endpoint object to get
* @bound_id: the bound id of the endpoint object to find
*
* Returns: (transfer full) (nullable): the endpoint that has the given
* @bound_id, or %NULL if there is no such endpoint
*/
WpEndpoint *
wp_session_get_endpoint (WpSession * self, guint32 bound_id)
wp_session_find_endpoint (WpSession * self, guint32 bound_id)
{
g_return_val_if_fail (WP_IS_SESSION (self), NULL);
g_return_val_if_fail (wp_proxy_get_features (WP_PROXY (self)) &
WP_SESSION_FEATURE_ENDPOINTS, NULL);
WpSessionPrivate *priv = wp_session_get_instance_private (self);
g_autoptr (GPtrArray) endpoints =
wp_object_manager_get_objects (priv->endpoints_om, 0);
for (guint i = 0; i < endpoints->len; i++) {
gpointer proxy = g_ptr_array_index (endpoints, i);
g_return_val_if_fail (WP_IS_ENDPOINT (proxy), NULL);
if (wp_proxy_get_bound_id (WP_PROXY (proxy)) == bound_id)
return WP_ENDPOINT (g_object_ref (proxy));
}
return NULL;
return (WpEndpoint *)
wp_object_manager_find_proxy (priv->endpoints_om, bound_id);
}
/**
* wp_session_get_all_endpoints:
* wp_session_iterate_endpoints:
* @self: the session
*
* Returns: (transfer full) (element-type WpEndpoint): array with all
* Returns: (transfer full): a #WpIterator that iterates over all
* the endpoints that belong to this session
*/
GPtrArray *
wp_session_get_all_endpoints (WpSession * self)
WpIterator *
wp_session_iterate_endpoints (WpSession * self)
{
g_return_val_if_fail (WP_IS_SESSION (self), NULL);
g_return_val_if_fail (wp_proxy_get_features (WP_PROXY (self)) &
WP_SESSION_FEATURE_ENDPOINTS, NULL);
WpSessionPrivate *priv = wp_session_get_instance_private (self);
return wp_object_manager_get_objects (priv->endpoints_om, 0);
return wp_object_manager_iterate (priv->endpoints_om);
}
/**
@ -534,50 +525,41 @@ wp_session_get_n_links (WpSession * self)
}
/**
* wp_session_get_link:
* wp_session_find_link:
* @self: the session
* @bound_id: the bound id of the link object to get
* @bound_id: the bound id of the link object to find
*
* Returns: (transfer full) (nullable): the endpoint link that has the given
* @bound_id, or %NULL if there is no such endpoint link
*/
WpEndpointLink *
wp_session_get_link (WpSession * self, guint32 bound_id)
wp_session_find_link (WpSession * self, guint32 bound_id)
{
g_return_val_if_fail (WP_IS_SESSION (self), NULL);
g_return_val_if_fail (wp_proxy_get_features (WP_PROXY (self)) &
WP_SESSION_FEATURE_LINKS, NULL);
WpSessionPrivate *priv = wp_session_get_instance_private (self);
g_autoptr (GPtrArray) links =
wp_object_manager_get_objects (priv->links_om, 0);
for (guint i = 0; i < links->len; i++) {
gpointer proxy = g_ptr_array_index (links, i);
g_return_val_if_fail (WP_IS_ENDPOINT_LINK (proxy), NULL);
if (wp_proxy_get_bound_id (WP_PROXY (proxy)) == bound_id)
return WP_ENDPOINT_LINK (g_object_ref (proxy));
}
return NULL;
return (WpEndpointLink *)
wp_object_manager_find_proxy (priv->links_om, bound_id);
}
/**
* wp_session_get_all_links:
* wp_session_iterate_links:
* @self: the session
*
* Returns: (transfer full) (element-type WpEndpointLink): array with all
* Returns: (transfer full): a #WpIterator that iterates over all
* the endpoint links that belong to this session
*/
GPtrArray *
wp_session_get_all_links (WpSession * self)
WpIterator *
wp_session_iterate_links (WpSession * self)
{
g_return_val_if_fail (WP_IS_SESSION (self), NULL);
g_return_val_if_fail (wp_proxy_get_features (WP_PROXY (self)) &
WP_SESSION_FEATURE_LINKS, NULL);
WpSessionPrivate *priv = wp_session_get_instance_private (self);
return wp_object_manager_get_objects (priv->links_om, 0);
return wp_object_manager_iterate (priv->links_om);
}
/* WpImplSession */

View file

@ -35,11 +35,11 @@ typedef enum {
* wp_session_get_default_endpoint() and wp_session_set_default_endpoint()
* to store default endpoint preferences on the session
* @WP_SESSION_FEATURE_ENDPOINTS: caches information about endpoints, enabling
* the use of wp_session_get_n_endpoints(), wp_session_get_endpoint() and
* wp_session_get_all_endpoints()
* the use of wp_session_get_n_endpoints(), wp_session_find_endpoint() and
* wp_session_iterate_endpoints()
* @WP_SESSION_FEATURE_LINKS: caches information about endpoint links, enabling
* the use of wp_session_get_n_links(), wp_session_get_link() and
* wp_session_get_all_links()
* the use of wp_session_get_n_links(), wp_session_find_link() and
* wp_session_iterate_links()
*
* An extension of #WpProxyFeatures
*/
@ -92,19 +92,19 @@ WP_API
guint wp_session_get_n_endpoints (WpSession * self);
WP_API
WpEndpoint * wp_session_get_endpoint (WpSession * self, guint32 bound_id);
WpEndpoint * wp_session_find_endpoint (WpSession * self, guint32 bound_id);
WP_API
GPtrArray * wp_session_get_all_endpoints (WpSession * self);
WpIterator * wp_session_iterate_endpoints (WpSession * self);
WP_API
guint wp_session_get_n_links (WpSession * self);
WP_API
WpEndpointLink * wp_session_get_link (WpSession * self, guint32 bound_id);
WpEndpointLink * wp_session_find_link (WpSession * self, guint32 bound_id);
WP_API
GPtrArray * wp_session_get_all_links (WpSession * self);
WpIterator * wp_session_iterate_links (WpSession * self);
/**
* WP_TYPE_IMPL_SESSION:

View file

@ -46,7 +46,6 @@ struct _WpAudioStreamPrivate
WpObjectManager *ports_om;
WpObjectManager *audio_fade_source_ports_om;
GVariantBuilder port_vb;
gboolean port_config_done;
gboolean port_control_pending;
@ -610,10 +609,11 @@ wp_audio_stream_get_info (WpAudioStream * self)
return wp_proxy_get_info (WP_PROXY (priv->proxy));
}
static void
port_proxies_foreach_func(gpointer data, gpointer user_data)
static gboolean
port_proxies_fold_func (const GValue *item, GValue *ret, gpointer user_data)
{
WpProxy *port = WP_PROXY (data);
WpProxy *port = g_value_get_object (item);
GVariantBuilder *b = g_value_get_pointer (ret);
WpAudioStream *self = WP_AUDIO_STREAM (user_data);
WpAudioStreamPrivate *priv = wp_audio_stream_get_instance_private (self);
const struct pw_node_info *node_info;
@ -623,16 +623,16 @@ port_proxies_foreach_func(gpointer data, gpointer user_data)
uint32_t channel_n = SPA_AUDIO_CHANNEL_UNKNOWN;
node_info = wp_proxy_get_info (WP_PROXY (priv->proxy));
g_return_if_fail (node_info);
g_return_val_if_fail (node_info, TRUE);
port_info = wp_proxy_get_info (port);
g_return_if_fail (port_info);
g_return_val_if_fail (port_info, TRUE);
props = wp_proxy_get_properties (port);
/* skip control ports */
if (is_stream_control_port (WP_PORT (port)))
return;
return TRUE;
channel = wp_properties_get (props, PW_KEY_AUDIO_CHANNEL);
if (channel) {
@ -652,8 +652,9 @@ port_proxies_foreach_func(gpointer data, gpointer user_data)
uint32 channel; // enum spa_audio_channel
uint8 direction; // enum spa_direction
*/
g_variant_builder_add (&priv->port_vb, "(uuuy)", node_info->id,
g_variant_builder_add (b, "(uuuy)", node_info->id,
port_info->id, channel_n, (guint8) port_info->direction);
return TRUE;
}
gboolean
@ -661,14 +662,19 @@ wp_audio_stream_prepare_link (WpAudioStream * self, GVariant ** properties,
GError ** error)
{
WpAudioStreamPrivate *priv = wp_audio_stream_get_instance_private (self);
g_autoptr (GPtrArray) port_proxies =
wp_object_manager_get_objects (priv->ports_om, 0);
GVariantBuilder b;
g_auto (GValue) val = G_VALUE_INIT;
g_autoptr (WpIterator) it = NULL;
/* Create a variant array with all the ports */
g_variant_builder_init (&priv->port_vb, G_VARIANT_TYPE ("a(uuuy)"));
g_ptr_array_foreach (port_proxies, port_proxies_foreach_func, self);
*properties = g_variant_builder_end (&priv->port_vb);
g_variant_builder_init (&b, G_VARIANT_TYPE ("a(uuuy)"));
g_value_init (&val, G_TYPE_POINTER);
g_value_set_pointer (&val, &b);
it = wp_object_manager_iterate (priv->ports_om);
wp_iterator_fold (it, port_proxies_fold_func, &val, self);
*properties = g_variant_builder_end (&b);
return TRUE;
}

View file

@ -20,7 +20,6 @@ struct _WpVideoEndpoint
/* The task to signal the endpoint is initialized */
GTask *init_task;
GVariantBuilder port_vb;
WpObjectManager *ports_om;
};
@ -65,19 +64,20 @@ wp_video_endpoint_get_global_id (WpBaseEndpoint *ep)
return wp_proxy_get_bound_id (WP_PROXY (self->node));
}
static void
port_proxies_foreach_func (gpointer data, gpointer user_data)
static gboolean
port_proxies_fold_func (const GValue *item, GValue *ret, gpointer user_data)
{
WpProxy *port = WP_PROXY (data);
WpProxy *port = g_value_get_object (item);
GVariantBuilder *b = g_value_get_pointer (ret);
WpVideoEndpoint *self = WP_VIDEO_ENDPOINT (user_data);
const struct pw_node_info *node_info;
const struct pw_port_info *port_info;
node_info = wp_proxy_get_info (WP_PROXY (self->node));
g_return_if_fail (node_info);
g_return_val_if_fail (node_info, TRUE);
port_info = wp_proxy_get_info (port);
g_return_if_fail (port_info);
g_return_val_if_fail (port_info, TRUE);
/* tuple format:
uint32 node_id;
@ -85,8 +85,9 @@ port_proxies_foreach_func (gpointer data, gpointer user_data)
uint32 channel; // always 0 for video
uint8 direction; // enum spa_direction
*/
g_variant_builder_add (&self->port_vb, "(uuuy)", node_info->id,
g_variant_builder_add (b, "(uuuy)", node_info->id,
port_info->id, 0, (guint8) port_info->direction);
return TRUE;
}
static gboolean
@ -94,14 +95,19 @@ wp_video_endpoint_prepare_link (WpBaseEndpoint * ep, guint32 stream_id,
WpBaseEndpointLink * link, GVariant ** properties, GError ** error)
{
WpVideoEndpoint *self = WP_VIDEO_ENDPOINT (ep);
g_autoptr (GPtrArray) port_proxies = wp_object_manager_get_objects (
self->ports_om, 0);
GVariantBuilder b;
g_auto (GValue) val = G_VALUE_INIT;
g_autoptr (WpIterator) it = NULL;
/* Create a variant array with all the ports */
g_variant_builder_init (&self->port_vb, G_VARIANT_TYPE ("a(uuuy)"));
g_ptr_array_foreach (port_proxies, port_proxies_foreach_func, self);
*properties = g_variant_builder_end (&self->port_vb);
g_variant_builder_init (&b, G_VARIANT_TYPE ("a(uuuy)"));
g_value_init (&val, G_TYPE_POINTER);
g_value_set_pointer (&val, &b);
it = wp_object_manager_iterate (self->ports_om);
wp_iterator_fold (it, port_proxies_fold_func, &val, self);
*properties = g_variant_builder_end (&b);
return TRUE;
}

View file

@ -64,34 +64,52 @@ print_client_endpoint (WpEndpoint *ep)
static void
list_endpoints (WpObjectManager * om, struct WpCliData * d)
{
g_autoptr (GPtrArray) arr = NULL;
g_autoptr (WpIterator) it = NULL;
g_autoptr (WpSession) session = NULL;
guint i;
g_auto (GValue) val = G_VALUE_INIT;
arr = wp_object_manager_get_objects (om, WP_TYPE_SESSION);
if (arr->len > 0)
session = WP_SESSION (g_object_ref (g_ptr_array_index (arr, 0)));
g_clear_pointer (&arr, g_ptr_array_unref);
it = wp_object_manager_iterate (om);
for (; wp_iterator_next (it, &val) &&
g_type_is_a (G_VALUE_TYPE (&val), WP_TYPE_SESSION);
g_value_unset (&val))
{
session = g_value_dup_object (&val);
g_value_unset (&val);
break;
}
arr = wp_object_manager_get_objects (om, WP_TYPE_ENDPOINT);
wp_iterator_reset (it);
g_print ("Audio capture devices:\n");
for (i = 0; i < arr->len; i++) {
WpEndpoint *ep = g_ptr_array_index (arr, i);
for (; wp_iterator_next (it, &val) &&
g_type_is_a (G_VALUE_TYPE (&val), WP_TYPE_ENDPOINT);
g_value_unset (&val))
{
WpEndpoint *ep = g_value_get_object (&val);
if (g_strcmp0 (wp_endpoint_get_media_class (ep), "Audio/Source") == 0)
print_dev_endpoint (ep, session, WP_DEFAULT_ENDPOINT_TYPE_AUDIO_SOURCE);
}
wp_iterator_reset (it);
g_print ("\nAudio playback devices:\n");
for (i = 0; i < arr->len; i++) {
WpEndpoint *ep = g_ptr_array_index (arr, i);
for (; wp_iterator_next (it, &val) &&
g_type_is_a (G_VALUE_TYPE (&val), WP_TYPE_ENDPOINT);
g_value_unset (&val))
{
WpEndpoint *ep = g_value_get_object (&val);
if (g_strcmp0 (wp_endpoint_get_media_class (ep), "Audio/Sink") == 0)
print_dev_endpoint (ep, session, WP_DEFAULT_ENDPOINT_TYPE_AUDIO_SINK);
}
wp_iterator_reset (it);
g_print ("\nClient streams:\n");
for (i = 0; i < arr->len; i++) {
WpEndpoint *ep = g_ptr_array_index (arr, i);
for (; wp_iterator_next (it, &val) &&
g_type_is_a (G_VALUE_TYPE (&val), WP_TYPE_ENDPOINT);
g_value_unset (&val))
{
WpEndpoint *ep = g_value_get_object (&val);
if (g_str_has_suffix (wp_endpoint_get_media_class (ep), "/Audio"))
print_client_endpoint (ep);
}
@ -102,14 +120,20 @@ list_endpoints (WpObjectManager * om, struct WpCliData * d)
static void
set_default (WpObjectManager * om, struct WpCliData * d)
{
g_autoptr (GPtrArray) arr = NULL;
g_autoptr (WpIterator) it = NULL;
g_autoptr (WpSession) session = NULL;
guint i;
g_auto (GValue) val = G_VALUE_INIT;
arr = wp_object_manager_get_objects (om, WP_TYPE_SESSION);
if (arr->len > 0)
session = WP_SESSION (g_object_ref (g_ptr_array_index (arr, 0)));
g_clear_pointer (&arr, g_ptr_array_unref);
it = wp_object_manager_iterate (om);
for (; wp_iterator_next (it, &val) &&
g_type_is_a (G_VALUE_TYPE (&val), WP_TYPE_SESSION);
g_value_unset (&val))
{
session = g_value_dup_object (&val);
g_value_unset (&val);
break;
}
if (!session) {
g_print ("No Session object - changing the default endpoint is not supported\n");
@ -117,10 +141,13 @@ set_default (WpObjectManager * om, struct WpCliData * d)
return;
}
arr = wp_object_manager_get_objects (om, WP_TYPE_ENDPOINT);
wp_iterator_reset (it);
for (i = 0; i < arr->len; i++) {
WpEndpoint *ep = g_ptr_array_index (arr, i);
for (; wp_iterator_next (it, &val) &&
g_type_is_a (G_VALUE_TYPE (&val), WP_TYPE_ENDPOINT);
g_value_unset (&val))
{
WpEndpoint *ep = g_value_get_object (&val);
guint32 id = wp_proxy_get_bound_id (WP_PROXY (ep));
if (id == d->params.set_default.id) {
@ -148,13 +175,13 @@ set_default (WpObjectManager * om, struct WpCliData * d)
static void
set_volume (WpObjectManager * om, struct WpCliData * d)
{
g_autoptr (GPtrArray) arr = NULL;
guint i;
g_autoptr (WpIterator) it = NULL;
g_auto (GValue) val = G_VALUE_INIT;
arr = wp_object_manager_get_objects (om, WP_TYPE_ENDPOINT);
it = wp_object_manager_iterate (om);
for (i = 0; i < arr->len; i++) {
WpEndpoint *ep = g_ptr_array_index (arr, i);
for (; wp_iterator_next (it, &val); g_value_unset (&val)) {
WpEndpoint *ep = g_value_get_object (&val);
guint32 id = wp_proxy_get_bound_id (WP_PROXY (ep));
if (id == d->params.set_volume.id) {
@ -172,17 +199,17 @@ set_volume (WpObjectManager * om, struct WpCliData * d)
static void
device_node_props (WpObjectManager * om, struct WpCliData * d)
{
g_autoptr (GPtrArray) arr = NULL;
guint i;
g_autoptr (WpIterator) it = NULL;
g_auto (GValue) val = G_VALUE_INIT;
const struct spa_dict * dict;
const struct spa_dict_item *item;
arr = wp_object_manager_get_objects (om, WP_TYPE_NODE);
it = wp_object_manager_iterate (om);
g_print ("Capture device nodes:\n");
for (i = 0; i < arr->len; i++) {
WpProxy *node = g_ptr_array_index (arr, i);
for (; wp_iterator_next (it, &val); g_value_unset (&val)) {
WpProxy *node = g_value_get_object (&val);
g_autoptr (WpProperties) props = wp_proxy_get_properties (node);
if (g_strcmp0 (wp_properties_get (props, "media.class"), "Audio/Source") != 0)
@ -198,10 +225,11 @@ device_node_props (WpObjectManager * om, struct WpCliData * d)
g_print ("\n");
}
wp_iterator_reset (it);
g_print ("Playback device nodes:\n");
for (i = 0; i < arr->len; i++) {
WpProxy *node = g_ptr_array_index (arr, i);
for (; wp_iterator_next (it, &val); g_value_unset (&val)) {
WpProxy *node = g_value_get_object (&val);
g_autoptr (WpProperties) props = wp_proxy_get_properties (node);
if (g_strcmp0 (wp_properties_get (props, "media.class"), "Audio/Sink") != 0)