mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-04 13:30:12 -05:00
pulse-server: fill linked sink/source in create_stream reply
This commit is contained in:
parent
1df7db5301
commit
fd16eb450a
1 changed files with 157 additions and 97 deletions
|
|
@ -542,6 +542,134 @@ static const struct pw_manager_events manager_events = {
|
|||
.metadata = manager_metadata,
|
||||
};
|
||||
|
||||
static bool is_client(struct pw_manager_object *o)
|
||||
{
|
||||
return strcmp(o->type, PW_TYPE_INTERFACE_Client) == 0;
|
||||
}
|
||||
|
||||
static bool is_module(struct pw_manager_object *o)
|
||||
{
|
||||
return strcmp(o->type, PW_TYPE_INTERFACE_Module) == 0;
|
||||
}
|
||||
|
||||
static bool is_card(struct pw_manager_object *o)
|
||||
{
|
||||
const char *str;
|
||||
return
|
||||
strcmp(o->type, PW_TYPE_INTERFACE_Device) == 0 &&
|
||||
o->props != NULL &&
|
||||
(str = pw_properties_get(o->props, PW_KEY_MEDIA_CLASS)) != NULL &&
|
||||
strcmp(str, "Audio/Device") == 0;
|
||||
}
|
||||
|
||||
static bool is_sink(struct pw_manager_object *o)
|
||||
{
|
||||
const char *str;
|
||||
return
|
||||
strcmp(o->type, PW_TYPE_INTERFACE_Node) == 0 &&
|
||||
o->props != NULL &&
|
||||
(str = pw_properties_get(o->props, PW_KEY_MEDIA_CLASS)) != NULL &&
|
||||
strcmp(str, "Audio/Sink") == 0;
|
||||
}
|
||||
|
||||
static bool is_source(struct pw_manager_object *o)
|
||||
{
|
||||
const char *str;
|
||||
return
|
||||
strcmp(o->type, PW_TYPE_INTERFACE_Node) == 0 &&
|
||||
o->props != NULL &&
|
||||
(str = pw_properties_get(o->props, PW_KEY_MEDIA_CLASS)) != NULL &&
|
||||
strcmp(str, "Audio/Source") == 0;
|
||||
}
|
||||
|
||||
static bool is_sink_input(struct pw_manager_object *o)
|
||||
{
|
||||
const char *str;
|
||||
return
|
||||
strcmp(o->type, PW_TYPE_INTERFACE_Node) == 0 &&
|
||||
o->props != NULL &&
|
||||
(str = pw_properties_get(o->props, PW_KEY_MEDIA_CLASS)) != NULL &&
|
||||
strcmp(str, "Stream/Output/Audio") == 0;
|
||||
}
|
||||
|
||||
static bool is_source_output(struct pw_manager_object *o)
|
||||
{
|
||||
const char *str;
|
||||
return
|
||||
strcmp(o->type, PW_TYPE_INTERFACE_Node) == 0 &&
|
||||
o->props != NULL &&
|
||||
(str = pw_properties_get(o->props, PW_KEY_MEDIA_CLASS)) != NULL &&
|
||||
strcmp(str, "Stream/Input/Audio") == 0;
|
||||
}
|
||||
|
||||
static bool is_link(struct pw_manager_object *o)
|
||||
{
|
||||
return strcmp(o->type, PW_TYPE_INTERFACE_Link) == 0;
|
||||
}
|
||||
|
||||
struct selector {
|
||||
bool (*type) (struct pw_manager_object *o);
|
||||
uint32_t id;
|
||||
const char *key;
|
||||
const char *value;
|
||||
void (*accumulate) (struct selector *sel, struct pw_manager_object *o);
|
||||
int32_t score;
|
||||
struct pw_manager_object *best;
|
||||
};
|
||||
|
||||
static struct pw_manager_object *select_object(struct pw_manager *m,
|
||||
struct selector *s)
|
||||
{
|
||||
struct pw_manager_object *o;
|
||||
const char *str;
|
||||
|
||||
spa_list_for_each(o, &m->object_list, link) {
|
||||
if (s->type != NULL && !s->type(o))
|
||||
continue;
|
||||
if (o->id == s->id)
|
||||
return o;
|
||||
if (s->accumulate)
|
||||
s->accumulate(s, o);
|
||||
if (o->props && s->key != NULL && s->value != NULL &&
|
||||
(str = pw_properties_get(o->props, s->key)) != NULL &&
|
||||
strcmp(str, s->value) == 0)
|
||||
return o;
|
||||
}
|
||||
return s->best;
|
||||
}
|
||||
|
||||
static struct pw_manager_object *find_linked(struct client *client, uint32_t obj_id, enum pw_direction direction)
|
||||
{
|
||||
struct pw_manager *m = client->manager;
|
||||
struct pw_manager_object *o, *p;
|
||||
const char *str;
|
||||
uint32_t in_node, out_node;
|
||||
|
||||
spa_list_for_each(o, &m->object_list, link) {
|
||||
if (o->props == NULL || !is_link(o))
|
||||
continue;
|
||||
|
||||
if ((str = pw_properties_get(o->props, PW_KEY_LINK_OUTPUT_NODE)) == NULL)
|
||||
continue;
|
||||
out_node = pw_properties_parse_int(str);
|
||||
if ((str = pw_properties_get(o->props, PW_KEY_LINK_INPUT_NODE)) == NULL)
|
||||
continue;
|
||||
in_node = pw_properties_parse_int(str);
|
||||
|
||||
if (direction == PW_DIRECTION_OUTPUT && obj_id == out_node) {
|
||||
struct selector sel = { .id = in_node, .type = is_sink, };
|
||||
if ((p = select_object(m, &sel)) != NULL)
|
||||
return p;
|
||||
}
|
||||
if (direction == PW_DIRECTION_INPUT && obj_id == in_node) {
|
||||
struct selector sel = { .id = out_node, .type = is_source, };
|
||||
if ((p = select_object(m, &sel)) != NULL)
|
||||
return p;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct stream *find_stream(struct client *client, uint32_t id)
|
||||
{
|
||||
union pw_map_item *item;
|
||||
|
|
@ -818,9 +946,11 @@ static int reply_create_playback_stream(struct stream *stream)
|
|||
{
|
||||
struct client *client = stream->client;
|
||||
struct message *reply;
|
||||
uint32_t size;
|
||||
uint32_t size, peer_id;
|
||||
struct spa_dict_item items[1];
|
||||
char latency[32];
|
||||
struct pw_manager_object *peer;
|
||||
const char *peer_name;
|
||||
|
||||
fix_playback_buffer_attr(stream, &stream->attr);
|
||||
|
||||
|
|
@ -843,6 +973,15 @@ static int reply_create_playback_stream(struct stream *stream)
|
|||
|
||||
stream->pending = size;
|
||||
|
||||
peer = find_linked(client, stream->id, stream->direction);
|
||||
if (peer) {
|
||||
peer_id = peer->id;
|
||||
peer_name = pw_properties_get(peer->props, PW_KEY_NODE_NAME);
|
||||
} else {
|
||||
peer_id = SPA_ID_INVALID;
|
||||
peer_name = NULL;
|
||||
}
|
||||
|
||||
if (client->version >= 9) {
|
||||
message_put(reply,
|
||||
TAG_U32, stream->attr.maxlength,
|
||||
|
|
@ -855,8 +994,8 @@ static int reply_create_playback_stream(struct stream *stream)
|
|||
message_put(reply,
|
||||
TAG_SAMPLE_SPEC, &stream->ss,
|
||||
TAG_CHANNEL_MAP, &stream->map,
|
||||
TAG_U32, 0, /* sink index */
|
||||
TAG_STRING, "sink", /* sink name */
|
||||
TAG_U32, peer_id, /* sink index */
|
||||
TAG_STRING, peer_name, /* sink name */
|
||||
TAG_BOOLEAN, false, /* sink suspended state */
|
||||
TAG_INVALID);
|
||||
}
|
||||
|
|
@ -911,6 +1050,9 @@ static int reply_create_record_stream(struct stream *stream)
|
|||
struct message *reply;
|
||||
struct spa_dict_item items[1];
|
||||
char latency[32];
|
||||
struct pw_manager_object *peer;
|
||||
const char *peer_name;
|
||||
uint32_t peer_id;
|
||||
|
||||
fix_record_buffer_attr(stream, &stream->attr);
|
||||
|
||||
|
|
@ -928,6 +1070,15 @@ static int reply_create_record_stream(struct stream *stream)
|
|||
TAG_U32, stream->id, /* source_output/stream index */
|
||||
TAG_INVALID);
|
||||
|
||||
peer = find_linked(client, stream->id, stream->direction);
|
||||
if (peer) {
|
||||
peer_id = peer->id;
|
||||
peer_name = pw_properties_get(peer->props, PW_KEY_NODE_NAME);
|
||||
} else {
|
||||
peer_id = SPA_ID_INVALID;
|
||||
peer_name = NULL;
|
||||
}
|
||||
|
||||
if (client->version >= 9) {
|
||||
message_put(reply,
|
||||
TAG_U32, stream->attr.maxlength,
|
||||
|
|
@ -938,8 +1089,8 @@ static int reply_create_record_stream(struct stream *stream)
|
|||
message_put(reply,
|
||||
TAG_SAMPLE_SPEC, &stream->ss,
|
||||
TAG_CHANNEL_MAP, &stream->map,
|
||||
TAG_U32, SPA_ID_INVALID, /* source index */
|
||||
TAG_STRING, NULL, /* source name */
|
||||
TAG_U32, peer_id, /* source index */
|
||||
TAG_STRING, peer_name, /* source name */
|
||||
TAG_BOOLEAN, false, /* source suspended state */
|
||||
TAG_INVALID);
|
||||
}
|
||||
|
|
@ -1232,97 +1383,6 @@ static const struct pw_stream_events stream_events =
|
|||
.drained = stream_drained,
|
||||
};
|
||||
|
||||
static bool is_client(struct pw_manager_object *o)
|
||||
{
|
||||
return strcmp(o->type, PW_TYPE_INTERFACE_Client) == 0;
|
||||
}
|
||||
|
||||
static bool is_module(struct pw_manager_object *o)
|
||||
{
|
||||
return strcmp(o->type, PW_TYPE_INTERFACE_Module) == 0;
|
||||
}
|
||||
|
||||
static bool is_card(struct pw_manager_object *o)
|
||||
{
|
||||
const char *str;
|
||||
return
|
||||
strcmp(o->type, PW_TYPE_INTERFACE_Device) == 0 &&
|
||||
o->props != NULL &&
|
||||
(str = pw_properties_get(o->props, PW_KEY_MEDIA_CLASS)) != NULL &&
|
||||
strcmp(str, "Audio/Device") == 0;
|
||||
}
|
||||
|
||||
static bool is_sink(struct pw_manager_object *o)
|
||||
{
|
||||
const char *str;
|
||||
return
|
||||
strcmp(o->type, PW_TYPE_INTERFACE_Node) == 0 &&
|
||||
o->props != NULL &&
|
||||
(str = pw_properties_get(o->props, PW_KEY_MEDIA_CLASS)) != NULL &&
|
||||
strcmp(str, "Audio/Sink") == 0;
|
||||
}
|
||||
|
||||
static bool is_source(struct pw_manager_object *o)
|
||||
{
|
||||
const char *str;
|
||||
return
|
||||
strcmp(o->type, PW_TYPE_INTERFACE_Node) == 0 &&
|
||||
o->props != NULL &&
|
||||
(str = pw_properties_get(o->props, PW_KEY_MEDIA_CLASS)) != NULL &&
|
||||
strcmp(str, "Audio/Source") == 0;
|
||||
}
|
||||
|
||||
static bool is_sink_input(struct pw_manager_object *o)
|
||||
{
|
||||
const char *str;
|
||||
return
|
||||
strcmp(o->type, PW_TYPE_INTERFACE_Node) == 0 &&
|
||||
o->props != NULL &&
|
||||
(str = pw_properties_get(o->props, PW_KEY_MEDIA_CLASS)) != NULL &&
|
||||
strcmp(str, "Stream/Output/Audio") == 0;
|
||||
}
|
||||
|
||||
static bool is_source_output(struct pw_manager_object *o)
|
||||
{
|
||||
const char *str;
|
||||
return
|
||||
strcmp(o->type, PW_TYPE_INTERFACE_Node) == 0 &&
|
||||
o->props != NULL &&
|
||||
(str = pw_properties_get(o->props, PW_KEY_MEDIA_CLASS)) != NULL &&
|
||||
strcmp(str, "Stream/Input/Audio") == 0;
|
||||
}
|
||||
|
||||
struct selector {
|
||||
bool (*type) (struct pw_manager_object *o);
|
||||
uint32_t id;
|
||||
const char *key;
|
||||
const char *value;
|
||||
void (*accumulate) (struct selector *sel, struct pw_manager_object *o);
|
||||
int32_t score;
|
||||
struct pw_manager_object *best;
|
||||
};
|
||||
|
||||
static struct pw_manager_object *select_object(struct pw_manager *m,
|
||||
struct selector *s)
|
||||
{
|
||||
struct pw_manager_object *o;
|
||||
const char *str;
|
||||
|
||||
spa_list_for_each(o, &m->object_list, link) {
|
||||
if (s->type != NULL && !s->type(o))
|
||||
continue;
|
||||
if (o->id == s->id)
|
||||
return o;
|
||||
if (s->accumulate)
|
||||
s->accumulate(s, o);
|
||||
if (o->props && s->key != NULL && s->value != NULL &&
|
||||
(str = pw_properties_get(o->props, s->key)) != NULL &&
|
||||
strcmp(str, s->value) == 0)
|
||||
return o;
|
||||
}
|
||||
return s->best;
|
||||
}
|
||||
|
||||
static void fix_stream_properties(struct stream *stream, struct pw_properties *props)
|
||||
{
|
||||
const char *str;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue