From f3dfe61aa0a4fa53c4ad6c769ad86ab54702745a Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Wed, 3 Oct 2018 19:29:11 +0200 Subject: [PATCH] link: add link state and error to info Notify when state changes --- .../module-protocol-native/protocol-native.c | 4 + src/pipewire/introspect.c | 8 ++ src/pipewire/introspect.h | 7 +- src/pipewire/link.c | 79 +++++++++++-------- src/pipewire/private.h | 3 - src/tools/pipewire-monitor.c | 9 ++- 6 files changed, 68 insertions(+), 42 deletions(-) diff --git a/src/modules/module-protocol-native/protocol-native.c b/src/modules/module-protocol-native/protocol-native.c index b92dbac7c..5ecd9794d 100644 --- a/src/modules/module-protocol-native/protocol-native.c +++ b/src/modules/module-protocol-native/protocol-native.c @@ -1034,6 +1034,8 @@ static void link_marshal_info(void *object, struct pw_link_info *info) "i", info->output_port_id, "i", info->input_node_id, "i", info->input_port_id, + "i", info->state, + "s", info->error, "P", info->format, "i", n_items, NULL); @@ -1064,6 +1066,8 @@ static int link_demarshal_info(void *object, void *data, size_t size) "i", &info.output_port_id, "i", &info.input_node_id, "i", &info.input_port_id, + "i", &info.state, + "s", &info.error, "P", &info.format, "i", &props.n_items, NULL) < 0) return -EINVAL; diff --git a/src/pipewire/introspect.c b/src/pipewire/introspect.c index df3275f10..f543c9a2f 100644 --- a/src/pipewire/introspect.c +++ b/src/pipewire/introspect.c @@ -399,6 +399,12 @@ struct pw_link_info *pw_link_info_update(struct pw_link_info *info, info->input_node_id = update->input_node_id; info->input_port_id = update->input_port_id; } + if (update->change_mask & PW_LINK_CHANGE_MASK_STATE) { + info->state = update->state; + if (info->error) + free((void *) info->error); + info->error = update->error ? strdup(update->error) : NULL; + } if (update->change_mask & PW_LINK_CHANGE_MASK_FORMAT) { if (info->format) free(info->format); @@ -414,6 +420,8 @@ struct pw_link_info *pw_link_info_update(struct pw_link_info *info, void pw_link_info_free(struct pw_link_info *info) { + if (info->error) + free((void *) info->error); if (info->format) free(info->format); if (info->props) diff --git a/src/pipewire/introspect.h b/src/pipewire/introspect.h index b16a8e07f..477ab5d6a 100644 --- a/src/pipewire/introspect.h +++ b/src/pipewire/introspect.h @@ -204,13 +204,16 @@ struct pw_link_info { uint32_t id; /**< id of the global */ #define PW_LINK_CHANGE_MASK_OUTPUT (1 << 0) #define PW_LINK_CHANGE_MASK_INPUT (1 << 1) -#define PW_LINK_CHANGE_MASK_FORMAT (1 << 2) -#define PW_LINK_CHANGE_MASK_PROPS (1 << 3) +#define PW_LINK_CHANGE_MASK_STATE (1 << 2) +#define PW_LINK_CHANGE_MASK_FORMAT (1 << 4) +#define PW_LINK_CHANGE_MASK_PROPS (1 << 4) uint64_t change_mask; /**< bitfield of changed fields since last call */ uint32_t output_node_id; /**< server side output node id */ uint32_t output_port_id; /**< output port id */ uint32_t input_node_id; /**< server side input node id */ uint32_t input_port_id; /**< input port id */ + enum pw_link_state state; /**< the current state of the link */ + const char *error; /**< an error reason if \a state is error */ struct spa_pod *format; /**< format over link */ struct spa_dict *props; /**< the properties of the link */ }; diff --git a/src/pipewire/link.c b/src/pipewire/link.c index 33dacc86a..ce3da33a9 100644 --- a/src/pipewire/link.c +++ b/src/pipewire/link.c @@ -88,44 +88,53 @@ static void debug_link(struct pw_link *link) static void pw_link_update_state(struct pw_link *link, enum pw_link_state state, char *error) { - enum pw_link_state old = link->state; + enum pw_link_state old = link->info.state; + struct pw_node *in = link->input->node, *out = link->output->node; + struct pw_resource *resource; - if (state != old) { - struct pw_node *in = link->input->node, *out = link->output->node; + if (state == old) + return; - if (state == PW_LINK_STATE_ERROR) { - pw_log_error("link %p: update state %s -> error (%s)", link, - pw_link_state_as_string(old), error); - } else { - pw_log_debug("link %p: update state %s -> %s", link, - pw_link_state_as_string(old), pw_link_state_as_string(state)); - } - link->state = state; - if (link->error) - free(link->error); - link->error = error; + if (state == PW_LINK_STATE_ERROR) { + pw_log_error("link %p: update state %s -> error (%s)", link, + pw_link_state_as_string(old), error); + } else { + pw_log_debug("link %p: update state %s -> %s", link, + pw_link_state_as_string(old), pw_link_state_as_string(state)); + } - pw_link_events_state_changed(link, old, state, error); + link->info.state = state; + if (link->info.error) + free((char*)link->info.error); + link->info.error = error; - debug_link(link); + pw_link_events_state_changed(link, old, state, error); - if (old != PW_LINK_STATE_PAUSED && state == PW_LINK_STATE_PAUSED) { - if (++out->n_ready_output_links == out->n_used_output_links) - pw_node_set_state(out, PW_NODE_STATE_RUNNING); - if (++in->n_ready_input_links == in->n_used_input_links) - pw_node_set_state(in, PW_NODE_STATE_RUNNING); - pw_link_activate(link); - } - else if (old == PW_LINK_STATE_PAUSED && state < PW_LINK_STATE_PAUSED) { - if (--out->n_ready_output_links == 0 && - out->n_ready_input_links == 0) - pw_node_set_state(out, PW_NODE_STATE_IDLE); - if (--in->n_ready_input_links == 0 && - in->n_ready_output_links == 0) - pw_node_set_state(in, PW_NODE_STATE_IDLE); - } + link->info.change_mask |= PW_LINK_CHANGE_MASK_STATE; + pw_link_events_info_changed(link, &link->info); + spa_list_for_each(resource, &link->resource_list, link) + pw_link_resource_info(resource, &link->info); + + link->info.change_mask = 0; + + debug_link(link); + + if (old != PW_LINK_STATE_PAUSED && state == PW_LINK_STATE_PAUSED) { + if (++out->n_ready_output_links == out->n_used_output_links) + pw_node_set_state(out, PW_NODE_STATE_RUNNING); + if (++in->n_ready_input_links == in->n_used_input_links) + pw_node_set_state(in, PW_NODE_STATE_RUNNING); + pw_link_activate(link); + } + else if (old == PW_LINK_STATE_PAUSED && state < PW_LINK_STATE_PAUSED) { + if (--out->n_ready_output_links == 0 && + out->n_ready_input_links == 0) + pw_node_set_state(out, PW_NODE_STATE_IDLE); + if (--in->n_ready_input_links == 0 && + in->n_ready_output_links == 0) + pw_node_set_state(in, PW_NODE_STATE_IDLE); } } @@ -852,14 +861,14 @@ int pw_link_activate(struct pw_link *this) { struct impl *impl = SPA_CONTAINER_OF(this, struct impl, this); - pw_log_debug("link %p: activate %d %d", this, impl->activated, this->state); + pw_log_debug("link %p: activate %d %d", this, impl->activated, this->info.state); if (impl->activated) return 0; pw_link_prepare(this); - if (this->state == PW_LINK_STATE_PAUSED) { + if (this->info.state == PW_LINK_STATE_PAUSED) { pw_loop_invoke(this->output->node->data_loop, do_activate_link, SPA_ID_INVALID, NULL, 0, false, this); impl->activated = true; @@ -874,7 +883,7 @@ static int check_states(struct pw_link *this, void *user_data, int res) struct pw_port *input, *output; int in_mix_state, out_mix_state; - if (this->state == PW_LINK_STATE_ERROR) + if (this->info.state == PW_LINK_STATE_ERROR) return -EIO; input = this->input; @@ -1318,7 +1327,7 @@ struct pw_link *pw_link_new(struct pw_core *core, this->core = core; this->properties = properties; - this->state = PW_LINK_STATE_INIT; + this->info.state = PW_LINK_STATE_INIT; this->input = input; this->output = output; diff --git a/src/pipewire/private.h b/src/pipewire/private.h index 3c7961c8c..7661e204d 100644 --- a/src/pipewire/private.h +++ b/src/pipewire/private.h @@ -462,9 +462,6 @@ struct pw_link { struct pw_properties *properties; /**< extra link properties */ bool feedback; - enum pw_link_state state; /**< link state */ - char *error; /**< error message when state error */ - struct spa_list resource_list; /**< list of bound resources */ struct spa_io_buffers *io; /**< link io area */ diff --git a/src/tools/pipewire-monitor.c b/src/tools/pipewire-monitor.c index 8474afaf7..c9ed8c373 100644 --- a/src/tools/pipewire-monitor.c +++ b/src/tools/pipewire-monitor.c @@ -426,12 +426,17 @@ static void link_event_info(void *object, struct pw_link_info *info) printf("%c\toutput-port-id: %u\n", MARK_CHANGE(0), info->output_port_id); printf("%c\tinput-node-id: %u\n", MARK_CHANGE(1), info->input_node_id); printf("%c\tinput-port-id: %u\n", MARK_CHANGE(1), info->input_port_id); - printf("%c\tformat:\n", MARK_CHANGE(2)); + printf("%c\tstate: \"%s\"", MARK_CHANGE(2), pw_link_state_as_string(info->state)); + if (info->state == PW_LINK_STATE_ERROR && info->error) + printf(" \"%s\"\n", info->error); + else + printf("\n"); + printf("%c\tformat:\n", MARK_CHANGE(3)); if (info->format) spa_debug_format(2, NULL, info->format); else printf("\t\tnone\n"); - print_properties(info->props, MARK_CHANGE(3)); + print_properties(info->props, MARK_CHANGE(4)); } }