diff --git a/src/modules/module-session-manager/client-session/client-session.c b/src/modules/module-session-manager/client-session/client-session.c index bb0f011ea..1508da859 100644 --- a/src/modules/module-session-manager/client-session/client-session.c +++ b/src/modules/module-session-manager/client-session/client-session.c @@ -64,6 +64,7 @@ static int client_session_link_update(void *object, PW_KEY_FACTORY_ID, PW_KEY_CLIENT_ID, PW_KEY_SESSION_ID, + PW_KEY_SESSION_SERVICES, PW_KEY_ENDPOINT_LINK_OUTPUT_ENDPOINT, PW_KEY_ENDPOINT_LINK_OUTPUT_STREAM, PW_KEY_ENDPOINT_LINK_INPUT_ENDPOINT, diff --git a/src/modules/module-session-manager/client-session/session.c b/src/modules/module-session-manager/client-session/session.c index 38a505746..7afad96c9 100644 --- a/src/modules/module-session-manager/client-session/session.c +++ b/src/modules/module-session-manager/client-session/session.c @@ -285,7 +285,7 @@ int session_init(struct session *this, NULL, session_bind, this); if (!this->global) goto no_mem; - + pw_properties_setf(this->props, PW_KEY_OBJECT_ID, "%u", pw_global_get_id(this->global)); pw_properties_setf(this->props, PW_KEY_OBJECT_SERIAL, "%"PRIu64, diff --git a/src/pipewire/extensions/session-manager/interfaces.h b/src/pipewire/extensions/session-manager/interfaces.h index a05870784..21c02fb1b 100644 --- a/src/pipewire/extensions/session-manager/interfaces.h +++ b/src/pipewire/extensions/session-manager/interfaces.h @@ -20,6 +20,12 @@ extern "C" { * \{ */ +#define PW_SESSION_SERVICE_NONE "" +#define PW_SESSION_SERVICE_AUDIO_IN "audio-in" +#define PW_SESSION_SERVICE_AUDIO_OUT "audio-out" +#define PW_SESSION_SERVICE_VIDEO_IN "video-in" +#define PW_SESSION_SERVICE_VIDEO_OUT "video-out" + #define PW_TYPE_INTERFACE_Session PW_TYPE_INFO_INTERFACE_BASE "Session" #define PW_VERSION_SESSION 0 struct pw_session; diff --git a/src/pipewire/extensions/session-manager/keys.h b/src/pipewire/extensions/session-manager/keys.h index 5a2fa68bf..320e6868f 100644 --- a/src/pipewire/extensions/session-manager/keys.h +++ b/src/pipewire/extensions/session-manager/keys.h @@ -16,6 +16,7 @@ extern "C" { */ #define PW_KEY_SESSION_ID "session.id" /**< id of a session manager */ +#define PW_KEY_SESSION_SERVICES "session.services" /**< a list of available services on this session */ #define PW_KEY_ENDPOINT_ID "endpoint.id" /**< id of an endpoint */ #define PW_KEY_ENDPOINT_NAME "endpoint.name" /**< the name of an endpoint */ diff --git a/src/pipewire/private.h b/src/pipewire/private.h index 3d95922eb..a60604021 100644 --- a/src/pipewire/private.h +++ b/src/pipewire/private.h @@ -1053,6 +1053,12 @@ struct pw_stream { struct pw_proxy *proxy; struct spa_hook proxy_listener; + struct pw_registry *registry; + struct spa_hook registry_listener; + + struct pw_session *session; + struct spa_hook session_listener; + struct spa_hook node_listener; struct spa_list controls; diff --git a/src/pipewire/stream.c b/src/pipewire/stream.c index 22ccbfb0a..5f7f207e3 100644 --- a/src/pipewire/stream.c +++ b/src/pipewire/stream.c @@ -23,6 +23,7 @@ #include "pipewire/pipewire.h" #include "pipewire/stream.h" #include "pipewire/private.h" +#include "pipewire/extensions/session-manager.h" PW_LOG_TOPIC_EXTERN(log_stream); #define PW_LOG_TOPIC_DEFAULT log_stream @@ -1111,6 +1112,47 @@ static const struct spa_node_methods impl_node = { .port_reuse_buffer = impl_port_reuse_buffer, }; +static void session_event_info (void *data, const struct pw_session_info *info) +{ + struct pw_stream *stream = data; + const char *services = spa_dict_lookup(info->props, PW_KEY_SESSION_SERVICES); + if (services == NULL || spa_streq(services, PW_SESSION_SERVICE_NONE)) { + return; + } + // some services are available, so the stream can now be considered + // connected, although more services may become available after this + if (stream->state == PW_STREAM_STATE_CONNECTING) { + stream_set_state(stream, PW_STREAM_STATE_PAUSED, NULL); + } +} + +static const struct pw_session_events session_events = { + PW_VERSION_SESSION_EVENTS, + .info = &session_event_info, +}; + +static void registry_event_global(void *data, uint32_t id, + uint32_t permissions, const char *type, + uint32_t version, const struct spa_dict *props) +{ + struct pw_stream *stream = data; + if (stream->session != NULL) + return; + + if (spa_streq(type, PW_TYPE_INTERFACE_Session)) { + stream->session = pw_registry_bind(stream->registry, + id, type, PW_VERSION_SESSION, 0); + pw_session_add_listener(stream->session, + &stream->session_listener, + &session_events, data); + } +} + +static const struct pw_registry_events registry_events = { + PW_VERSION_REGISTRY_EVENTS, + .global = registry_event_global, +}; + static void proxy_removed(void *_data) { struct pw_stream *stream = _data; @@ -1141,7 +1183,11 @@ static void proxy_bound(void *data, uint32_t global_id) { struct pw_stream *stream = data; stream->node_id = global_id; - stream_set_state(stream, PW_STREAM_STATE_PAUSED, NULL); + stream->registry = pw_core_get_registry(stream->core, + PW_VERSION_REGISTRY, + 0 /* user_data size */ ); + pw_registry_add_listener(stream->registry, &stream->registry_listener, + ®istry_events, data); } static const struct pw_proxy_events proxy_events = { @@ -1493,6 +1539,9 @@ stream_new(struct pw_context *context, const char *name, this->name = name ? strdup(name) : NULL; this->node_id = SPA_ID_INVALID; + + this->registry = NULL; + this->session = NULL; spa_ringbuffer_init(&impl->dequeued.ring); spa_ringbuffer_init(&impl->queued.ring);