node: keep better track of driver node

When a session disappears, try to move nodes to another session.
This commit is contained in:
Wim Taymans 2018-05-17 17:40:08 +02:00
parent 1bff5afe05
commit ef9fcd1093
7 changed files with 144 additions and 72 deletions

View file

@ -689,11 +689,9 @@ static int impl_node_process(struct spa_node *node)
struct impl *impl = this->impl;
int status;
impl->client_node->node->driver_node = impl->this.node->driver_node;
impl->ctrl.min_size = impl->ctrl.max_size =
impl->this.node->driver_node->rt.quantum->size;
spa_log_trace(this->log, "%p: process %d", this, impl->ctrl.max_size);
if (impl->use_converter) {
@ -897,8 +895,9 @@ static void client_node_destroy(void *data)
struct impl *impl = data;
pw_log_debug("client-stream %p: destroy", &impl->this);
spa_hook_remove(&impl->client_node_listener);
pw_node_set_driver(impl->client_node->node, NULL);
spa_hook_remove(&impl->client_node_listener);
spa_hook_remove(&impl->node_listener);
pw_node_destroy(impl->this.node);
cleanup(impl);
@ -935,14 +934,22 @@ static void node_destroy(void *data)
pw_log_debug("client-stream %p: destroy", &impl->this);
spa_hook_remove(&impl->node_listener);
spa_hook_remove(&impl->client_node_listener);
pw_client_node_destroy(impl->client_node);
cleanup(impl);
}
static void node_driver_changed(void *data, struct pw_node *driver)
{
struct impl *impl = data;
impl->client_node->node->driver_node = driver;
}
static const struct pw_node_events node_events = {
PW_VERSION_NODE_EVENTS,
.destroy = node_destroy,
.driver_changed = node_driver_changed,
};
/** Create a new client stream

View file

@ -126,6 +126,9 @@ struct link_data {
};
static int handle_autoconnect(struct impl *impl, struct pw_node *node,
const struct pw_properties *props);
/** \endcond */
static void link_data_remove(struct link_data *data)
@ -151,10 +154,17 @@ static void session_destroy(struct session *sess)
spa_list_remove(&sess->l);
spa_hook_remove(&sess->node_listener);
spa_list_for_each_safe(ni, t, &sess->node_list, l)
node_info_free(ni);
if (sess->dsp)
if (sess->dsp) {
spa_hook_remove(&sess->dsp_listener);
pw_node_destroy(sess->dsp);
}
spa_list_for_each_safe(ni, t, &sess->node_list, l) {
pw_node_set_state(ni->node, PW_NODE_STATE_SUSPENDED);
pw_node_set_driver(ni->node, NULL);
handle_autoconnect(ni->impl, ni->node,
pw_node_get_properties(ni->node));
node_info_free(ni);
}
free(sess);
}
@ -306,7 +316,7 @@ static void reconfigure_session(struct session *sess)
sess->node->rt.quantum->rate.num = 1;
sess->node->rt.quantum->rate.denom = sess->sample_rate;
sess->node->rt.quantum->size = buffer_size;
sess->node->rt.quantum->size = sess->buffer_size;
pw_log_info("module %p: driver node:%p quantum:%d/%d",
impl, sess->node, sess->sample_rate, buffer_size);
@ -358,6 +368,8 @@ static int link_session_dsp(struct session *session)
}
pw_link_register(session->link, NULL, pw_module_get_global(impl->module), NULL);
reconfigure_session(session);
return 0;
}
@ -412,7 +424,7 @@ static int find_session(void *data, struct session *sess)
return 0;
}
static void handle_autoconnect(struct impl *impl, struct pw_node *node,
static int handle_autoconnect(struct impl *impl, struct pw_node *node,
const struct pw_properties *props)
{
struct pw_node *peer;
@ -423,6 +435,11 @@ static void handle_autoconnect(struct impl *impl, struct pw_node *node,
struct session *session;
struct node_info *info;
uint32_t sample_rate, buffer_size;
int res;
str = pw_properties_get(props, PW_NODE_PROP_AUTOCONNECT);
if (str == NULL || !pw_properties_parse_bool(str))
return 0;
sample_rate = DEFAULT_SAMPLE_RATE;
@ -455,16 +472,16 @@ static void handle_autoconnect(struct impl *impl, struct pw_node *node,
else if (strcmp(category, "Capture") == 0)
find.media_class = "Audio/Source";
else
return;
return -EINVAL;
}
else if (strcmp(media, "Video") == 0) {
if (strcmp(category, "Capture") == 0)
find.media_class = "Video/Source";
else
return;
return -EINVAL;
}
else
return;
return -EINVAL;
str = pw_properties_get(props, PW_NODE_PROP_TARGET_NODE);
if (str != NULL)
@ -479,7 +496,7 @@ static void handle_autoconnect(struct impl *impl, struct pw_node *node,
spa_list_for_each(session, &impl->session_list, l)
find_session(&find, session);
if (find.sess == NULL)
return;
return -ENOENT;
session = find.sess;
@ -488,24 +505,24 @@ static void handle_autoconnect(struct impl *impl, struct pw_node *node,
else if (strcmp(category, "Playback") == 0)
direction = PW_DIRECTION_INPUT;
else
return;
return -EINVAL;
if (exclusive || session->dsp == NULL) {
if (exclusive && !spa_list_is_empty(&session->node_list)) {
pw_log_warn("session busy, can't get exclusive access");
return;
return -EBUSY;
}
if (session->link != NULL) {
pw_log_warn("session busy with DSP");
return;
return -EBUSY;
}
peer = session->node;
session->exclusive = exclusive;
}
else {
if (session->link == NULL) {
if (link_session_dsp(session) < 0)
return;
if ((res = link_session_dsp(session)) < 0)
return res;
}
peer = session->dsp;
}
@ -520,13 +537,15 @@ static void handle_autoconnect(struct impl *impl, struct pw_node *node,
info->buffer_size = buffer_size;
spa_list_init(&info->links);
spa_list_append(&info->session->node_list, &info->l);
spa_list_append(&session->node_list, &info->l);
pw_node_add_listener(node, &info->node_listener, &node_info_events, info);
pw_node_for_each_port(peer, direction, on_peer_port, info);
reconfigure_session(session);
return 1;
}
static void node_destroy(void *data)
@ -647,9 +666,7 @@ static int on_global(void *data, struct pw_global *global)
properties = pw_node_get_properties(node);
str = pw_properties_get(properties, PW_NODE_PROP_AUTOCONNECT);
if (str != NULL && pw_properties_parse_bool(str)) {
handle_autoconnect(impl, node, properties);
if (handle_autoconnect(impl, node, properties) == 1) {
return 0;
}
else if ((str = pw_properties_get(properties, "media.class")) == NULL)