2020-03-12 18:00:01 +02:00
|
|
|
/* WirePlumber
|
|
|
|
|
*
|
|
|
|
|
* Copyright © 2020 Collabora Ltd.
|
|
|
|
|
* @author George Kiagiadakis <george.kiagiadakis@collabora.com>
|
|
|
|
|
*
|
|
|
|
|
* SPDX-License-Identifier: MIT
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* SECTION: WpSessionItem
|
2020-03-18 17:13:52 +02:00
|
|
|
* @title: Session Items
|
2020-03-12 18:00:01 +02:00
|
|
|
*/
|
|
|
|
|
|
2020-04-14 18:31:17 +03:00
|
|
|
#define G_LOG_DOMAIN "wp-si"
|
|
|
|
|
|
2020-03-12 18:00:01 +02:00
|
|
|
#include "session-item.h"
|
2020-11-16 10:34:58 +02:00
|
|
|
#include "core.h"
|
2020-04-16 17:38:31 +03:00
|
|
|
#include "debug.h"
|
2020-03-20 14:45:17 +02:00
|
|
|
#include "error.h"
|
2020-03-12 18:00:01 +02:00
|
|
|
#include "wpenums.h"
|
2020-11-15 20:01:51 +02:00
|
|
|
#include "private/impl-endpoint.h"
|
2020-03-12 18:00:01 +02:00
|
|
|
|
2020-11-16 10:34:58 +02:00
|
|
|
#include <spa/utils/defs.h>
|
|
|
|
|
|
2020-03-29 11:17:16 +03:00
|
|
|
struct _WpSiTransition
|
|
|
|
|
{
|
|
|
|
|
WpTransition parent;
|
|
|
|
|
guint (*get_next_step) (WpSessionItem * self, WpTransition * transition,
|
|
|
|
|
guint step);
|
|
|
|
|
void (*execute_step) (WpSessionItem * self, WpTransition * transition,
|
|
|
|
|
guint step);
|
2020-04-16 13:18:21 +03:00
|
|
|
void (*rollback) (WpSessionItem * self);
|
2020-03-29 11:17:16 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
G_DECLARE_FINAL_TYPE (WpSiTransition, wp_si_transition,
|
|
|
|
|
WP, SI_TRANSITION, WpTransition);
|
|
|
|
|
G_DEFINE_TYPE (WpSiTransition, wp_si_transition, WP_TYPE_TRANSITION)
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
wp_si_transition_init (WpSiTransition * transition) {}
|
|
|
|
|
|
|
|
|
|
static guint
|
|
|
|
|
wp_si_transition_get_next_step (WpTransition * transition, guint step)
|
|
|
|
|
{
|
|
|
|
|
WpSiTransition *self = WP_SI_TRANSITION (transition);
|
|
|
|
|
WpSessionItem *item = wp_transition_get_source_object (transition);
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (self->get_next_step, WP_TRANSITION_STEP_ERROR);
|
|
|
|
|
|
|
|
|
|
step = self->get_next_step (item, transition, step);
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (step == WP_TRANSITION_STEP_NONE || self->execute_step,
|
|
|
|
|
WP_TRANSITION_STEP_ERROR);
|
|
|
|
|
return step;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
wp_si_transition_execute_step (WpTransition * transition, guint step)
|
|
|
|
|
{
|
|
|
|
|
WpSiTransition *self = WP_SI_TRANSITION (transition);
|
|
|
|
|
WpSessionItem *item = wp_transition_get_source_object (transition);
|
2020-04-16 13:18:21 +03:00
|
|
|
|
|
|
|
|
if (step != WP_TRANSITION_STEP_ERROR)
|
|
|
|
|
self->execute_step (item, transition, step);
|
|
|
|
|
else if (self->rollback)
|
|
|
|
|
self->rollback (item);
|
2020-03-29 11:17:16 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
wp_si_transition_class_init (WpSiTransitionClass * klass)
|
|
|
|
|
{
|
|
|
|
|
WpTransitionClass *transition_class = (WpTransitionClass *) klass;
|
|
|
|
|
|
|
|
|
|
transition_class->get_next_step = wp_si_transition_get_next_step;
|
|
|
|
|
transition_class->execute_step = wp_si_transition_execute_step;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2020-03-12 18:00:01 +02:00
|
|
|
typedef struct _WpSessionItemPrivate WpSessionItemPrivate;
|
|
|
|
|
struct _WpSessionItemPrivate
|
|
|
|
|
{
|
|
|
|
|
GWeakRef session;
|
|
|
|
|
guint32 flags;
|
2020-04-28 11:26:51 -04:00
|
|
|
GWeakRef parent;
|
2020-03-20 14:45:17 +02:00
|
|
|
|
2020-03-31 19:40:49 +03:00
|
|
|
union {
|
|
|
|
|
WpProxy *impl_proxy;
|
|
|
|
|
WpImplEndpoint *impl_endpoint;
|
|
|
|
|
WpImplEndpointLink *impl_link;
|
|
|
|
|
};
|
2020-03-29 14:20:22 +03:00
|
|
|
GHashTable *impl_streams;
|
2020-03-12 18:00:01 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
enum {
|
|
|
|
|
SIGNAL_FLAGS_CHANGED,
|
|
|
|
|
N_SIGNALS
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
guint32 signals[N_SIGNALS] = {0};
|
|
|
|
|
|
2020-03-18 17:13:52 +02:00
|
|
|
/**
|
|
|
|
|
* WpSessionItem:
|
|
|
|
|
*/
|
2020-03-12 18:00:01 +02:00
|
|
|
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (WpSessionItem, wp_session_item, G_TYPE_OBJECT)
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
wp_session_item_init (WpSessionItem * self)
|
|
|
|
|
{
|
|
|
|
|
WpSessionItemPrivate *priv =
|
|
|
|
|
wp_session_item_get_instance_private (self);
|
|
|
|
|
|
|
|
|
|
g_weak_ref_init (&priv->session, NULL);
|
2020-04-28 11:26:51 -04:00
|
|
|
g_weak_ref_init (&priv->parent, NULL);
|
2020-03-12 18:00:01 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
wp_session_item_dispose (GObject * object)
|
|
|
|
|
{
|
|
|
|
|
WpSessionItem * self = WP_SESSION_ITEM (object);
|
|
|
|
|
|
|
|
|
|
wp_session_item_reset (self);
|
|
|
|
|
|
|
|
|
|
G_OBJECT_CLASS (wp_session_item_parent_class)->dispose (object);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
wp_session_item_finalize (GObject * object)
|
|
|
|
|
{
|
|
|
|
|
WpSessionItem * self = WP_SESSION_ITEM (object);
|
2020-03-20 14:45:17 +02:00
|
|
|
WpSessionItemPrivate *priv = wp_session_item_get_instance_private (self);
|
2020-03-12 18:00:01 +02:00
|
|
|
|
|
|
|
|
g_weak_ref_clear (&priv->session);
|
2020-04-28 11:26:51 -04:00
|
|
|
g_weak_ref_clear (&priv->parent);
|
2020-03-12 18:00:01 +02:00
|
|
|
|
|
|
|
|
G_OBJECT_CLASS (wp_session_item_parent_class)->finalize (object);
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-09 19:24:42 +03:00
|
|
|
static void
|
|
|
|
|
wp_session_item_default_reset (WpSessionItem * self)
|
|
|
|
|
{
|
|
|
|
|
wp_session_item_unexport (self);
|
|
|
|
|
wp_session_item_deactivate (self);
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-29 16:03:54 +03:00
|
|
|
static gpointer
|
|
|
|
|
wp_session_item_default_get_associated_proxy (WpSessionItem * self,
|
|
|
|
|
GType proxy_type)
|
|
|
|
|
{
|
|
|
|
|
WpSessionItemPrivate *priv;
|
2020-05-05 16:31:53 +03:00
|
|
|
gpointer ret = NULL;
|
2020-03-29 16:03:54 +03:00
|
|
|
|
|
|
|
|
if (WP_IS_SI_STREAM (self)) {
|
2020-04-28 11:29:15 -04:00
|
|
|
g_autoptr (WpSiEndpoint) ep =
|
|
|
|
|
wp_si_stream_get_parent_endpoint (WP_SI_STREAM (self));
|
2020-03-29 16:03:54 +03:00
|
|
|
priv = wp_session_item_get_instance_private (WP_SESSION_ITEM (ep));
|
|
|
|
|
} else {
|
|
|
|
|
priv = wp_session_item_get_instance_private (self);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (proxy_type == WP_TYPE_SESSION) {
|
2020-05-05 16:31:53 +03:00
|
|
|
ret = g_weak_ref_get (&priv->session);
|
2020-03-29 16:03:54 +03:00
|
|
|
}
|
|
|
|
|
else if (proxy_type == WP_TYPE_ENDPOINT) {
|
2020-03-31 19:40:49 +03:00
|
|
|
if (priv->impl_proxy && WP_IS_ENDPOINT (priv->impl_proxy))
|
2020-05-05 16:31:53 +03:00
|
|
|
ret = g_object_ref (priv->impl_proxy);
|
2020-03-31 19:40:49 +03:00
|
|
|
}
|
|
|
|
|
else if (proxy_type == WP_TYPE_ENDPOINT_LINK) {
|
|
|
|
|
if (priv->impl_proxy && WP_IS_ENDPOINT_LINK (priv->impl_proxy))
|
2020-05-05 16:31:53 +03:00
|
|
|
ret = g_object_ref (priv->impl_proxy);
|
2020-03-29 16:03:54 +03:00
|
|
|
}
|
|
|
|
|
else if (proxy_type == WP_TYPE_ENDPOINT_STREAM) {
|
|
|
|
|
gpointer impl_stream = priv->impl_streams ?
|
|
|
|
|
g_hash_table_lookup (priv->impl_streams, self) : NULL;
|
2020-05-05 16:31:53 +03:00
|
|
|
ret = impl_stream ? g_object_ref (impl_stream) : NULL;
|
2020-03-29 16:03:54 +03:00
|
|
|
}
|
|
|
|
|
|
2020-05-05 16:31:53 +03:00
|
|
|
wp_trace_object (self, "associated %s: " WP_OBJECT_FORMAT,
|
|
|
|
|
g_type_name (proxy_type), WP_OBJECT_ARGS (ret));
|
|
|
|
|
|
|
|
|
|
return ret;
|
2020-03-29 16:03:54 +03:00
|
|
|
}
|
|
|
|
|
|
2020-03-20 14:42:33 +02:00
|
|
|
static guint
|
2020-04-16 17:38:31 +03:00
|
|
|
wp_session_item_default_activate_get_next_step (WpSessionItem * self,
|
2020-03-20 14:42:33 +02:00
|
|
|
WpTransition * transition, guint step)
|
|
|
|
|
{
|
|
|
|
|
/* the default implementation just activates instantly,
|
|
|
|
|
without taking any action */
|
|
|
|
|
return WP_TRANSITION_STEP_NONE;
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-29 14:20:22 +03:00
|
|
|
enum {
|
|
|
|
|
EXPORT_STEP_ENDPOINT = WP_TRANSITION_STEP_CUSTOM_START,
|
|
|
|
|
EXPORT_STEP_STREAMS,
|
2020-05-11 09:56:06 +03:00
|
|
|
EXPORT_STEP_ENDPOINT_FT_STREAMS,
|
2020-03-29 14:20:22 +03:00
|
|
|
EXPORT_STEP_LINK,
|
2020-05-07 16:02:23 +03:00
|
|
|
EXPORT_STEP_CONNECT_DESTROYED,
|
2020-03-29 14:20:22 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static guint
|
2020-04-16 17:38:31 +03:00
|
|
|
wp_session_item_default_export_get_next_step (WpSessionItem * self,
|
|
|
|
|
WpTransition * transition, guint step)
|
2020-03-29 14:20:22 +03:00
|
|
|
{
|
|
|
|
|
WpSessionItemPrivate *priv = wp_session_item_get_instance_private (self);
|
|
|
|
|
|
|
|
|
|
switch (step) {
|
|
|
|
|
case WP_TRANSITION_STEP_NONE:
|
2020-04-16 17:38:31 +03:00
|
|
|
if (WP_IS_SI_ENDPOINT (self))
|
2020-03-29 14:20:22 +03:00
|
|
|
return EXPORT_STEP_ENDPOINT;
|
2020-04-16 17:38:31 +03:00
|
|
|
else if (WP_IS_SI_LINK (self))
|
2020-03-29 14:20:22 +03:00
|
|
|
return EXPORT_STEP_LINK;
|
|
|
|
|
else {
|
|
|
|
|
wp_transition_return_error (transition, g_error_new (
|
|
|
|
|
WP_DOMAIN_LIBRARY, WP_LIBRARY_ERROR_INVALID_ARGUMENT,
|
2020-04-16 17:38:31 +03:00
|
|
|
"Cannot export WpSessionItem of unknown type " WP_OBJECT_FORMAT,
|
|
|
|
|
WP_OBJECT_ARGS (self)));
|
2020-03-29 14:20:22 +03:00
|
|
|
return WP_TRANSITION_STEP_ERROR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case EXPORT_STEP_ENDPOINT:
|
2020-04-09 19:24:42 +03:00
|
|
|
g_return_val_if_fail (WP_IS_SI_ENDPOINT (self), WP_TRANSITION_STEP_ERROR);
|
2020-03-29 14:20:22 +03:00
|
|
|
return EXPORT_STEP_STREAMS;
|
|
|
|
|
|
|
|
|
|
case EXPORT_STEP_STREAMS:
|
|
|
|
|
g_return_val_if_fail (WP_IS_SI_ENDPOINT (self), WP_TRANSITION_STEP_ERROR);
|
|
|
|
|
g_return_val_if_fail (priv->impl_streams, WP_TRANSITION_STEP_ERROR);
|
|
|
|
|
|
lib: refactor WpProxy
This is an attempt to unclutter the API of WpProxy and
split functionality into smaller pieces, making it easier
to work with.
In this new class layout, we have the following classes:
- WpObject: base class for everything; handles activating
| and deactivating "features"
|- WpProxy: base class for anything that wraps a pw_proxy;
| handles events from pw_proxy and nothing more
|- WpGlobalProxy: handles integration with the registry
All the other classes derive from WpGlobalProxy. The reason
for separating WpGlobalProxy from WpProxy, though, is that
classes such as WpImplNode / WpSpaDevice can also derive from
WpProxy now, without interfacing with the registry.
All objects that come with an "info" structure and have properties
and/or params also implement the WpPipewireObject interface. This
provides the API to query properties and get/set params. Essentially,
this is implemented by all classes except WpMetadata (pw_metadata
does not have info)
This interface is implemented on each object separately, using
a private "mixin", which is a set of vfunc implementations and helper
functions (and macros) to facilitate the implementation of this interface.
A notable difference to the old WpProxy is that now features can be
deactivated, so it is possible to enable something and later disable
it again.
This commit disables modules, tests, tools, etc, to avoid growing the
patch more, while ensuring that the project compiles.
2020-11-10 19:17:02 +02:00
|
|
|
/* go to next step only when all impl proxies are activated */
|
2020-03-29 14:20:22 +03:00
|
|
|
if (g_hash_table_size (priv->impl_streams) ==
|
|
|
|
|
wp_si_endpoint_get_n_streams (WP_SI_ENDPOINT (self)))
|
2020-05-11 09:56:06 +03:00
|
|
|
return EXPORT_STEP_ENDPOINT_FT_STREAMS;
|
2020-03-29 14:20:22 +03:00
|
|
|
else
|
|
|
|
|
return step;
|
|
|
|
|
|
2020-05-11 09:56:06 +03:00
|
|
|
case EXPORT_STEP_ENDPOINT_FT_STREAMS:
|
|
|
|
|
return WP_TRANSITION_STEP_NONE;
|
|
|
|
|
|
2020-03-31 19:40:49 +03:00
|
|
|
case EXPORT_STEP_LINK:
|
2020-04-09 19:24:42 +03:00
|
|
|
g_return_val_if_fail (WP_IS_SI_LINK (self), WP_TRANSITION_STEP_ERROR);
|
2020-05-07 16:02:23 +03:00
|
|
|
return EXPORT_STEP_CONNECT_DESTROYED;
|
|
|
|
|
|
|
|
|
|
case EXPORT_STEP_CONNECT_DESTROYED:
|
2020-03-29 14:20:22 +03:00
|
|
|
return WP_TRANSITION_STEP_NONE;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
return WP_TRANSITION_STEP_ERROR;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-20 14:45:17 +02:00
|
|
|
static void
|
lib: refactor WpProxy
This is an attempt to unclutter the API of WpProxy and
split functionality into smaller pieces, making it easier
to work with.
In this new class layout, we have the following classes:
- WpObject: base class for everything; handles activating
| and deactivating "features"
|- WpProxy: base class for anything that wraps a pw_proxy;
| handles events from pw_proxy and nothing more
|- WpGlobalProxy: handles integration with the registry
All the other classes derive from WpGlobalProxy. The reason
for separating WpGlobalProxy from WpProxy, though, is that
classes such as WpImplNode / WpSpaDevice can also derive from
WpProxy now, without interfacing with the registry.
All objects that come with an "info" structure and have properties
and/or params also implement the WpPipewireObject interface. This
provides the API to query properties and get/set params. Essentially,
this is implemented by all classes except WpMetadata (pw_metadata
does not have info)
This interface is implemented on each object separately, using
a private "mixin", which is a set of vfunc implementations and helper
functions (and macros) to facilitate the implementation of this interface.
A notable difference to the old WpProxy is that now features can be
deactivated, so it is possible to enable something and later disable
it again.
This commit disables modules, tests, tools, etc, to avoid growing the
patch more, while ensuring that the project compiles.
2020-11-10 19:17:02 +02:00
|
|
|
on_export_proxy_activated (WpObject * proxy, GAsyncResult * res, gpointer data)
|
2020-03-20 14:45:17 +02:00
|
|
|
{
|
2020-03-29 14:20:22 +03:00
|
|
|
WpTransition *transition = WP_TRANSITION (data);
|
|
|
|
|
WpSessionItem *self = wp_transition_get_source_object (transition);
|
2020-03-20 14:45:17 +02:00
|
|
|
WpSessionItemPrivate *priv = wp_session_item_get_instance_private (self);
|
2020-03-29 14:20:22 +03:00
|
|
|
g_autoptr (GError) error = NULL;
|
2020-03-20 14:45:17 +02:00
|
|
|
|
lib: refactor WpProxy
This is an attempt to unclutter the API of WpProxy and
split functionality into smaller pieces, making it easier
to work with.
In this new class layout, we have the following classes:
- WpObject: base class for everything; handles activating
| and deactivating "features"
|- WpProxy: base class for anything that wraps a pw_proxy;
| handles events from pw_proxy and nothing more
|- WpGlobalProxy: handles integration with the registry
All the other classes derive from WpGlobalProxy. The reason
for separating WpGlobalProxy from WpProxy, though, is that
classes such as WpImplNode / WpSpaDevice can also derive from
WpProxy now, without interfacing with the registry.
All objects that come with an "info" structure and have properties
and/or params also implement the WpPipewireObject interface. This
provides the API to query properties and get/set params. Essentially,
this is implemented by all classes except WpMetadata (pw_metadata
does not have info)
This interface is implemented on each object separately, using
a private "mixin", which is a set of vfunc implementations and helper
functions (and macros) to facilitate the implementation of this interface.
A notable difference to the old WpProxy is that now features can be
deactivated, so it is possible to enable something and later disable
it again.
This commit disables modules, tests, tools, etc, to avoid growing the
patch more, while ensuring that the project compiles.
2020-11-10 19:17:02 +02:00
|
|
|
if (!wp_object_activate_finish (proxy, res, &error)) {
|
2020-03-29 14:20:22 +03:00
|
|
|
wp_transition_return_error (transition, g_steal_pointer (&error));
|
2020-03-20 14:45:17 +02:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-29 14:20:22 +03:00
|
|
|
if (WP_IS_IMPL_ENDPOINT_STREAM (proxy)) {
|
|
|
|
|
g_autoptr (WpSiStream) si_stream = NULL;
|
|
|
|
|
|
|
|
|
|
g_object_get (proxy, "item", &si_stream, NULL);
|
|
|
|
|
g_return_if_fail (si_stream != NULL);
|
|
|
|
|
|
|
|
|
|
g_hash_table_insert (priv->impl_streams, si_stream, g_object_ref (proxy));
|
|
|
|
|
}
|
|
|
|
|
|
lib: refactor WpProxy
This is an attempt to unclutter the API of WpProxy and
split functionality into smaller pieces, making it easier
to work with.
In this new class layout, we have the following classes:
- WpObject: base class for everything; handles activating
| and deactivating "features"
|- WpProxy: base class for anything that wraps a pw_proxy;
| handles events from pw_proxy and nothing more
|- WpGlobalProxy: handles integration with the registry
All the other classes derive from WpGlobalProxy. The reason
for separating WpGlobalProxy from WpProxy, though, is that
classes such as WpImplNode / WpSpaDevice can also derive from
WpProxy now, without interfacing with the registry.
All objects that come with an "info" structure and have properties
and/or params also implement the WpPipewireObject interface. This
provides the API to query properties and get/set params. Essentially,
this is implemented by all classes except WpMetadata (pw_metadata
does not have info)
This interface is implemented on each object separately, using
a private "mixin", which is a set of vfunc implementations and helper
functions (and macros) to facilitate the implementation of this interface.
A notable difference to the old WpProxy is that now features can be
deactivated, so it is possible to enable something and later disable
it again.
This commit disables modules, tests, tools, etc, to avoid growing the
patch more, while ensuring that the project compiles.
2020-11-10 19:17:02 +02:00
|
|
|
wp_debug_object (self, "export proxy " WP_OBJECT_FORMAT " activated",
|
2020-05-11 09:56:06 +03:00
|
|
|
WP_OBJECT_ARGS (proxy));
|
|
|
|
|
|
2020-03-29 14:20:22 +03:00
|
|
|
wp_transition_advance (transition);
|
2020-03-20 14:45:17 +02:00
|
|
|
}
|
|
|
|
|
|
2020-05-07 16:02:23 +03:00
|
|
|
static gboolean
|
|
|
|
|
on_export_proxy_destroyed_deferred (WpSessionItem * self)
|
|
|
|
|
{
|
|
|
|
|
WpSessionItemPrivate *priv = wp_session_item_get_instance_private (self);
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (priv->impl_proxy, G_SOURCE_REMOVE);
|
|
|
|
|
g_return_val_if_fail (WP_SESSION_ITEM_GET_CLASS (self)->export_rollback,
|
|
|
|
|
G_SOURCE_REMOVE);
|
|
|
|
|
|
|
|
|
|
wp_info_object (self, "destroying " WP_OBJECT_FORMAT
|
|
|
|
|
" upon request by the server", WP_OBJECT_ARGS (priv->impl_proxy));
|
|
|
|
|
|
|
|
|
|
WP_SESSION_ITEM_GET_CLASS (self)->export_rollback (self);
|
|
|
|
|
|
|
|
|
|
priv->flags |= WP_SI_FLAG_EXPORT_ERROR;
|
|
|
|
|
g_signal_emit (self, signals[SIGNAL_FLAGS_CHANGED], 0, priv->flags);
|
|
|
|
|
|
|
|
|
|
return G_SOURCE_REMOVE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
lib: refactor WpProxy
This is an attempt to unclutter the API of WpProxy and
split functionality into smaller pieces, making it easier
to work with.
In this new class layout, we have the following classes:
- WpObject: base class for everything; handles activating
| and deactivating "features"
|- WpProxy: base class for anything that wraps a pw_proxy;
| handles events from pw_proxy and nothing more
|- WpGlobalProxy: handles integration with the registry
All the other classes derive from WpGlobalProxy. The reason
for separating WpGlobalProxy from WpProxy, though, is that
classes such as WpImplNode / WpSpaDevice can also derive from
WpProxy now, without interfacing with the registry.
All objects that come with an "info" structure and have properties
and/or params also implement the WpPipewireObject interface. This
provides the API to query properties and get/set params. Essentially,
this is implemented by all classes except WpMetadata (pw_metadata
does not have info)
This interface is implemented on each object separately, using
a private "mixin", which is a set of vfunc implementations and helper
functions (and macros) to facilitate the implementation of this interface.
A notable difference to the old WpProxy is that now features can be
deactivated, so it is possible to enable something and later disable
it again.
This commit disables modules, tests, tools, etc, to avoid growing the
patch more, while ensuring that the project compiles.
2020-11-10 19:17:02 +02:00
|
|
|
on_export_proxy_destroyed (WpObject * proxy, gpointer data)
|
2020-05-07 16:02:23 +03:00
|
|
|
{
|
|
|
|
|
WpSessionItem *self = WP_SESSION_ITEM (data);
|
lib: refactor WpProxy
This is an attempt to unclutter the API of WpProxy and
split functionality into smaller pieces, making it easier
to work with.
In this new class layout, we have the following classes:
- WpObject: base class for everything; handles activating
| and deactivating "features"
|- WpProxy: base class for anything that wraps a pw_proxy;
| handles events from pw_proxy and nothing more
|- WpGlobalProxy: handles integration with the registry
All the other classes derive from WpGlobalProxy. The reason
for separating WpGlobalProxy from WpProxy, though, is that
classes such as WpImplNode / WpSpaDevice can also derive from
WpProxy now, without interfacing with the registry.
All objects that come with an "info" structure and have properties
and/or params also implement the WpPipewireObject interface. This
provides the API to query properties and get/set params. Essentially,
this is implemented by all classes except WpMetadata (pw_metadata
does not have info)
This interface is implemented on each object separately, using
a private "mixin", which is a set of vfunc implementations and helper
functions (and macros) to facilitate the implementation of this interface.
A notable difference to the old WpProxy is that now features can be
deactivated, so it is possible to enable something and later disable
it again.
This commit disables modules, tests, tools, etc, to avoid growing the
patch more, while ensuring that the project compiles.
2020-11-10 19:17:02 +02:00
|
|
|
g_autoptr (WpCore) core = wp_object_get_core (proxy);
|
2020-05-07 16:02:23 +03:00
|
|
|
|
2020-05-13 15:03:05 -04:00
|
|
|
if (core)
|
|
|
|
|
wp_core_idle_add_closure (core, NULL, g_cclosure_new_object (
|
2020-05-07 16:02:23 +03:00
|
|
|
G_CALLBACK (on_export_proxy_destroyed_deferred), G_OBJECT (self)));
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-20 14:45:17 +02:00
|
|
|
static void
|
2020-04-16 17:38:31 +03:00
|
|
|
wp_session_item_default_export_execute_step (WpSessionItem * self,
|
|
|
|
|
WpTransition * transition, guint step)
|
2020-03-20 14:45:17 +02:00
|
|
|
{
|
|
|
|
|
WpSessionItemPrivate *priv = wp_session_item_get_instance_private (self);
|
2020-03-29 14:20:22 +03:00
|
|
|
g_autoptr (WpSession) session = g_weak_ref_get (&priv->session);
|
lib: refactor WpProxy
This is an attempt to unclutter the API of WpProxy and
split functionality into smaller pieces, making it easier
to work with.
In this new class layout, we have the following classes:
- WpObject: base class for everything; handles activating
| and deactivating "features"
|- WpProxy: base class for anything that wraps a pw_proxy;
| handles events from pw_proxy and nothing more
|- WpGlobalProxy: handles integration with the registry
All the other classes derive from WpGlobalProxy. The reason
for separating WpGlobalProxy from WpProxy, though, is that
classes such as WpImplNode / WpSpaDevice can also derive from
WpProxy now, without interfacing with the registry.
All objects that come with an "info" structure and have properties
and/or params also implement the WpPipewireObject interface. This
provides the API to query properties and get/set params. Essentially,
this is implemented by all classes except WpMetadata (pw_metadata
does not have info)
This interface is implemented on each object separately, using
a private "mixin", which is a set of vfunc implementations and helper
functions (and macros) to facilitate the implementation of this interface.
A notable difference to the old WpProxy is that now features can be
deactivated, so it is possible to enable something and later disable
it again.
This commit disables modules, tests, tools, etc, to avoid growing the
patch more, while ensuring that the project compiles.
2020-11-10 19:17:02 +02:00
|
|
|
g_autoptr (WpCore) core = wp_object_get_core (WP_OBJECT (session));
|
2020-03-20 14:45:17 +02:00
|
|
|
|
2020-03-29 14:20:22 +03:00
|
|
|
switch (step) {
|
|
|
|
|
case EXPORT_STEP_ENDPOINT:
|
2020-03-20 14:45:17 +02:00
|
|
|
priv->impl_endpoint = wp_impl_endpoint_new (core, WP_SI_ENDPOINT (self));
|
|
|
|
|
|
lib: refactor WpProxy
This is an attempt to unclutter the API of WpProxy and
split functionality into smaller pieces, making it easier
to work with.
In this new class layout, we have the following classes:
- WpObject: base class for everything; handles activating
| and deactivating "features"
|- WpProxy: base class for anything that wraps a pw_proxy;
| handles events from pw_proxy and nothing more
|- WpGlobalProxy: handles integration with the registry
All the other classes derive from WpGlobalProxy. The reason
for separating WpGlobalProxy from WpProxy, though, is that
classes such as WpImplNode / WpSpaDevice can also derive from
WpProxy now, without interfacing with the registry.
All objects that come with an "info" structure and have properties
and/or params also implement the WpPipewireObject interface. This
provides the API to query properties and get/set params. Essentially,
this is implemented by all classes except WpMetadata (pw_metadata
does not have info)
This interface is implemented on each object separately, using
a private "mixin", which is a set of vfunc implementations and helper
functions (and macros) to facilitate the implementation of this interface.
A notable difference to the old WpProxy is that now features can be
deactivated, so it is possible to enable something and later disable
it again.
This commit disables modules, tests, tools, etc, to avoid growing the
patch more, while ensuring that the project compiles.
2020-11-10 19:17:02 +02:00
|
|
|
wp_object_activate (WP_OBJECT (priv->impl_endpoint),
|
|
|
|
|
WP_PIPEWIRE_OBJECT_FEATURES_ALL, NULL,
|
|
|
|
|
(GAsyncReadyCallback) on_export_proxy_activated,
|
2020-03-29 14:20:22 +03:00
|
|
|
transition);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case EXPORT_STEP_STREAMS: {
|
|
|
|
|
guint i, n_streams;
|
|
|
|
|
|
|
|
|
|
priv->impl_streams = g_hash_table_new_full (g_direct_hash, g_direct_equal,
|
|
|
|
|
NULL, g_object_unref);
|
|
|
|
|
|
|
|
|
|
n_streams = wp_si_endpoint_get_n_streams (WP_SI_ENDPOINT (self));
|
|
|
|
|
for (i = 0; i < n_streams; i++) {
|
|
|
|
|
WpSiStream *stream = wp_si_endpoint_get_stream (WP_SI_ENDPOINT (self), i);
|
|
|
|
|
WpImplEndpointStream *impl_stream =
|
|
|
|
|
wp_impl_endpoint_stream_new (core, stream);
|
|
|
|
|
|
lib: refactor WpProxy
This is an attempt to unclutter the API of WpProxy and
split functionality into smaller pieces, making it easier
to work with.
In this new class layout, we have the following classes:
- WpObject: base class for everything; handles activating
| and deactivating "features"
|- WpProxy: base class for anything that wraps a pw_proxy;
| handles events from pw_proxy and nothing more
|- WpGlobalProxy: handles integration with the registry
All the other classes derive from WpGlobalProxy. The reason
for separating WpGlobalProxy from WpProxy, though, is that
classes such as WpImplNode / WpSpaDevice can also derive from
WpProxy now, without interfacing with the registry.
All objects that come with an "info" structure and have properties
and/or params also implement the WpPipewireObject interface. This
provides the API to query properties and get/set params. Essentially,
this is implemented by all classes except WpMetadata (pw_metadata
does not have info)
This interface is implemented on each object separately, using
a private "mixin", which is a set of vfunc implementations and helper
functions (and macros) to facilitate the implementation of this interface.
A notable difference to the old WpProxy is that now features can be
deactivated, so it is possible to enable something and later disable
it again.
This commit disables modules, tests, tools, etc, to avoid growing the
patch more, while ensuring that the project compiles.
2020-11-10 19:17:02 +02:00
|
|
|
wp_object_activate (WP_OBJECT (impl_stream),
|
|
|
|
|
WP_OBJECT_FEATURES_ALL, NULL,
|
|
|
|
|
(GAsyncReadyCallback) on_export_proxy_activated,
|
2020-03-29 14:20:22 +03:00
|
|
|
transition);
|
|
|
|
|
|
|
|
|
|
/* the augment task holds a ref; object will be added to
|
lib: refactor WpProxy
This is an attempt to unclutter the API of WpProxy and
split functionality into smaller pieces, making it easier
to work with.
In this new class layout, we have the following classes:
- WpObject: base class for everything; handles activating
| and deactivating "features"
|- WpProxy: base class for anything that wraps a pw_proxy;
| handles events from pw_proxy and nothing more
|- WpGlobalProxy: handles integration with the registry
All the other classes derive from WpGlobalProxy. The reason
for separating WpGlobalProxy from WpProxy, though, is that
classes such as WpImplNode / WpSpaDevice can also derive from
WpProxy now, without interfacing with the registry.
All objects that come with an "info" structure and have properties
and/or params also implement the WpPipewireObject interface. This
provides the API to query properties and get/set params. Essentially,
this is implemented by all classes except WpMetadata (pw_metadata
does not have info)
This interface is implemented on each object separately, using
a private "mixin", which is a set of vfunc implementations and helper
functions (and macros) to facilitate the implementation of this interface.
A notable difference to the old WpProxy is that now features can be
deactivated, so it is possible to enable something and later disable
it again.
This commit disables modules, tests, tools, etc, to avoid growing the
patch more, while ensuring that the project compiles.
2020-11-10 19:17:02 +02:00
|
|
|
priv->impl_streams when activated */
|
2020-03-29 14:20:22 +03:00
|
|
|
g_object_unref (impl_stream);
|
|
|
|
|
}
|
|
|
|
|
break;
|
2020-03-20 14:45:17 +02:00
|
|
|
}
|
2020-05-11 09:56:06 +03:00
|
|
|
case EXPORT_STEP_ENDPOINT_FT_STREAMS:
|
|
|
|
|
/* add feature streams only after the streams are exported, otherwise
|
lib: refactor WpProxy
This is an attempt to unclutter the API of WpProxy and
split functionality into smaller pieces, making it easier
to work with.
In this new class layout, we have the following classes:
- WpObject: base class for everything; handles activating
| and deactivating "features"
|- WpProxy: base class for anything that wraps a pw_proxy;
| handles events from pw_proxy and nothing more
|- WpGlobalProxy: handles integration with the registry
All the other classes derive from WpGlobalProxy. The reason
for separating WpGlobalProxy from WpProxy, though, is that
classes such as WpImplNode / WpSpaDevice can also derive from
WpProxy now, without interfacing with the registry.
All objects that come with an "info" structure and have properties
and/or params also implement the WpPipewireObject interface. This
provides the API to query properties and get/set params. Essentially,
this is implemented by all classes except WpMetadata (pw_metadata
does not have info)
This interface is implemented on each object separately, using
a private "mixin", which is a set of vfunc implementations and helper
functions (and macros) to facilitate the implementation of this interface.
A notable difference to the old WpProxy is that now features can be
deactivated, so it is possible to enable something and later disable
it again.
This commit disables modules, tests, tools, etc, to avoid growing the
patch more, while ensuring that the project compiles.
2020-11-10 19:17:02 +02:00
|
|
|
the endpoint will never be activated in the first place (because it
|
2020-05-11 09:56:06 +03:00
|
|
|
internally waits for the streams to be ready) */
|
lib: refactor WpProxy
This is an attempt to unclutter the API of WpProxy and
split functionality into smaller pieces, making it easier
to work with.
In this new class layout, we have the following classes:
- WpObject: base class for everything; handles activating
| and deactivating "features"
|- WpProxy: base class for anything that wraps a pw_proxy;
| handles events from pw_proxy and nothing more
|- WpGlobalProxy: handles integration with the registry
All the other classes derive from WpGlobalProxy. The reason
for separating WpGlobalProxy from WpProxy, though, is that
classes such as WpImplNode / WpSpaDevice can also derive from
WpProxy now, without interfacing with the registry.
All objects that come with an "info" structure and have properties
and/or params also implement the WpPipewireObject interface. This
provides the API to query properties and get/set params. Essentially,
this is implemented by all classes except WpMetadata (pw_metadata
does not have info)
This interface is implemented on each object separately, using
a private "mixin", which is a set of vfunc implementations and helper
functions (and macros) to facilitate the implementation of this interface.
A notable difference to the old WpProxy is that now features can be
deactivated, so it is possible to enable something and later disable
it again.
This commit disables modules, tests, tools, etc, to avoid growing the
patch more, while ensuring that the project compiles.
2020-11-10 19:17:02 +02:00
|
|
|
wp_object_activate (WP_OBJECT (priv->impl_endpoint),
|
2020-05-11 09:56:06 +03:00
|
|
|
WP_ENDPOINT_FEATURE_STREAMS, NULL,
|
lib: refactor WpProxy
This is an attempt to unclutter the API of WpProxy and
split functionality into smaller pieces, making it easier
to work with.
In this new class layout, we have the following classes:
- WpObject: base class for everything; handles activating
| and deactivating "features"
|- WpProxy: base class for anything that wraps a pw_proxy;
| handles events from pw_proxy and nothing more
|- WpGlobalProxy: handles integration with the registry
All the other classes derive from WpGlobalProxy. The reason
for separating WpGlobalProxy from WpProxy, though, is that
classes such as WpImplNode / WpSpaDevice can also derive from
WpProxy now, without interfacing with the registry.
All objects that come with an "info" structure and have properties
and/or params also implement the WpPipewireObject interface. This
provides the API to query properties and get/set params. Essentially,
this is implemented by all classes except WpMetadata (pw_metadata
does not have info)
This interface is implemented on each object separately, using
a private "mixin", which is a set of vfunc implementations and helper
functions (and macros) to facilitate the implementation of this interface.
A notable difference to the old WpProxy is that now features can be
deactivated, so it is possible to enable something and later disable
it again.
This commit disables modules, tests, tools, etc, to avoid growing the
patch more, while ensuring that the project compiles.
2020-11-10 19:17:02 +02:00
|
|
|
(GAsyncReadyCallback) on_export_proxy_activated,
|
2020-05-11 09:56:06 +03:00
|
|
|
transition);
|
|
|
|
|
break;
|
|
|
|
|
|
2020-03-29 14:20:22 +03:00
|
|
|
case EXPORT_STEP_LINK:
|
2020-03-31 19:40:49 +03:00
|
|
|
priv->impl_link = wp_impl_endpoint_link_new (core, WP_SI_LINK (self));
|
|
|
|
|
|
lib: refactor WpProxy
This is an attempt to unclutter the API of WpProxy and
split functionality into smaller pieces, making it easier
to work with.
In this new class layout, we have the following classes:
- WpObject: base class for everything; handles activating
| and deactivating "features"
|- WpProxy: base class for anything that wraps a pw_proxy;
| handles events from pw_proxy and nothing more
|- WpGlobalProxy: handles integration with the registry
All the other classes derive from WpGlobalProxy. The reason
for separating WpGlobalProxy from WpProxy, though, is that
classes such as WpImplNode / WpSpaDevice can also derive from
WpProxy now, without interfacing with the registry.
All objects that come with an "info" structure and have properties
and/or params also implement the WpPipewireObject interface. This
provides the API to query properties and get/set params. Essentially,
this is implemented by all classes except WpMetadata (pw_metadata
does not have info)
This interface is implemented on each object separately, using
a private "mixin", which is a set of vfunc implementations and helper
functions (and macros) to facilitate the implementation of this interface.
A notable difference to the old WpProxy is that now features can be
deactivated, so it is possible to enable something and later disable
it again.
This commit disables modules, tests, tools, etc, to avoid growing the
patch more, while ensuring that the project compiles.
2020-11-10 19:17:02 +02:00
|
|
|
wp_object_activate (WP_OBJECT (priv->impl_link),
|
|
|
|
|
WP_OBJECT_FEATURES_ALL, NULL,
|
|
|
|
|
(GAsyncReadyCallback) on_export_proxy_activated,
|
2020-03-31 19:40:49 +03:00
|
|
|
transition);
|
2020-03-29 14:20:22 +03:00
|
|
|
break;
|
|
|
|
|
|
2020-05-07 16:02:23 +03:00
|
|
|
case EXPORT_STEP_CONNECT_DESTROYED:
|
|
|
|
|
g_signal_connect_object (priv->impl_proxy, "pw-proxy-destroyed",
|
|
|
|
|
G_CALLBACK (on_export_proxy_destroyed), self, 0);
|
|
|
|
|
wp_transition_advance (transition);
|
|
|
|
|
break;
|
|
|
|
|
|
2020-04-16 13:18:21 +03:00
|
|
|
default:
|
|
|
|
|
g_return_if_reached ();
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-04-16 17:38:31 +03:00
|
|
|
|
2020-04-16 13:18:21 +03:00
|
|
|
static void
|
2020-04-16 17:38:31 +03:00
|
|
|
wp_session_item_default_export_rollback (WpSessionItem * self)
|
2020-04-16 13:18:21 +03:00
|
|
|
{
|
|
|
|
|
WpSessionItemPrivate *priv = wp_session_item_get_instance_private (self);
|
2020-05-07 16:02:23 +03:00
|
|
|
if (priv->impl_proxy)
|
|
|
|
|
g_signal_handlers_disconnect_by_data (priv->impl_proxy, self);
|
2020-04-16 13:18:21 +03:00
|
|
|
g_clear_pointer (&priv->impl_streams, g_hash_table_unref);
|
|
|
|
|
g_clear_object (&priv->impl_proxy);
|
|
|
|
|
g_weak_ref_set (&priv->session, NULL);
|
2020-03-20 14:45:17 +02:00
|
|
|
}
|
|
|
|
|
|
2020-03-12 18:00:01 +02:00
|
|
|
static void
|
|
|
|
|
wp_session_item_class_init (WpSessionItemClass * klass)
|
|
|
|
|
{
|
|
|
|
|
GObjectClass *object_class = (GObjectClass *) klass;
|
|
|
|
|
|
|
|
|
|
object_class->dispose = wp_session_item_dispose;
|
|
|
|
|
object_class->finalize = wp_session_item_finalize;
|
|
|
|
|
|
2020-04-09 19:24:42 +03:00
|
|
|
klass->reset = wp_session_item_default_reset;
|
2020-03-29 16:03:54 +03:00
|
|
|
klass->get_associated_proxy = wp_session_item_default_get_associated_proxy;
|
2020-04-16 17:38:31 +03:00
|
|
|
klass->activate_get_next_step = wp_session_item_default_activate_get_next_step;
|
|
|
|
|
klass->export_get_next_step = wp_session_item_default_export_get_next_step;
|
|
|
|
|
klass->export_execute_step = wp_session_item_default_export_execute_step;
|
|
|
|
|
klass->export_rollback = wp_session_item_default_export_rollback;
|
2020-03-20 14:42:33 +02:00
|
|
|
|
2020-03-12 18:00:01 +02:00
|
|
|
/**
|
|
|
|
|
* WpSessionItem::flags-changed:
|
|
|
|
|
* @self: the session item
|
|
|
|
|
* @flags: the current flags
|
|
|
|
|
*/
|
|
|
|
|
signals[SIGNAL_FLAGS_CHANGED] = g_signal_new (
|
|
|
|
|
"flags-changed", G_TYPE_FROM_CLASS (klass),
|
|
|
|
|
G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL,
|
|
|
|
|
G_TYPE_NONE, 1, WP_TYPE_SI_FLAGS);
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-09 19:24:42 +03:00
|
|
|
/**
|
|
|
|
|
* wp_session_item_reset: (virtual reset)
|
|
|
|
|
* @self: the session item
|
|
|
|
|
*
|
|
|
|
|
* Resets the state of the item, deactivating it, unexporting it and
|
|
|
|
|
* resetting configuration options as well.
|
|
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
wp_session_item_reset (WpSessionItem * self)
|
|
|
|
|
{
|
|
|
|
|
g_return_if_fail (WP_IS_SESSION_ITEM (self));
|
|
|
|
|
g_return_if_fail (WP_SESSION_ITEM_GET_CLASS (self)->reset);
|
|
|
|
|
|
|
|
|
|
WP_SESSION_ITEM_GET_CLASS (self)->reset (self);
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-28 11:26:51 -04:00
|
|
|
/**
|
|
|
|
|
* wp_session_item_get_parent:
|
|
|
|
|
* @self: the session item
|
|
|
|
|
*
|
|
|
|
|
* Gets the item's parent, which is the #WpSessionBin this item has been added
|
|
|
|
|
* to, or NULL if the item does not belong to a session bin.
|
|
|
|
|
*
|
|
|
|
|
* Returns: (nullable) (transfer full): the item's parent.
|
|
|
|
|
*/
|
|
|
|
|
WpSessionItem *
|
|
|
|
|
wp_session_item_get_parent (WpSessionItem * self)
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (WP_IS_SESSION_ITEM (self), NULL);
|
|
|
|
|
|
|
|
|
|
WpSessionItemPrivate *priv =
|
|
|
|
|
wp_session_item_get_instance_private (self);
|
|
|
|
|
return g_weak_ref_get (&priv->parent);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* wp_session_item_set_parent:
|
|
|
|
|
* @self: the session item
|
2020-11-16 10:34:58 +02:00
|
|
|
* @parent: (transfer none): the parent item
|
2020-04-28 11:26:51 -04:00
|
|
|
*
|
2020-11-16 10:34:58 +02:00
|
|
|
* Private API.
|
|
|
|
|
* Sets the item's parent; used internally by #WpSessionBin.
|
2020-04-28 11:26:51 -04:00
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
wp_session_item_set_parent (WpSessionItem *self, WpSessionItem *parent)
|
|
|
|
|
{
|
|
|
|
|
g_return_if_fail (WP_IS_SESSION_ITEM (self));
|
|
|
|
|
|
|
|
|
|
WpSessionItemPrivate *priv =
|
|
|
|
|
wp_session_item_get_instance_private (self);
|
|
|
|
|
|
|
|
|
|
g_weak_ref_set (&priv->parent, parent);
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-12 18:00:01 +02:00
|
|
|
/**
|
|
|
|
|
* wp_session_item_get_flags:
|
|
|
|
|
* @self: the session item
|
|
|
|
|
*
|
|
|
|
|
* Returns: the item's flags
|
|
|
|
|
*/
|
|
|
|
|
WpSiFlags
|
|
|
|
|
wp_session_item_get_flags (WpSessionItem * self)
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (WP_IS_SESSION_ITEM (self), 0);
|
|
|
|
|
|
|
|
|
|
WpSessionItemPrivate *priv =
|
|
|
|
|
wp_session_item_get_instance_private (self);
|
|
|
|
|
return priv->flags;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* wp_session_item_set_flag:
|
|
|
|
|
* @self: the session item
|
|
|
|
|
* @flag: the flag to set
|
|
|
|
|
*
|
|
|
|
|
* Sets the specified @flag on this item.
|
|
|
|
|
*
|
|
|
|
|
* Note that bits 1-8 cannot be set using this function, they can only
|
|
|
|
|
* be changed internally.
|
|
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
wp_session_item_set_flag (WpSessionItem * self, WpSiFlags flag)
|
|
|
|
|
{
|
|
|
|
|
g_return_if_fail (WP_IS_SESSION_ITEM (self));
|
|
|
|
|
|
|
|
|
|
WpSessionItemPrivate *priv =
|
|
|
|
|
wp_session_item_get_instance_private (self);
|
|
|
|
|
|
|
|
|
|
/* mask to make sure we are not changing an immutable flag */
|
|
|
|
|
flag &= ~((1<<8) - 1);
|
|
|
|
|
if (flag != 0) {
|
|
|
|
|
priv->flags |= flag;
|
|
|
|
|
g_signal_emit (self, signals[SIGNAL_FLAGS_CHANGED], 0, priv->flags);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* wp_session_item_clear_flag:
|
|
|
|
|
* @self: the session item
|
|
|
|
|
* @flag: the flag to clear
|
|
|
|
|
*
|
|
|
|
|
* Clears the specified @flag from this item.
|
|
|
|
|
*
|
|
|
|
|
* Note that bits 1-8 cannot be cleared using this function, they can only
|
|
|
|
|
* be changed internally.
|
|
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
wp_session_item_clear_flag (WpSessionItem * self, WpSiFlags flag)
|
|
|
|
|
{
|
|
|
|
|
g_return_if_fail (WP_IS_SESSION_ITEM (self));
|
|
|
|
|
|
|
|
|
|
WpSessionItemPrivate *priv =
|
|
|
|
|
wp_session_item_get_instance_private (self);
|
|
|
|
|
|
|
|
|
|
/* mask to make sure we are not changing an immutable flag */
|
|
|
|
|
flag &= ~((1<<8) - 1);
|
|
|
|
|
if (flag != 0) {
|
|
|
|
|
priv->flags &= ~flag;
|
|
|
|
|
g_signal_emit (self, signals[SIGNAL_FLAGS_CHANGED], 0, priv->flags);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-29 16:03:54 +03:00
|
|
|
/**
|
|
|
|
|
* wp_session_item_get_associated_proxy: (virtual get_associated_proxy)
|
|
|
|
|
* @self: the session item
|
|
|
|
|
* @proxy_type: a #WpProxy subclass #GType
|
|
|
|
|
*
|
|
|
|
|
* An associated proxy is a #WpProxy subclass instance that is somehow related
|
|
|
|
|
* to this item. For example:
|
|
|
|
|
* - An exported #WpSiEndpoint should have at least:
|
|
|
|
|
* - an associated #WpEndpoint
|
|
|
|
|
* - an associated #WpSession
|
|
|
|
|
* - An exported #WpSiStream should have at least:
|
|
|
|
|
* - an associated #WpEndpointStream
|
|
|
|
|
* - an associated #WpEndpoint
|
|
|
|
|
* - In cases where the item wraps a single PipeWire node, it should also
|
|
|
|
|
* have an associated #WpNode
|
|
|
|
|
*
|
|
|
|
|
* Returns: (nullable) (transfer full) (type WpProxy): the associated proxy
|
|
|
|
|
* of the specified @proxy_type, or %NULL if there is no association to
|
|
|
|
|
* such a proxy
|
|
|
|
|
*/
|
|
|
|
|
gpointer
|
|
|
|
|
wp_session_item_get_associated_proxy (WpSessionItem * self, GType proxy_type)
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (WP_IS_SESSION_ITEM (self), NULL);
|
|
|
|
|
g_return_val_if_fail (WP_SESSION_ITEM_GET_CLASS (self)->get_associated_proxy,
|
|
|
|
|
NULL);
|
|
|
|
|
g_return_val_if_fail (g_type_is_a (proxy_type, WP_TYPE_PROXY), NULL);
|
|
|
|
|
|
|
|
|
|
return WP_SESSION_ITEM_GET_CLASS (self)->get_associated_proxy (self, proxy_type);
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-31 19:26:05 +03:00
|
|
|
/**
|
|
|
|
|
* wp_session_item_get_associated_proxy_id:
|
|
|
|
|
* @self: the session item
|
|
|
|
|
* @proxy_type: a #WpProxy subclass #GType
|
|
|
|
|
*
|
|
|
|
|
* Returns: the bound id of the associated proxy of the specified @proxy_type,
|
|
|
|
|
* or `SPA_ID_INVALID` if there is no association to such a proxy
|
|
|
|
|
*/
|
|
|
|
|
guint32
|
|
|
|
|
wp_session_item_get_associated_proxy_id (WpSessionItem * self, GType proxy_type)
|
|
|
|
|
{
|
|
|
|
|
g_autoptr (WpProxy) proxy = wp_session_item_get_associated_proxy (self,
|
|
|
|
|
proxy_type);
|
|
|
|
|
if (!proxy)
|
|
|
|
|
return SPA_ID_INVALID;
|
|
|
|
|
|
|
|
|
|
return wp_proxy_get_bound_id (proxy);
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-12 18:00:01 +02:00
|
|
|
/**
|
|
|
|
|
* wp_session_item_configure: (virtual configure)
|
|
|
|
|
* @self: the session item
|
2020-04-11 11:05:26 +03:00
|
|
|
* @args: (transfer floating): the configuration options to set
|
2020-03-12 18:00:01 +02:00
|
|
|
* (`a{sv}` dictionary, mapping option names to values)
|
|
|
|
|
*
|
|
|
|
|
* Returns: %TRUE on success, %FALSE if the options could not be set
|
|
|
|
|
*/
|
|
|
|
|
gboolean
|
|
|
|
|
wp_session_item_configure (WpSessionItem * self, GVariant * args)
|
|
|
|
|
{
|
2020-04-11 11:05:26 +03:00
|
|
|
g_autoptr (GVariant) args_ref = g_variant_ref_sink (args);
|
|
|
|
|
|
2020-03-12 18:00:01 +02:00
|
|
|
g_return_val_if_fail (WP_IS_SESSION_ITEM (self), FALSE);
|
|
|
|
|
g_return_val_if_fail (WP_SESSION_ITEM_GET_CLASS (self)->configure,
|
|
|
|
|
FALSE);
|
2020-04-16 11:55:23 +03:00
|
|
|
g_return_val_if_fail (g_variant_is_of_type (args, G_VARIANT_TYPE_VARDICT),
|
2020-03-12 18:00:01 +02:00
|
|
|
FALSE);
|
|
|
|
|
|
|
|
|
|
return WP_SESSION_ITEM_GET_CLASS (self)->configure (self, args);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* wp_session_item_get_configuration: (virtual get_configuration)
|
|
|
|
|
* @self: the session item
|
|
|
|
|
*
|
2020-03-17 23:03:10 +02:00
|
|
|
* Returns: (transfer floating): the active configuration, as a `a{sv}` dictionary
|
2020-03-12 18:00:01 +02:00
|
|
|
*/
|
|
|
|
|
GVariant *
|
|
|
|
|
wp_session_item_get_configuration (WpSessionItem * self)
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (WP_IS_SESSION_ITEM (self), NULL);
|
|
|
|
|
g_return_val_if_fail (WP_SESSION_ITEM_GET_CLASS (self)->get_configuration,
|
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
|
|
return WP_SESSION_ITEM_GET_CLASS (self)->get_configuration (self);
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-08 19:56:08 +03:00
|
|
|
/* clear the in progress flag before calling the callback, so that
|
|
|
|
|
it's possible to call wp_session_item_export from within the callback */
|
2020-03-12 18:00:01 +02:00
|
|
|
static void
|
2020-05-08 19:56:08 +03:00
|
|
|
on_activate_transition_pre_completed (gpointer data, GClosure *closure)
|
2020-03-12 18:00:01 +02:00
|
|
|
{
|
2020-05-08 19:56:08 +03:00
|
|
|
WpTransition *transition = WP_TRANSITION (data);
|
|
|
|
|
WpSessionItem *self = wp_transition_get_source_object (transition);
|
|
|
|
|
WpSessionItemPrivate *priv =
|
|
|
|
|
wp_session_item_get_instance_private (self);
|
|
|
|
|
|
|
|
|
|
priv->flags &= ~WP_SI_FLAG_ACTIVATING;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
on_activate_transition_post_completed (gpointer data, GClosure *closure)
|
|
|
|
|
{
|
|
|
|
|
WpTransition *transition = WP_TRANSITION (data);
|
|
|
|
|
WpSessionItem *self = wp_transition_get_source_object (transition);
|
2020-03-12 18:00:01 +02:00
|
|
|
WpSessionItemPrivate *priv =
|
|
|
|
|
wp_session_item_get_instance_private (self);
|
|
|
|
|
|
2020-04-16 17:38:31 +03:00
|
|
|
priv->flags |= wp_transition_had_error (transition) ?
|
|
|
|
|
WP_SI_FLAG_ACTIVATE_ERROR : WP_SI_FLAG_ACTIVE;
|
2020-03-12 18:00:01 +02:00
|
|
|
g_signal_emit (self, signals[SIGNAL_FLAGS_CHANGED], 0, priv->flags);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2021-01-20 09:55:07 -05:00
|
|
|
* wp_session_item_activate_closure:
|
2020-03-12 18:00:01 +02:00
|
|
|
* @self: the session item
|
2021-01-20 09:55:07 -05:00
|
|
|
* @closure: (transfer full): the closure to use when activation is completed
|
2020-03-12 18:00:01 +02:00
|
|
|
*
|
2020-04-16 17:38:31 +03:00
|
|
|
* Activates the item asynchronously.
|
2021-01-20 09:55:07 -05:00
|
|
|
* You can use wp_session_item_activate_finish() in the closure callback to get
|
2020-03-20 14:44:32 +02:00
|
|
|
* the result of this operation.
|
2020-03-12 18:00:01 +02:00
|
|
|
*
|
2020-04-16 17:38:31 +03:00
|
|
|
* This internally starts a #WpTransition that calls into
|
|
|
|
|
* #WpSessionItemClass.activate_get_next_step() and
|
|
|
|
|
* #WpSessionItemClass.activate_execute_step() to advance.
|
|
|
|
|
* If the transition fails, #WpSessionItemClass.activate_rollback() is called
|
|
|
|
|
* to reverse previous actions.
|
|
|
|
|
*
|
|
|
|
|
* The default implementation of the above virtual functions activates the
|
|
|
|
|
* item successfully without doing anything. In order to implement a meaningful
|
|
|
|
|
* session item, you should override all 3 of them.
|
|
|
|
|
*
|
|
|
|
|
* When this method is called, the %WP_SI_FLAG_ACTIVATING flag is set. When
|
|
|
|
|
* the operation finishes successfully, that flag is cleared and replaced with
|
|
|
|
|
* either %WP_SI_FLAG_ACTIVE or %WP_SI_FLAG_ACTIVATE_ERROR, depending on the
|
|
|
|
|
* success outcome of the operation. In order to clear
|
|
|
|
|
* %WP_SI_FLAG_ACTIVATE_ERROR, you can either call wp_session_item_deactivate()
|
|
|
|
|
* or wp_session_item_activate() to try activating again.
|
|
|
|
|
*
|
|
|
|
|
* This method cannot be called if another operation (activation or export) is
|
|
|
|
|
* in progress (%WP_SI_FLAGS_MASK_OPERATION_IN_PROGRESS) or if the item is
|
|
|
|
|
* already activated.
|
2020-03-12 18:00:01 +02:00
|
|
|
*/
|
|
|
|
|
void
|
2021-01-20 09:55:07 -05:00
|
|
|
wp_session_item_activate_closure (WpSessionItem * self, GClosure *closure)
|
2020-03-12 18:00:01 +02:00
|
|
|
{
|
|
|
|
|
g_return_if_fail (WP_IS_SESSION_ITEM (self));
|
|
|
|
|
|
|
|
|
|
WpSessionItemPrivate *priv =
|
|
|
|
|
wp_session_item_get_instance_private (self);
|
|
|
|
|
|
2020-04-16 17:38:31 +03:00
|
|
|
g_return_if_fail (!(priv->flags &
|
|
|
|
|
(WP_SI_FLAGS_MASK_OPERATION_IN_PROGRESS | WP_SI_FLAG_ACTIVE)));
|
2020-03-12 18:00:01 +02:00
|
|
|
|
2020-04-16 17:38:31 +03:00
|
|
|
/* TODO: add a way to cancel the transition if deactivate() is called in the meantime */
|
2020-05-08 19:56:08 +03:00
|
|
|
WpTransition *transition = wp_transition_new_closure (
|
|
|
|
|
wp_si_transition_get_type (), self, NULL, closure);
|
2020-03-12 18:00:01 +02:00
|
|
|
wp_transition_set_source_tag (transition, wp_session_item_activate);
|
2020-05-08 19:56:08 +03:00
|
|
|
|
|
|
|
|
g_closure_add_marshal_guards (closure,
|
|
|
|
|
transition, on_activate_transition_pre_completed,
|
|
|
|
|
transition, on_activate_transition_post_completed);
|
2020-03-12 18:00:01 +02:00
|
|
|
|
2020-05-05 16:31:53 +03:00
|
|
|
wp_debug_object (self, "activating item");
|
|
|
|
|
|
2020-04-16 17:38:31 +03:00
|
|
|
priv->flags &= ~WP_SI_FLAG_ACTIVATE_ERROR;
|
2020-03-12 18:00:01 +02:00
|
|
|
priv->flags |= WP_SI_FLAG_ACTIVATING;
|
|
|
|
|
g_signal_emit (self, signals[SIGNAL_FLAGS_CHANGED], 0, priv->flags);
|
|
|
|
|
|
2020-03-29 11:17:16 +03:00
|
|
|
WP_SI_TRANSITION (transition)->get_next_step =
|
2020-04-16 17:38:31 +03:00
|
|
|
WP_SESSION_ITEM_GET_CLASS (self)->activate_get_next_step;
|
2020-03-29 11:17:16 +03:00
|
|
|
WP_SI_TRANSITION (transition)->execute_step =
|
2020-04-16 17:38:31 +03:00
|
|
|
WP_SESSION_ITEM_GET_CLASS (self)->activate_execute_step;
|
2020-04-16 13:18:21 +03:00
|
|
|
WP_SI_TRANSITION (transition)->rollback =
|
2020-04-16 17:38:31 +03:00
|
|
|
WP_SESSION_ITEM_GET_CLASS (self)->activate_rollback;
|
2020-03-12 18:00:01 +02:00
|
|
|
wp_transition_advance (transition);
|
|
|
|
|
}
|
|
|
|
|
|
2021-01-20 09:55:07 -05:00
|
|
|
/**
|
|
|
|
|
* wp_session_item_activate:
|
|
|
|
|
* @self: the session item
|
|
|
|
|
* @callback: (scope async): a callback to call when activation is finished
|
|
|
|
|
* @callback_data: (closure): data passed to @callback
|
|
|
|
|
*
|
|
|
|
|
* @callback and @callback_data version of wp_session_item_activate_closure()
|
|
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
wp_session_item_activate (WpSessionItem * self,
|
|
|
|
|
GAsyncReadyCallback callback,
|
|
|
|
|
gpointer callback_data)
|
|
|
|
|
{
|
|
|
|
|
g_return_if_fail (WP_IS_SESSION_ITEM (self));
|
|
|
|
|
|
|
|
|
|
WpSessionItemPrivate *priv =
|
|
|
|
|
wp_session_item_get_instance_private (self);
|
|
|
|
|
|
|
|
|
|
g_return_if_fail (!(priv->flags &
|
|
|
|
|
(WP_SI_FLAGS_MASK_OPERATION_IN_PROGRESS | WP_SI_FLAG_ACTIVE)));
|
|
|
|
|
|
|
|
|
|
GClosure *closure =
|
|
|
|
|
g_cclosure_new (G_CALLBACK (callback), callback_data, NULL);
|
|
|
|
|
|
|
|
|
|
wp_session_item_activate_closure (self, closure);
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-20 14:44:32 +02:00
|
|
|
/**
|
|
|
|
|
* wp_session_item_activate_finish:
|
|
|
|
|
* @self: the session item
|
|
|
|
|
* @res: the async operation result
|
|
|
|
|
* @error: (out) (optional): the error of the operation, if any
|
|
|
|
|
*
|
|
|
|
|
* Returns: %TRUE if the item is now activateed, %FALSE if there was an error
|
|
|
|
|
*/
|
|
|
|
|
gboolean
|
|
|
|
|
wp_session_item_activate_finish (WpSessionItem * self, GAsyncResult * res,
|
|
|
|
|
GError ** error)
|
|
|
|
|
{
|
2020-04-16 17:38:31 +03:00
|
|
|
g_return_val_if_fail (WP_IS_SESSION_ITEM (self), FALSE);
|
2020-03-20 14:44:32 +02:00
|
|
|
g_return_val_if_fail (
|
|
|
|
|
g_async_result_is_tagged (res, wp_session_item_activate), FALSE);
|
|
|
|
|
return wp_transition_finish (res, error);
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-12 18:00:01 +02:00
|
|
|
/**
|
2020-04-16 13:18:21 +03:00
|
|
|
* wp_session_item_deactivate:
|
2020-03-12 18:00:01 +02:00
|
|
|
* @self: the session item
|
|
|
|
|
*
|
2020-04-09 19:24:42 +03:00
|
|
|
* De-activates the item and/or cancels any ongoing activation operation.
|
|
|
|
|
*
|
|
|
|
|
* If the item was not activated, this method does nothing.
|
2020-03-12 18:00:01 +02:00
|
|
|
*/
|
|
|
|
|
void
|
2020-04-09 19:24:42 +03:00
|
|
|
wp_session_item_deactivate (WpSessionItem * self)
|
2020-03-12 18:00:01 +02:00
|
|
|
{
|
|
|
|
|
g_return_if_fail (WP_IS_SESSION_ITEM (self));
|
2020-04-16 13:18:21 +03:00
|
|
|
|
|
|
|
|
WpSessionItemPrivate *priv = wp_session_item_get_instance_private (self);
|
2020-04-16 17:38:31 +03:00
|
|
|
static const guint flags = 0xf; /* all activation flags */
|
2020-03-12 18:00:01 +02:00
|
|
|
|
2020-04-09 19:24:42 +03:00
|
|
|
//TODO cancel job if ACTIVATING
|
|
|
|
|
|
2020-04-16 13:18:21 +03:00
|
|
|
if (priv->flags & WP_SI_FLAG_ACTIVE &&
|
2020-04-16 17:38:31 +03:00
|
|
|
WP_SESSION_ITEM_GET_CLASS (self)->activate_rollback)
|
|
|
|
|
WP_SESSION_ITEM_GET_CLASS (self)->activate_rollback (self);
|
2020-04-16 13:18:21 +03:00
|
|
|
|
|
|
|
|
if (priv->flags & flags) {
|
|
|
|
|
priv->flags &= ~flags;
|
|
|
|
|
g_signal_emit (self, signals[SIGNAL_FLAGS_CHANGED], 0, priv->flags);
|
|
|
|
|
}
|
2020-03-12 18:00:01 +02:00
|
|
|
}
|
2020-03-20 14:45:17 +02:00
|
|
|
|
2020-04-16 17:38:31 +03:00
|
|
|
static void
|
2020-05-08 19:56:08 +03:00
|
|
|
on_export_transition_pre_completed (gpointer data, GClosure *closure)
|
2020-04-16 17:38:31 +03:00
|
|
|
{
|
2020-05-08 19:56:08 +03:00
|
|
|
WpTransition *transition = WP_TRANSITION (data);
|
|
|
|
|
WpSessionItem *self = wp_transition_get_source_object (transition);
|
|
|
|
|
WpSessionItemPrivate *priv =
|
|
|
|
|
wp_session_item_get_instance_private (self);
|
|
|
|
|
|
|
|
|
|
priv->flags &= ~WP_SI_FLAG_EXPORTING;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
on_export_transition_post_completed (gpointer data, GClosure *closure)
|
|
|
|
|
{
|
|
|
|
|
WpTransition *transition = WP_TRANSITION (data);
|
|
|
|
|
WpSessionItem *self = wp_transition_get_source_object (transition);
|
2020-04-16 17:38:31 +03:00
|
|
|
WpSessionItemPrivate *priv =
|
|
|
|
|
wp_session_item_get_instance_private (self);
|
|
|
|
|
|
|
|
|
|
priv->flags |= wp_transition_had_error (transition) ?
|
|
|
|
|
WP_SI_FLAG_EXPORT_ERROR : WP_SI_FLAG_EXPORTED;
|
|
|
|
|
g_signal_emit (self, signals[SIGNAL_FLAGS_CHANGED], 0, priv->flags);
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-20 14:45:17 +02:00
|
|
|
/**
|
2021-01-20 10:26:46 -05:00
|
|
|
* wp_session_item_export_closure:
|
2020-03-20 14:45:17 +02:00
|
|
|
* @self: the session item
|
|
|
|
|
* @session: the session on which to export this item
|
2021-01-20 10:26:46 -05:00
|
|
|
* @closure: (transfer full): the closure to use when export is completed
|
2020-03-20 14:45:17 +02:00
|
|
|
*
|
|
|
|
|
* Exports this item asynchronously on PipeWire, making it part of the
|
2020-04-16 17:38:31 +03:00
|
|
|
* specified @session. You can use wp_session_item_export_finish() in the
|
|
|
|
|
* @callback to get the result of this operation.
|
|
|
|
|
*
|
|
|
|
|
* This internally starts a #WpTransition that calls into
|
|
|
|
|
* #WpSessionItemClass.export_get_next_step() and
|
|
|
|
|
* #WpSessionItemClass.export_execute_step() to advance.
|
|
|
|
|
* If the transition fails, #WpSessionItemClass.export_rollback() is called
|
|
|
|
|
* to reverse previous actions.
|
|
|
|
|
*
|
|
|
|
|
* Exporting is internally implemented for endpoints (items that implement
|
|
|
|
|
* #WpSiEndpoint) and endpoint links (items that implement #WpSiLink). On other
|
|
|
|
|
* items the default implementation will immediately call the @callback,
|
|
|
|
|
* reporting error. You can extend this to export custom interfaces by
|
|
|
|
|
* overriding the virtual functions mentioned above.
|
|
|
|
|
*
|
|
|
|
|
* When this method is called, the %WP_SI_FLAG_EXPORTING flag is set. When
|
|
|
|
|
* the operation finishes successfully, that flag is cleared and replaced with
|
|
|
|
|
* either %WP_SI_FLAG_EXPORTED or %WP_SI_FLAG_EXPORT_ERROR, depending on the
|
|
|
|
|
* success outcome of the operation. In order to clear
|
|
|
|
|
* %WP_SI_FLAG_EXPORT_ERROR, you can either call wp_session_item_unexport()
|
|
|
|
|
* or wp_session_item_export() to try exporting again.
|
2020-03-20 14:45:17 +02:00
|
|
|
*
|
2020-04-16 17:38:31 +03:00
|
|
|
* This method cannot be called if another operation (activation or export) is
|
|
|
|
|
* in progress (%WP_SI_FLAGS_MASK_OPERATION_IN_PROGRESS) or if the item is
|
|
|
|
|
* already exported.
|
2020-03-20 14:45:17 +02:00
|
|
|
*/
|
|
|
|
|
void
|
2021-01-20 10:26:46 -05:00
|
|
|
wp_session_item_export_closure (WpSessionItem * self, WpSession * session,
|
|
|
|
|
GClosure *closure)
|
2020-03-20 14:45:17 +02:00
|
|
|
{
|
|
|
|
|
g_return_if_fail (WP_IS_SESSION_ITEM (self));
|
|
|
|
|
g_return_if_fail (WP_IS_SESSION (session));
|
|
|
|
|
|
2020-04-09 19:24:42 +03:00
|
|
|
WpSessionItemPrivate *priv =
|
|
|
|
|
wp_session_item_get_instance_private (self);
|
|
|
|
|
|
2020-04-16 17:38:31 +03:00
|
|
|
g_return_if_fail (!(priv->flags &
|
|
|
|
|
(WP_SI_FLAGS_MASK_OPERATION_IN_PROGRESS | WP_SI_FLAG_EXPORTED)));
|
2020-04-09 19:24:42 +03:00
|
|
|
|
2020-04-16 17:38:31 +03:00
|
|
|
g_weak_ref_set (&priv->session, session);
|
|
|
|
|
|
|
|
|
|
/* TODO: add a way to cancel the transition if unexport() is called in the meantime */
|
2020-05-08 19:56:08 +03:00
|
|
|
WpTransition *transition = wp_transition_new_closure (
|
|
|
|
|
wp_si_transition_get_type (), self, NULL, closure);
|
2020-04-16 17:38:31 +03:00
|
|
|
wp_transition_set_source_tag (transition, wp_session_item_export);
|
2020-05-08 19:56:08 +03:00
|
|
|
|
|
|
|
|
g_closure_add_marshal_guards (closure,
|
|
|
|
|
transition, on_export_transition_pre_completed,
|
|
|
|
|
transition, on_export_transition_post_completed);
|
2020-04-16 17:38:31 +03:00
|
|
|
|
2020-05-05 16:31:53 +03:00
|
|
|
wp_debug_object (self, "exporting item on session " WP_OBJECT_FORMAT,
|
|
|
|
|
WP_OBJECT_ARGS (session));
|
|
|
|
|
|
2020-04-16 17:38:31 +03:00
|
|
|
priv->flags &= ~WP_SI_FLAG_EXPORT_ERROR;
|
|
|
|
|
priv->flags |= WP_SI_FLAG_EXPORTING;
|
|
|
|
|
g_signal_emit (self, signals[SIGNAL_FLAGS_CHANGED], 0, priv->flags);
|
|
|
|
|
|
|
|
|
|
WP_SI_TRANSITION (transition)->get_next_step =
|
|
|
|
|
WP_SESSION_ITEM_GET_CLASS (self)->export_get_next_step;
|
|
|
|
|
WP_SI_TRANSITION (transition)->execute_step =
|
|
|
|
|
WP_SESSION_ITEM_GET_CLASS (self)->export_execute_step;
|
|
|
|
|
WP_SI_TRANSITION (transition)->rollback =
|
|
|
|
|
WP_SESSION_ITEM_GET_CLASS (self)->export_rollback;
|
|
|
|
|
wp_transition_advance (transition);
|
2020-03-20 14:45:17 +02:00
|
|
|
}
|
|
|
|
|
|
2021-01-20 10:26:46 -05:00
|
|
|
/**
|
|
|
|
|
* wp_session_item_export:
|
|
|
|
|
* @self: the session item
|
|
|
|
|
* @session: the session on which to export this item
|
|
|
|
|
* @callback: (scope async): a callback to call when exporting is finished
|
|
|
|
|
* @callback_data: (closure): data passed to @callback
|
|
|
|
|
*
|
|
|
|
|
* @callback and @callback_data version of wp_session_item_export_closure()
|
|
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
wp_session_item_export (WpSessionItem * self, WpSession * session,
|
|
|
|
|
GAsyncReadyCallback callback, gpointer callback_data)
|
|
|
|
|
{
|
|
|
|
|
g_return_if_fail (WP_IS_SESSION_ITEM (self));
|
|
|
|
|
g_return_if_fail (WP_IS_SESSION (session));
|
|
|
|
|
|
|
|
|
|
WpSessionItemPrivate *priv =
|
|
|
|
|
wp_session_item_get_instance_private (self);
|
|
|
|
|
|
|
|
|
|
g_return_if_fail (!(priv->flags &
|
|
|
|
|
(WP_SI_FLAGS_MASK_OPERATION_IN_PROGRESS | WP_SI_FLAG_EXPORTED)));
|
|
|
|
|
|
|
|
|
|
GClosure *closure =
|
|
|
|
|
g_cclosure_new (G_CALLBACK (callback), callback_data, NULL);
|
|
|
|
|
|
|
|
|
|
wp_session_item_export_closure (self, session, closure);
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-20 14:45:17 +02:00
|
|
|
/**
|
2020-04-16 17:38:31 +03:00
|
|
|
* wp_session_item_export_finish:
|
2020-03-20 14:45:17 +02:00
|
|
|
* @self: the session item
|
|
|
|
|
* @res: the async operation result
|
|
|
|
|
* @error: (out) (optional): the error of the operation, if any
|
|
|
|
|
*
|
|
|
|
|
* Returns: %TRUE if the item is now exported, %FALSE if there was an error
|
|
|
|
|
*/
|
|
|
|
|
gboolean
|
|
|
|
|
wp_session_item_export_finish (WpSessionItem * self, GAsyncResult * res,
|
|
|
|
|
GError ** error)
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (WP_IS_SESSION_ITEM (self), FALSE);
|
2020-04-16 17:38:31 +03:00
|
|
|
g_return_val_if_fail (
|
|
|
|
|
g_async_result_is_tagged (res, wp_session_item_export), FALSE);
|
|
|
|
|
return wp_transition_finish (res, error);
|
2020-03-20 14:45:17 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2020-04-16 17:38:31 +03:00
|
|
|
* wp_session_item_unexport:
|
2020-03-20 14:45:17 +02:00
|
|
|
* @self: the session item
|
|
|
|
|
*
|
|
|
|
|
* Reverses the effects of a previous call to wp_session_item_export().
|
|
|
|
|
* This means that after this method is called:
|
|
|
|
|
* - The item is no longer exported on PipeWire
|
|
|
|
|
* - The item is no longer associated with a session
|
|
|
|
|
* - If an export operation was in progress, it is cancelled.
|
|
|
|
|
*
|
|
|
|
|
* If the item was not exported, this method does nothing.
|
|
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
wp_session_item_unexport (WpSessionItem * self)
|
|
|
|
|
{
|
|
|
|
|
g_return_if_fail (WP_IS_SESSION_ITEM (self));
|
2020-04-16 17:38:31 +03:00
|
|
|
|
|
|
|
|
WpSessionItemPrivate *priv = wp_session_item_get_instance_private (self);
|
|
|
|
|
static const guint flags = 0xf0; /* all export flags */
|
2020-03-20 14:45:17 +02:00
|
|
|
|
2020-04-09 19:24:42 +03:00
|
|
|
//TODO cancel job if EXPORTING
|
|
|
|
|
|
2020-04-16 17:38:31 +03:00
|
|
|
if (priv->flags & WP_SI_FLAG_EXPORTED &&
|
|
|
|
|
WP_SESSION_ITEM_GET_CLASS (self)->export_rollback)
|
|
|
|
|
WP_SESSION_ITEM_GET_CLASS (self)->export_rollback (self);
|
|
|
|
|
|
|
|
|
|
if (priv->flags & flags) {
|
|
|
|
|
priv->flags &= ~flags;
|
|
|
|
|
g_signal_emit (self, signals[SIGNAL_FLAGS_CHANGED], 0, priv->flags);
|
|
|
|
|
}
|
2020-03-20 14:45:17 +02:00
|
|
|
}
|