media-session: link all stream ports

Create a helper in the session manager to link all ports between
2 nodes.

Make the output endpoint call the input endpoint create_link, passing
the node or ports to link to.

Make the input endpoint complete the link by calling the session
helper to link all ports.

Remove the node policy, we're only using a policy for the endpoints
now.
This commit is contained in:
Wim Taymans 2019-11-15 12:08:46 +01:00
parent 9bc5d23ffe
commit 3cd7d90d88
9 changed files with 201 additions and 1447 deletions

View file

@ -113,19 +113,10 @@ static int client_endpoint_create_link(void *object, const struct spa_dict *prop
char buf[1024]; char buf[1024];
struct spa_pod_builder b = { 0, }; struct spa_pod_builder b = { 0, };
struct spa_pod *param; struct spa_pod *param;
int res;
pw_log_debug(NAME" %p: endpoint %p", impl, endpoint); pw_log_debug(NAME" %p: endpoint %p", impl, endpoint);
p = pw_properties_new_dict(props);
if (endpoint->info.direction == PW_DIRECTION_OUTPUT) {
pw_properties_setf(p, PW_KEY_LINK_OUTPUT_NODE, "%d", endpoint->obj->info->id);
pw_properties_setf(p, PW_KEY_LINK_OUTPUT_PORT, "-1");
} else {
pw_properties_setf(p, PW_KEY_LINK_INPUT_NODE, "%d", endpoint->obj->info->id);
pw_properties_setf(p, PW_KEY_LINK_INPUT_PORT, "-1");
}
if (!endpoint->active) { if (!endpoint->active) {
endpoint->format.info.raw.rate = 48000; endpoint->format.info.raw.rate = 48000;
@ -147,15 +138,43 @@ static int client_endpoint_create_link(void *object, const struct spa_dict *prop
endpoint->active = true; endpoint->active = true;
} }
sm_media_session_create_object(impl->session, p = pw_properties_new_dict(props);
"link-factory", if (p == NULL)
PW_TYPE_INTERFACE_Link, return -errno;
PW_VERSION_LINK_PROXY,
&p->dict, 0);
if (endpoint->info.direction == PW_DIRECTION_OUTPUT) {
const char *str;
struct sm_object *obj;
str = spa_dict_lookup(props, PW_KEY_ENDPOINT_LINK_INPUT_ENDPOINT);
if (str == NULL) {
pw_log_warn(NAME" %p: no target endpoint given", impl);
res = -EINVAL;
goto exit;
}
obj = sm_media_session_find_object(impl->session, atoi(str));
if (obj == NULL || obj->type != PW_TYPE_INTERFACE_Endpoint) {
pw_log_warn(NAME" %p: could not find endpoint %s (%p)", impl, str, obj);
res = -EINVAL;
goto exit;
}
pw_properties_setf(p, PW_KEY_LINK_OUTPUT_NODE, "%d", endpoint->obj->info->id);
pw_properties_setf(p, PW_KEY_LINK_OUTPUT_PORT, "-1");
pw_endpoint_proxy_create_link((struct pw_endpoint_proxy*)obj->proxy, &p->dict);
} else {
pw_properties_setf(p, PW_KEY_LINK_INPUT_NODE, "%d", endpoint->obj->info->id);
pw_properties_setf(p, PW_KEY_LINK_INPUT_PORT, "-1");
sm_media_session_create_links(impl->session, &p->dict);
}
res = 0;
exit:
pw_properties_free(p); pw_properties_free(p);
return 0; return res;
} }
static const struct pw_client_endpoint_proxy_events client_endpoint_events = { static const struct pw_client_endpoint_proxy_events client_endpoint_events = {
@ -305,14 +324,14 @@ static int setup_alsa_fallback_endpoint(struct alsa_object *obj)
if ((str = pw_properties_get(n->props, PW_KEY_PRIORITY_SESSION)) != NULL) if ((str = pw_properties_get(n->props, PW_KEY_PRIORITY_SESSION)) != NULL)
pw_properties_set(s->props, PW_KEY_PRIORITY_SESSION, str); pw_properties_set(s->props, PW_KEY_PRIORITY_SESSION, str);
if (n->direction == PW_DIRECTION_OUTPUT) if (n->direction == PW_DIRECTION_OUTPUT)
pw_properties_set(s->props, PW_KEY_STREAM_NAME, "Playback"); pw_properties_set(s->props, PW_KEY_ENDPOINT_STREAM_NAME, "Playback");
else else
pw_properties_set(s->props, PW_KEY_STREAM_NAME, "Capture"); pw_properties_set(s->props, PW_KEY_ENDPOINT_STREAM_NAME, "Capture");
s->info.version = PW_VERSION_ENDPOINT_STREAM_INFO; s->info.version = PW_VERSION_ENDPOINT_STREAM_INFO;
s->info.id = n->id; s->info.id = n->id;
s->info.endpoint_id = endpoint->info.id; s->info.endpoint_id = endpoint->info.id;
s->info.name = (char*)pw_properties_get(s->props, PW_KEY_STREAM_NAME); s->info.name = (char*)pw_properties_get(s->props, PW_KEY_ENDPOINT_STREAM_NAME);
s->info.change_mask = PW_ENDPOINT_STREAM_CHANGE_MASK_PROPS; s->info.change_mask = PW_ENDPOINT_STREAM_CHANGE_MASK_PROPS;
s->info.props = &s->props->dict; s->info.props = &s->props->dict;

View file

@ -605,6 +605,88 @@ struct pw_proxy *sm_media_session_create_object(struct sm_media_session *sess,
factory_name, type, version, props, user_data_size); factory_name, type, version, props, user_data_size);
} }
int sm_media_session_create_links(struct sm_media_session *sess,
const struct spa_dict *dict)
{
struct impl *impl = SPA_CONTAINER_OF(sess, struct impl, this);
struct sm_object *obj;
struct sm_node *outnode, *innode;
struct sm_port *outport, *inport;
struct pw_properties *props;
const char *str;
int res;
sm_media_session_roundtrip(sess);
/* find output node */
if ((str = spa_dict_lookup(dict, PW_KEY_LINK_OUTPUT_NODE)) == NULL) {
res = -EINVAL;
pw_log_error(NAME" %p: no output node given", impl);
goto exit;
}
if ((obj = find_object(impl, atoi(str))) == NULL ||
obj->type != PW_TYPE_INTERFACE_Node) {
res = -EINVAL;
pw_log_error(NAME" %p: can find output node %s", impl, str);
goto exit;
}
outnode = (struct sm_node*)obj;
/* find input node */
if ((str = spa_dict_lookup(dict, PW_KEY_LINK_INPUT_NODE)) == NULL) {
res = -EINVAL;
pw_log_error(NAME" %p: no input node given", impl);
goto exit;
}
if ((obj = find_object(impl, atoi(str))) == NULL ||
obj->type != PW_TYPE_INTERFACE_Node) {
res = -EINVAL;
pw_log_error(NAME" %p: can find input node %s", impl, str);
goto exit;
}
innode = (struct sm_node*)obj;
pw_log_debug(NAME" %p: linking %d -> %d", impl, outnode->obj.id, innode->obj.id);
props = pw_properties_new(NULL, NULL);
pw_properties_setf(props, PW_KEY_LINK_OUTPUT_NODE, "%d", outnode->obj.id);
pw_properties_setf(props, PW_KEY_LINK_INPUT_NODE, "%d", innode->obj.id);
for (outport = spa_list_first(&outnode->port_list, struct sm_port, link),
inport = spa_list_first(&innode->port_list, struct sm_port, link);
!spa_list_is_end(outport, &outnode->port_list, link) &&
!spa_list_is_end(inport, &innode->port_list, link);) {
pw_log_debug(NAME" %p: port %d:%d -> %d:%d", impl,
outport->direction, outport->obj.id,
inport->direction, inport->obj.id);
if (outport->direction == PW_DIRECTION_OUTPUT &&
inport->direction == PW_DIRECTION_INPUT) {
pw_properties_setf(props, PW_KEY_LINK_OUTPUT_PORT, "%d", outport->obj.id);
pw_properties_setf(props, PW_KEY_LINK_INPUT_PORT, "%d", inport->obj.id);
sm_media_session_create_object(sess, "link-factory",
PW_TYPE_INTERFACE_Link,
PW_VERSION_LINK_PROXY,
&props->dict, 0);
outport = spa_list_next(outport, link);
inport = spa_list_next(inport, link);
} else {
if (outport->direction != PW_DIRECTION_OUTPUT)
outport = spa_list_next(outport, link);
if (inport->direction != PW_DIRECTION_INPUT)
inport = spa_list_next(inport, link);
}
}
pw_properties_free(props);
res = 0;
exit:
return res;
}
/** /**
* Session implementation * Session implementation

View file

@ -168,6 +168,9 @@ struct pw_proxy *sm_media_session_create_object(struct sm_media_session *sess,
const char *factory_name, uint32_t type, uint32_t version, const char *factory_name, uint32_t type, uint32_t version,
const struct spa_dict *props, size_t user_data_size); const struct spa_dict *props, size_t user_data_size);
int sm_media_session_create_links(struct sm_media_session *sess,
const struct spa_dict *dict);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View file

@ -43,6 +43,7 @@
#include "media-session.h" #include "media-session.h"
#define NAME "policy-ep" #define NAME "policy-ep"
#define SESSION_KEY "policy-endpoint"
#define DEFAULT_CHANNELS 2 #define DEFAULT_CHANNELS 2
#define DEFAULT_SAMPLERATE 48000 #define DEFAULT_SAMPLERATE 48000
@ -108,7 +109,7 @@ handle_endpoint(struct impl *impl, struct sm_object *object)
struct endpoint *ep; struct endpoint *ep;
uint32_t client_id = SPA_ID_INVALID; uint32_t client_id = SPA_ID_INVALID;
if (sm_object_get_data(object, "policy-endpoint") != NULL) if (sm_object_get_data(object, SESSION_KEY) != NULL)
return 0; return 0;
if (object->props) { if (object->props) {
@ -123,7 +124,7 @@ handle_endpoint(struct impl *impl, struct sm_object *object)
if (media_class == NULL) if (media_class == NULL)
return 0; return 0;
ep = sm_object_add_data(object, "policy-endpoint", sizeof(struct endpoint)); ep = sm_object_add_data(object, SESSION_KEY, sizeof(struct endpoint));
ep->obj = (struct sm_endpoint*)object; ep->obj = (struct sm_endpoint*)object;
ep->id = object->id; ep->id = object->id;
ep->impl = impl; ep->impl = impl;
@ -183,27 +184,22 @@ handle_stream(struct impl *impl, struct sm_object *object)
struct stream *s; struct stream *s;
struct endpoint *ep; struct endpoint *ep;
if (sm_object_get_data(object, "policy-endpoint") != NULL) if (sm_object_get_data(object, SESSION_KEY) != NULL)
return 0; return 0;
if (stream->endpoint == NULL) if (stream->endpoint == NULL)
return 0; return 0;
ep = sm_object_get_data(&stream->endpoint->obj, "policy-endpoint"); ep = sm_object_get_data(&stream->endpoint->obj, SESSION_KEY);
if (ep == NULL) if (ep == NULL)
return 0; return 0;
s = sm_object_add_data(object, "policy-endpoint", sizeof(struct stream)); s = sm_object_add_data(object, SESSION_KEY, sizeof(struct stream));
s->obj = (struct sm_endpoint_stream*)object; s->obj = (struct sm_endpoint_stream*)object;
s->id = object->id; s->id = object->id;
s->impl = impl; s->impl = impl;
s->endpoint = ep; s->endpoint = ep;
if (s->endpoint->type == ENDPOINT_TYPE_DEVICE) {
pw_endpoint_stream_proxy_enum_params((struct pw_endpoint_stream_proxy*)stream->obj.proxy,
0, SPA_PARAM_EnumFormat,
0, -1, NULL);
}
return 0; return 0;
} }
@ -212,8 +208,6 @@ static void session_update(void *data, struct sm_object *object)
struct impl *impl = data; struct impl *impl = data;
int res; int res;
pw_log_debug(NAME " %p: update global '%d'", impl, object->id);
switch (object->type) { switch (object->type) {
case PW_TYPE_INTERFACE_Endpoint: case PW_TYPE_INTERFACE_Endpoint:
res = handle_endpoint(impl, object); res = handle_endpoint(impl, object);
@ -243,8 +237,10 @@ static void session_remove(void *data, struct sm_object *object)
case PW_TYPE_INTERFACE_Endpoint: case PW_TYPE_INTERFACE_Endpoint:
{ {
struct endpoint *ep; struct endpoint *ep;
if ((ep = sm_object_get_data(object, "policy-endpoint")) != NULL) if ((ep = sm_object_get_data(object, SESSION_KEY)) != NULL) {
spa_list_remove(&ep->link); spa_list_remove(&ep->link);
free(ep->media);
}
break; break;
} }
default: default:
@ -323,24 +319,18 @@ static int link_endpoints(struct endpoint *endpoint, enum pw_direction direction
pw_log_debug(NAME " %p: link endpoints %d %d %d", impl, max, endpoint->id, peer->id); pw_log_debug(NAME " %p: link endpoints %d %d %d", impl, max, endpoint->id, peer->id);
if (endpoint->direction == PW_DIRECTION_INPUT) {
struct endpoint *t = endpoint;
endpoint = peer;
peer = t;
}
props = pw_properties_new(NULL, NULL); props = pw_properties_new(NULL, NULL);
if (endpoint->direction == PW_DIRECTION_OUTPUT) { pw_properties_setf(props, PW_KEY_ENDPOINT_LINK_OUTPUT_ENDPOINT, "%d", endpoint->id);
pw_properties_setf(props, PW_KEY_LINK_OUTPUT_NODE, "%d", endpoint->id); pw_properties_setf(props, PW_KEY_ENDPOINT_LINK_OUTPUT_STREAM, "%d", -1);
pw_properties_setf(props, PW_KEY_LINK_OUTPUT_PORT, "%d", -1); pw_properties_setf(props, PW_KEY_ENDPOINT_LINK_INPUT_ENDPOINT, "%d", peer->id);
pw_properties_setf(props, PW_KEY_LINK_INPUT_NODE, "%d", peer->id); pw_properties_setf(props, PW_KEY_ENDPOINT_LINK_INPUT_STREAM, "%d", -1);
pw_properties_setf(props, PW_KEY_LINK_INPUT_PORT, "%d", -1); pw_log_debug(NAME " %p: endpoint %d -> endpoint %d", impl,
pw_log_debug(NAME " %p: endpoint %d -> endpoint %d", impl, endpoint->id, peer->id);
endpoint->id, peer->id);
}
else {
pw_properties_setf(props, PW_KEY_LINK_OUTPUT_NODE, "%d", peer->id);
pw_properties_setf(props, PW_KEY_LINK_OUTPUT_PORT, "%d", -1);
pw_properties_setf(props, PW_KEY_LINK_INPUT_NODE, "%d", endpoint->id);
pw_properties_setf(props, PW_KEY_LINK_INPUT_PORT, "%d", -1);
pw_log_debug(NAME " %p: endpoint %d -> endpoint %d", impl,
peer->id, endpoint->id);
}
pw_endpoint_proxy_create_link((struct pw_endpoint_proxy*)endpoint->obj->obj.proxy, pw_endpoint_proxy_create_link((struct pw_endpoint_proxy*)endpoint->obj->obj.proxy,
&props->dict); &props->dict);
@ -487,7 +477,7 @@ static int rescan_endpoint(struct impl *impl, struct endpoint *ep)
if ((obj = sm_media_session_find_object(impl->session, find.path_id)) != NULL) { if ((obj = sm_media_session_find_object(impl->session, find.path_id)) != NULL) {
if (obj->type == PW_TYPE_INTERFACE_Endpoint) { if (obj->type == PW_TYPE_INTERFACE_Endpoint) {
peer = sm_object_get_data(obj, "policy-endpoint"); peer = sm_object_get_data(obj, SESSION_KEY);
goto do_link; goto do_link;
} }
} }

File diff suppressed because it is too large Load diff

View file

@ -42,6 +42,7 @@
#include "media-session.h" #include "media-session.h"
#define NAME "stream-monitor" #define NAME "stream-monitor"
#define SESSION_KEY "stream-monitor"
#define DEFAULT_CHANNELS 2 #define DEFAULT_CHANNELS 2
#define DEFAULT_SAMPLERATE 48000 #define DEFAULT_SAMPLERATE 48000
@ -120,7 +121,13 @@ static int client_endpoint_set_session_id(void *object, uint32_t id)
static int client_endpoint_set_param(void *object, static int client_endpoint_set_param(void *object,
uint32_t id, uint32_t flags, const struct spa_pod *param) uint32_t id, uint32_t flags, const struct spa_pod *param)
{ {
return -ENOTSUP; struct client_endpoint *endpoint = object;
struct impl *impl = endpoint->impl;
struct node *node = endpoint->node;
pw_log_debug(NAME " %p: node %d set param %d", impl, node->obj->obj.id, id);
return pw_node_proxy_set_param((struct pw_node_proxy*)node->obj->obj.proxy,
id, flags, param);
} }
@ -134,8 +141,6 @@ static int client_endpoint_create_link(void *object, const struct spa_dict *prop
{ {
struct client_endpoint *endpoint = object; struct client_endpoint *endpoint = object;
struct impl *impl = endpoint->impl; struct impl *impl = endpoint->impl;
const char *str;
struct sm_object *obj;
struct node *node = endpoint->node; struct node *node = endpoint->node;
struct pw_properties *p; struct pw_properties *p;
int res; int res;
@ -152,22 +157,9 @@ static int client_endpoint_create_link(void *object, const struct spa_dict *prop
if (endpoint->info.direction == PW_DIRECTION_OUTPUT) { if (endpoint->info.direction == PW_DIRECTION_OUTPUT) {
pw_properties_setf(p, PW_KEY_LINK_OUTPUT_NODE, "%d", endpoint->node->id); pw_properties_setf(p, PW_KEY_LINK_OUTPUT_NODE, "%d", endpoint->node->id);
pw_properties_setf(p, PW_KEY_LINK_OUTPUT_PORT, "-1"); pw_properties_setf(p, PW_KEY_LINK_OUTPUT_PORT, "-1");
str = spa_dict_lookup(props, PW_KEY_LINK_INPUT_NODE);
} else { } else {
pw_properties_setf(p, PW_KEY_LINK_INPUT_NODE, "%d", endpoint->node->id); pw_properties_setf(p, PW_KEY_LINK_INPUT_NODE, "%d", endpoint->node->id);
pw_properties_setf(p, PW_KEY_LINK_INPUT_PORT, "-1"); pw_properties_setf(p, PW_KEY_LINK_INPUT_PORT, "-1");
str = spa_dict_lookup(props, PW_KEY_LINK_OUTPUT_NODE);
}
if (str == NULL) {
pw_log_warn(NAME" %p: no target endpoint given", impl);
res = -EINVAL;
goto exit;
}
obj = sm_media_session_find_object(impl->session, atoi(str));
if (obj == NULL || obj->type != PW_TYPE_INTERFACE_Endpoint) {
pw_log_warn(NAME" %p: could not find object %s (%p)", impl, str, obj);
res = -EINVAL;
goto exit;
} }
if (!endpoint->stream.active) { if (!endpoint->stream.active) {
@ -192,12 +184,29 @@ static int client_endpoint_create_link(void *object, const struct spa_dict *prop
pw_node_proxy_set_param((struct pw_node_proxy*)node->obj->obj.proxy, pw_node_proxy_set_param((struct pw_node_proxy*)node->obj->obj.proxy,
SPA_PARAM_PortConfig, 0, param); SPA_PARAM_PortConfig, 0, param);
endpoint->pending_config = pw_proxy_sync(node->obj->obj.proxy, 0);
endpoint->stream.active = true; endpoint->stream.active = true;
} }
pw_endpoint_proxy_create_link((struct pw_endpoint_proxy*)obj->proxy, &p->dict); if (endpoint->info.direction == PW_DIRECTION_OUTPUT) {
const char *str;
struct sm_object *obj;
str = spa_dict_lookup(props, PW_KEY_ENDPOINT_LINK_INPUT_ENDPOINT);
if (str == NULL) {
pw_log_warn(NAME" %p: no target endpoint given", impl);
res = -EINVAL;
goto exit;
}
obj = sm_media_session_find_object(impl->session, atoi(str));
if (obj == NULL || obj->type != PW_TYPE_INTERFACE_Endpoint) {
pw_log_warn(NAME" %p: could not find endpoint %s (%p)", impl, str, obj);
res = -EINVAL;
goto exit;
}
pw_endpoint_proxy_create_link((struct pw_endpoint_proxy*)obj->proxy, &p->dict);
} else {
sm_media_session_create_links(impl->session, &p->dict);
}
res = 0; res = 0;
@ -277,14 +286,14 @@ static struct client_endpoint *make_endpoint(struct node *node)
if ((str = pw_properties_get(props, PW_KEY_MEDIA_CLASS)) != NULL) if ((str = pw_properties_get(props, PW_KEY_MEDIA_CLASS)) != NULL)
pw_properties_set(s->props, PW_KEY_MEDIA_CLASS, str); pw_properties_set(s->props, PW_KEY_MEDIA_CLASS, str);
if (node->direction == PW_DIRECTION_OUTPUT) if (node->direction == PW_DIRECTION_OUTPUT)
pw_properties_set(s->props, PW_KEY_STREAM_NAME, "Playback"); pw_properties_set(s->props, PW_KEY_ENDPOINT_STREAM_NAME, "Playback");
else else
pw_properties_set(s->props, PW_KEY_STREAM_NAME, "Capture"); pw_properties_set(s->props, PW_KEY_ENDPOINT_STREAM_NAME, "Capture");
s->info.version = PW_VERSION_ENDPOINT_STREAM_INFO; s->info.version = PW_VERSION_ENDPOINT_STREAM_INFO;
s->info.id = 0; s->info.id = 0;
s->info.endpoint_id = endpoint->info.id; s->info.endpoint_id = endpoint->info.id;
s->info.name = (char*)pw_properties_get(s->props, PW_KEY_STREAM_NAME); s->info.name = (char*)pw_properties_get(s->props, PW_KEY_ENDPOINT_STREAM_NAME);
s->info.change_mask = PW_ENDPOINT_STREAM_CHANGE_MASK_PROPS; s->info.change_mask = PW_ENDPOINT_STREAM_CHANGE_MASK_PROPS;
s->info.props = &s->props->dict; s->info.props = &s->props->dict;
@ -349,46 +358,6 @@ static const struct pw_node_proxy_events node_events = {
.param = node_event_param, .param = node_event_param,
}; };
static void node_proxy_destroy(void *data)
{
struct node *n = data;
struct impl *impl = n->impl;
pw_log_debug(NAME " %p: proxy destroy node %d", impl, n->id);
if (n->endpoint)
destroy_endpoint(n->endpoint);
free(n->media);
}
static void node_proxy_done(void *data, int seq)
{
struct node *n = data;
struct impl *impl = n->impl;
struct client_endpoint *endpoint = n->endpoint;
if (endpoint == NULL)
return;
if (endpoint->pending_config != 0) {
pw_log_debug(NAME" %p: config complete", impl);
endpoint->pending_config = 0;
}
}
static void node_proxy_error(void *data, int seq, int res, const char *message)
{
struct node *n = data;
struct impl *impl = n->impl;
pw_log_error(NAME " %p: proxy seq:%d got error %d: %s", impl, seq, res, message);
}
static const struct pw_proxy_events node_proxy_events = {
PW_VERSION_PROXY_EVENTS,
.destroy = node_proxy_destroy,
.done = node_proxy_done,
.error = node_proxy_error,
};
static int static int
handle_node(struct impl *impl, struct sm_object *obj) handle_node(struct impl *impl, struct sm_object *obj)
{ {
@ -396,7 +365,7 @@ handle_node(struct impl *impl, struct sm_object *obj)
enum pw_direction direction; enum pw_direction direction;
struct node *node; struct node *node;
if (sm_object_get_data(obj, "stream-monitor") != NULL) if (sm_object_get_data(obj, SESSION_KEY) != NULL)
return 0; return 0;
media_class = obj->props ? pw_properties_get(obj->props, PW_KEY_MEDIA_CLASS) : NULL; media_class = obj->props ? pw_properties_get(obj->props, PW_KEY_MEDIA_CLASS) : NULL;
@ -422,7 +391,7 @@ handle_node(struct impl *impl, struct sm_object *obj)
else else
return 0; return 0;
node = sm_object_add_data(obj, "stream-monitor", sizeof(struct node)); node = sm_object_add_data(obj, SESSION_KEY, sizeof(struct node));
node->obj = (struct sm_node*)obj; node->obj = (struct sm_node*)obj;
node->impl = impl; node->impl = impl;
node->id = obj->id; node->id = obj->id;
@ -430,7 +399,6 @@ handle_node(struct impl *impl, struct sm_object *obj)
node->media = strdup(media_class); node->media = strdup(media_class);
pw_log_debug(NAME "%p: node %d is stream %s", impl, node->id, node->media); pw_log_debug(NAME "%p: node %d is stream %s", impl, node->id, node->media);
pw_proxy_add_listener(obj->proxy, &node->proxy_listener, &node_proxy_events, node);
pw_proxy_add_object_listener(obj->proxy, &node->listener, &node_events, node); pw_proxy_add_object_listener(obj->proxy, &node->listener, &node_events, node);
pw_node_proxy_enum_params((struct pw_node_proxy*)obj->proxy, pw_node_proxy_enum_params((struct pw_node_proxy*)obj->proxy,
@ -439,73 +407,11 @@ handle_node(struct impl *impl, struct sm_object *obj)
return 1; return 1;
} }
#if 0
static void stream_set_volume(struct impl *impl, struct node *node, float volume, bool mute)
{
char buf[1024];
struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buf, sizeof(buf));
pw_log_debug(NAME " %p: node %d set volume:%f mute:%d", impl, node->obj.id, volume, mute);
pw_node_proxy_set_param((struct pw_node_proxy*)node->obj.proxy,
SPA_PARAM_Props, 0,
spa_pod_builder_add_object(&b,
SPA_TYPE_OBJECT_Props, SPA_PARAM_Props,
SPA_PROP_volume, SPA_POD_Float(volume),
SPA_PROP_mute, SPA_POD_Bool(mute)));
}
static void rescan_session(struct impl *impl, struct session *sess)
{
struct node *node = sess->node;
struct spa_audio_info_raw info = { 0, };
uint8_t buf[1024];
struct spa_pod_builder b = { 0, };
struct spa_pod *param;
if (!sess->starting)
return;
if (node->info->props == NULL) {
pw_log_debug(NAME " %p: node %p has no properties", impl, node);
return;
}
if (node->media_type != SPA_MEDIA_TYPE_audio ||
node->media_subtype != SPA_MEDIA_SUBTYPE_raw) {
pw_log_debug(NAME " %p: node %p has no media type", impl, node);
return;
}
info = node->format;
info.rate = DEFAULT_SAMPLERATE;
pw_log_debug(NAME" %p: setting profile for session %d %d", impl, sess->id, sess->direction);
spa_pod_builder_init(&b, buf, sizeof(buf));
param = spa_format_audio_raw_build(&b, SPA_PARAM_Format, &info);
param = spa_pod_builder_add_object(&b,
SPA_TYPE_OBJECT_ParamPortConfig, SPA_PARAM_PortConfig,
SPA_PARAM_PORT_CONFIG_direction, SPA_POD_Id(pw_direction_reverse(sess->direction)),
SPA_PARAM_PORT_CONFIG_mode, SPA_POD_Id(SPA_PARAM_PORT_CONFIG_MODE_dsp),
SPA_PARAM_PORT_CONFIG_monitor, SPA_POD_Bool(true),
SPA_PARAM_PORT_CONFIG_format, SPA_POD_Pod(param));
pw_node_proxy_set_param((struct pw_node_proxy*)sess->node->obj.proxy,
SPA_PARAM_PortConfig, 0, param);
schedule_rescan(impl);
sess->starting = false;
}
#endif
static void session_update(void *data, struct sm_object *object) static void session_update(void *data, struct sm_object *object)
{ {
struct impl *impl = data; struct impl *impl = data;
int res; int res;
pw_log_debug(NAME " %p: update object '%d' %d", impl, object->id, object->type);
switch (object->type) { switch (object->type) {
case PW_TYPE_INTERFACE_Node: case PW_TYPE_INTERFACE_Node:
res = handle_node(impl, object); res = handle_node(impl, object);
@ -523,6 +429,20 @@ static void session_update(void *data, struct sm_object *object)
static void session_remove(void *data, struct sm_object *object) static void session_remove(void *data, struct sm_object *object)
{ {
switch (object->type) {
case PW_TYPE_INTERFACE_Node:
{
struct node *node;
if ((node = sm_object_get_data(object, SESSION_KEY)) != NULL) {
if (node->endpoint)
destroy_endpoint(node->endpoint);
free(node->media);
}
break;
}
default:
break;
}
} }
static const struct sm_media_session_events session_events = { static const struct sm_media_session_events session_events = {

View file

@ -48,7 +48,6 @@ executable('media-session',
'media-session/media-session.c', 'media-session/media-session.c',
'media-session/monitor.c', 'media-session/monitor.c',
'media-session/stream-monitor.c', 'media-session/stream-monitor.c',
'media-session/policy.c',
'media-session/policy-ep.c', 'media-session/policy-ep.c',
c_args : [ '-D_GNU_SOURCE' ], c_args : [ '-D_GNU_SOURCE' ],
install: false, install: false,

View file

@ -39,9 +39,14 @@ extern "C" {
#define PW_KEY_ENDPOINT_AUTOCONNECT "endpoint.autoconnect" /**< try to automatically connect this #define PW_KEY_ENDPOINT_AUTOCONNECT "endpoint.autoconnect" /**< try to automatically connect this
* endpoint. */ * endpoint. */
#define PW_KEY_STREAM_ID "stream.id" /**< id of a stream */ #define PW_KEY_ENDPOINT_STREAM_ID "endpoint-stream.id" /**< id of a stream */
#define PW_KEY_STREAM_NAME "stream.name" /**< unique name of a stream */ #define PW_KEY_ENDPOINT_STREAM_NAME "endpoint-stream.name" /**< unique name of a stream */
#define PW_KEY_STREAM_DESCRIPTION "stream.description" /**< description of a stream */ #define PW_KEY_ENDPOINT_STREAM_DESCRIPTION "endpoint-stream.description" /**< description of a stream */
#define PW_KEY_ENDPOINT_LINK_OUTPUT_ENDPOINT "endpoint-link.output.endpoint" /**< output endpoint of link */
#define PW_KEY_ENDPOINT_LINK_OUTPUT_STREAM "endpoint-link.output.stream" /**< output stream of link */
#define PW_KEY_ENDPOINT_LINK_INPUT_ENDPOINT "endpoint-link.input.endpoint" /**< input endpoint of link */
#define PW_KEY_ENDPOINT_LINK_INPUT_STREAM "endpoint-link.inut.stream" /**< input stream of link */
#ifdef __cplusplus #ifdef __cplusplus
} }

View file

@ -84,8 +84,8 @@ static int client_endpoint_stream_update(void *object,
PW_KEY_CLIENT_ID, PW_KEY_CLIENT_ID,
PW_KEY_ENDPOINT_ID, PW_KEY_ENDPOINT_ID,
PW_KEY_PRIORITY_SESSION, PW_KEY_PRIORITY_SESSION,
PW_KEY_STREAM_NAME, PW_KEY_ENDPOINT_STREAM_NAME,
PW_KEY_STREAM_DESCRIPTION, PW_KEY_ENDPOINT_STREAM_DESCRIPTION,
NULL NULL
}; };