+
+BT_HIDDEN
+void bt_component_set_graph(struct bt_component *component,
+ struct bt_graph *graph)
+{
+ struct bt_object *parent = bt_object_get_parent(&component->base);
+
+ assert(!parent || parent == &graph->base);
+ if (!parent) {
+ bt_object_set_parent(component, &graph->base);
+ }
+ bt_put(parent);
+}
+
+struct bt_graph *bt_component_get_graph(
+ struct bt_component *component)
+{
+ return (struct bt_graph *) bt_object_get_parent(&component->base);
+}
+
+static
+struct bt_port *bt_component_get_port(GPtrArray *ports, const char *name)
+{
+ size_t i;
+ struct bt_port *ret_port = NULL;
+
+ assert(name);
+
+ for (i = 0; i < ports->len; i++) {
+ struct bt_port *port = g_ptr_array_index(ports, i);
+ const char *port_name = bt_port_get_name(port);
+
+ if (!port_name) {
+ continue;
+ }
+
+ if (!strcmp(name, port_name)) {
+ ret_port = bt_get(port);
+ break;
+ }
+ }
+
+ return ret_port;
+}
+
+BT_HIDDEN
+struct bt_port *bt_component_get_input_port(struct bt_component *comp,
+ const char *name)
+{
+ assert(comp);
+
+ return bt_component_get_port(comp->input_ports, name);
+}
+
+BT_HIDDEN
+struct bt_port *bt_component_get_output_port(struct bt_component *comp,
+ const char *name)
+{
+ assert(comp);
+
+ return bt_component_get_port(comp->output_ports, name);
+}
+
+static
+struct bt_port *bt_component_get_port_at_index(GPtrArray *ports, int index)
+{
+ struct bt_port *port = NULL;
+
+ if (index < 0 || index >= ports->len) {
+ goto end;
+ }
+
+ port = bt_get(g_ptr_array_index(ports, index));
+end:
+ return port;
+}
+
+BT_HIDDEN
+struct bt_port *bt_component_get_input_port_at_index(struct bt_component *comp,
+ int index)
+{
+ assert(comp);
+
+ return bt_component_get_port_at_index(comp->input_ports, index);
+}
+
+BT_HIDDEN
+struct bt_port *bt_component_get_output_port_at_index(struct bt_component *comp,
+ int index)
+{
+ assert(comp);
+
+ return bt_component_get_port_at_index(comp->output_ports, index);
+}
+
+BT_HIDDEN
+struct bt_port *bt_component_add_input_port(
+ struct bt_component *component, const char *name)
+{
+ return bt_component_add_port(component, component->input_ports,
+ BT_PORT_TYPE_INPUT, name);
+}
+
+BT_HIDDEN
+struct bt_port *bt_component_add_output_port(
+ struct bt_component *component, const char *name)
+{
+ return bt_component_add_port(component, component->output_ports,
+ BT_PORT_TYPE_OUTPUT, name);
+}
+
+static
+void bt_component_remove_port_at_index(struct bt_component *component,
+ GPtrArray *ports, size_t index)
+{
+ struct bt_port *port;
+
+ assert(ports);
+ assert(index < ports->len);
+ port = g_ptr_array_index(ports, index);
+
+ /* Disconnect both ports of this port's connection, if any */
+ if (port->connection) {
+ bt_connection_disconnect_ports(port->connection, component);
+ }
+
+ /* Remove from parent's array of ports (weak refs) */
+ g_ptr_array_remove_index(ports, index);
+
+ /* Detach port from its component parent */
+ BT_PUT(port->base.parent);
+
+ // TODO: notify graph user: component's port removed
+}
+
+BT_HIDDEN
+enum bt_component_status bt_component_remove_port(
+ struct bt_component *component, struct bt_port *port)
+{
+ size_t i;
+ enum bt_component_status status = BT_COMPONENT_STATUS_OK;
+ GPtrArray *ports = NULL;
+
+ if (!component || !port) {
+ status = BT_COMPONENT_STATUS_INVALID;
+ goto end;
+ }
+
+ if (bt_port_get_type(port) == BT_PORT_TYPE_INPUT) {
+ ports = component->input_ports;
+ } else if (bt_port_get_type(port) == BT_PORT_TYPE_OUTPUT) {
+ ports = component->output_ports;
+ }
+
+ assert(ports);
+
+ for (i = 0; i < ports->len; i++) {
+ struct bt_port *cur_port = g_ptr_array_index(ports, i);
+
+ if (cur_port == port) {
+ bt_component_remove_port_at_index(component,
+ ports, i);
+ goto end;
+ }
+ }
+
+ status = BT_COMPONENT_STATUS_NOT_FOUND;
+end:
+ return status;
+}
+
+BT_HIDDEN
+enum bt_component_status bt_component_accept_port_connection(
+ struct bt_component *comp, struct bt_port *port)
+{
+ enum bt_component_status status = BT_COMPONENT_STATUS_OK;
+
+ assert(comp);
+ assert(port);
+
+ if (comp->class->methods.accept_port_connection) {
+ status = comp->class->methods.accept_port_connection(
+ comp, port);
+ }
+
+ return status;
+}
+
+BT_HIDDEN
+void bt_component_port_disconnected(struct bt_component *comp,
+ struct bt_port *port)
+{
+ assert(comp);
+ assert(port);
+
+ if (comp->class->methods.port_disconnected) {
+ comp->class->methods.port_disconnected(comp, port);
+ }
+}