media-session: keep track of dsp proxy

Keep the dsp_proxy around because we need it to clean up the
session.
This commit is contained in:
Wim Taymans 2018-10-05 10:28:20 +02:00
parent 4764d69e26
commit 41d38e56df

View file

@ -129,8 +129,8 @@ struct session {
struct node *node; struct node *node;
struct node *dsp; struct node *dsp;
struct pw_link_proxy *link; struct pw_proxy *dsp_proxy;
struct spa_hook link_listener; struct pw_proxy *link_proxy;
struct spa_list node_list; struct spa_list node_list;
@ -139,7 +139,6 @@ struct session {
struct spa_source *idle_timeout; struct spa_source *idle_timeout;
bool starting; bool starting;
bool dsp_pending;
bool enabled; bool enabled;
bool busy; bool busy;
bool exclusive; bool exclusive;
@ -217,9 +216,13 @@ static void add_idle_timeout(struct session *sess)
static int unlink_session_dsp(struct impl *impl, struct session *session) static int unlink_session_dsp(struct impl *impl, struct session *session)
{ {
if (session->link_proxy == NULL)
return 0;
if (impl->core_proxy) if (impl->core_proxy)
pw_core_proxy_destroy(impl->core_proxy, (struct pw_proxy*)session->link); pw_core_proxy_destroy(impl->core_proxy, session->link_proxy);
session->link = NULL;
session->link_proxy = NULL;
return 0; return 0;
} }
@ -233,8 +236,7 @@ static int on_node_idle(struct impl *impl, struct node *node)
switch (node->type) { switch (node->type) {
case NODE_TYPE_DSP: case NODE_TYPE_DSP:
pw_log_debug(NAME" %p: dsp idle for session %d", impl, sess->id); pw_log_debug(NAME" %p: dsp idle for session %d", impl, sess->id);
if (sess->link) unlink_session_dsp(impl, sess);
unlink_session_dsp(impl, sess);
break; break;
case NODE_TYPE_DEVICE: case NODE_TYPE_DEVICE:
@ -254,6 +256,9 @@ static int link_session_dsp(struct impl *impl, struct session *session)
{ {
struct pw_properties *props; struct pw_properties *props;
if (session->link_proxy != NULL)
return 0;
pw_log_debug(NAME " %p: link session dsp '%d'", impl, session->id); pw_log_debug(NAME " %p: link session dsp '%d'", impl, session->id);
props = pw_properties_new(NULL, NULL); props = pw_properties_new(NULL, NULL);
@ -271,12 +276,14 @@ static int link_session_dsp(struct impl *impl, struct session *session)
pw_properties_setf(props, PW_LINK_INPUT_PORT_ID, "%d", -1); pw_properties_setf(props, PW_LINK_INPUT_PORT_ID, "%d", -1);
} }
session->link = pw_core_proxy_create_object(impl->core_proxy, session->link_proxy = pw_core_proxy_create_object(impl->core_proxy,
"link-factory", "link-factory",
PW_TYPE_INTERFACE_Link, PW_TYPE_INTERFACE_Link,
PW_VERSION_LINK, PW_VERSION_LINK,
&props->dict, &props->dict,
0); 0);
pw_properties_free(props);
return 0; return 0;
} }
@ -290,8 +297,7 @@ static int on_node_running(struct impl *impl, struct node *node)
switch (node->type) { switch (node->type) {
case NODE_TYPE_DSP: case NODE_TYPE_DSP:
pw_log_debug(NAME" %p: dsp running for session %d", impl, sess->id); pw_log_debug(NAME" %p: dsp running for session %d", impl, sess->id);
if (sess->link == NULL) link_session_dsp(impl, sess);
link_session_dsp(impl, sess);
break; break;
case NODE_TYPE_DEVICE: case NODE_TYPE_DEVICE:
@ -374,9 +380,14 @@ static void remove_session(struct impl *impl, struct session *sess)
spa_list_remove(&n->session_link); spa_list_remove(&n->session_link);
} }
if (sess->dsp && impl->core_proxy) { if (sess->dsp) {
pw_log_debug(NAME " %p: destroy dsp %p", impl, sess->dsp->obj.proxy); sess->dsp->manager = NULL;
pw_core_proxy_destroy(impl->core_proxy, sess->dsp->obj.proxy); }
if (sess->dsp_proxy) {
pw_log_debug(NAME " %p: destroy dsp %p", impl, sess->dsp_proxy);
if (impl->core_proxy)
pw_core_proxy_destroy(impl->core_proxy, sess->dsp_proxy);
sess->dsp_proxy = NULL;
} }
spa_list_remove(&sess->l); spa_list_remove(&sess->l);
free(sess); free(sess);
@ -418,12 +429,14 @@ static int
handle_node(struct impl *impl, uint32_t id, uint32_t parent_id, handle_node(struct impl *impl, uint32_t id, uint32_t parent_id,
uint32_t type, const struct spa_dict *props) uint32_t type, const struct spa_dict *props)
{ {
const char *str; const char *str, *media_class;
bool need_dsp = false; bool need_dsp = false;
enum pw_direction direction; enum pw_direction direction;
struct pw_proxy *p; struct pw_proxy *p;
struct node *node; struct node *node;
media_class = props ? spa_dict_lookup(props, "media.class") : NULL;
p = pw_registry_proxy_bind(impl->registry_proxy, p = pw_registry_proxy_bind(impl->registry_proxy,
id, type, PW_VERSION_NODE, id, type, PW_VERSION_NODE,
sizeof(struct node)); sizeof(struct node));
@ -441,20 +454,17 @@ handle_node(struct impl *impl, uint32_t id, uint32_t parent_id,
spa_list_append(&impl->node_list, &node->l); spa_list_append(&impl->node_list, &node->l);
node->type = NODE_TYPE_UNKNOWN; node->type = NODE_TYPE_UNKNOWN;
if (props == NULL) if (media_class == NULL)
return 0; return 0;
if ((str = spa_dict_lookup(props, "media.class")) == NULL) pw_log_debug(NAME" %p: node media.class %s", impl, media_class);
return 0;
pw_log_debug(NAME" %p: node media.class %s", impl, str); if (strstr(media_class, "Stream/") == media_class) {
media_class += strlen("Stream/");
if (strstr(str, "Stream/") == str) { if (strstr(media_class, "Output/") == media_class)
str += strlen("Stream/");
if (strstr(str, "Output/") == str)
direction = PW_DIRECTION_OUTPUT; direction = PW_DIRECTION_OUTPUT;
else if (strstr(str, "Input/") == str) else if (strstr(media_class, "Input/") == media_class)
direction = PW_DIRECTION_INPUT; direction = PW_DIRECTION_INPUT;
else else
return 0; return 0;
@ -470,19 +480,19 @@ handle_node(struct impl *impl, uint32_t id, uint32_t parent_id,
else { else {
struct session *sess; struct session *sess;
if (strstr(str, "Audio/") == str) { if (strstr(media_class, "Audio/") == media_class) {
need_dsp = true; need_dsp = true;
str += strlen("Audio/"); media_class += strlen("Audio/");
} }
else if (strstr(str, "Video/") == str) { else if (strstr(media_class, "Video/") == media_class) {
str += strlen("Video/"); media_class += strlen("Video/");
} }
else else
return 0; return 0;
if (strcmp(str, "Sink") == 0) if (strcmp(media_class, "Sink") == 0)
direction = PW_DIRECTION_OUTPUT; direction = PW_DIRECTION_OUTPUT;
else if (strcmp(str, "Source") == 0) else if (strcmp(media_class, "Source") == 0)
direction = PW_DIRECTION_INPUT; direction = PW_DIRECTION_INPUT;
else else
return 0; return 0;
@ -732,12 +742,13 @@ static int find_session(void *data, struct session *sess)
static int link_nodes(struct node *peer, enum pw_direction direction, struct node *node) static int link_nodes(struct node *peer, enum pw_direction direction, struct node *node)
{ {
struct impl *impl = peer->obj.impl; struct impl *impl = peer->obj.impl;
struct pw_properties *props;
struct port *p; struct port *p;
pw_log_debug(NAME " %p: link nodes %d %d", impl, node->obj.id, peer->obj.id); pw_log_debug(NAME " %p: link nodes %d %d", impl, node->obj.id, peer->obj.id);
spa_list_for_each(p, &peer->port_list, l) { spa_list_for_each(p, &peer->port_list, l) {
struct pw_properties *props;
if (p->direction == direction) if (p->direction == direction)
continue; continue;
@ -766,6 +777,8 @@ static int link_nodes(struct node *peer, enum pw_direction direction, struct nod
PW_VERSION_LINK, PW_VERSION_LINK,
&props->dict, &props->dict,
0); 0);
pw_properties_free(props);
} }
return 0; return 0;
} }
@ -876,7 +889,7 @@ static int rescan_node(struct impl *impl, struct node *node)
pw_log_warn(NAME" %p: session %d busy, can't get exclusive access", impl, session->id); pw_log_warn(NAME" %p: session %d busy, can't get exclusive access", impl, session->id);
return -EBUSY; return -EBUSY;
} }
if (session->link != NULL) { if (session->link_proxy != NULL) {
pw_log_warn(NAME" %p: session %d busy with DSP", impl, session->id); pw_log_warn(NAME" %p: session %d busy with DSP", impl, session->id);
return -EBUSY; return -EBUSY;
} }
@ -928,10 +941,9 @@ static const struct pw_node_proxy_events dsp_node_events = {
static void rescan_session(struct impl *impl, struct session *sess) static void rescan_session(struct impl *impl, struct session *sess)
{ {
if (sess->need_dsp && sess->dsp == NULL && !sess->dsp_pending) { if (sess->need_dsp && sess->dsp == NULL && sess->dsp_proxy == NULL) {
struct pw_properties *props; struct pw_properties *props;
struct node *node = sess->node; struct node *node = sess->node;
void *dsp;
int i; int i;
uint64_t mask = 0; uint64_t mask = 0;
@ -950,14 +962,15 @@ static void rescan_session(struct impl *impl, struct session *sess)
pw_log_debug(NAME" %p: making audio dsp for session %d", impl, sess->id); pw_log_debug(NAME" %p: making audio dsp for session %d", impl, sess->id);
dsp = pw_core_proxy_create_object(impl->core_proxy, sess->dsp_proxy = pw_core_proxy_create_object(impl->core_proxy,
"audio-dsp", "audio-dsp",
PW_TYPE_INTERFACE_Node, PW_TYPE_INTERFACE_Node,
PW_VERSION_NODE, PW_VERSION_NODE,
&props->dict, &props->dict,
0); 0);
sess->dsp_pending = true; pw_properties_free(props);
pw_proxy_add_proxy_listener(dsp, &sess->listener, &dsp_node_events, sess);
pw_proxy_add_proxy_listener(sess->dsp_proxy, &sess->listener, &dsp_node_events, sess);
} }
else { else {
sess->starting = false; sess->starting = false;