2 * Copyright 2017 Philippe Proulx <pproulx@efficios.com>
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 #include <babeltrace/babeltrace-internal.h>
24 #include <babeltrace/ctf-ir/clock-class.h>
25 #include <babeltrace/ctf-ir/event.h>
26 #include <babeltrace/graph/clock-class-priority-map.h>
27 #include <babeltrace/graph/component-filter.h>
28 #include <babeltrace/graph/component.h>
29 #include <babeltrace/graph/notification-event.h>
30 #include <babeltrace/graph/notification-inactivity.h>
31 #include <babeltrace/graph/notification-iterator.h>
32 #include <babeltrace/graph/notification.h>
33 #include <babeltrace/graph/port.h>
34 #include <babeltrace/graph/private-component-filter.h>
35 #include <babeltrace/graph/private-component.h>
36 #include <babeltrace/graph/private-component.h>
37 #include <babeltrace/graph/private-connection.h>
38 #include <babeltrace/graph/private-notification-iterator.h>
39 #include <babeltrace/graph/private-port.h>
40 #include <plugins-common.h>
45 /* Array of struct bt_private_notification_iterator * (weak refs) */
46 GPtrArray
*muxer_notif_iters
;
49 struct bt_private_component
*priv_comp
;
50 unsigned int next_port_num
;
51 size_t available_input_ports
;
55 struct muxer_upstream_notif_iter
{
57 struct bt_notification_iterator
*notif_iter
;
60 struct bt_private_port
*priv_port
;
64 struct muxer_notif_iter
{
65 /* Array of struct muxer_upstream_notif_iter * (owned by this) */
66 GPtrArray
*muxer_upstream_notif_iters
;
68 /* Array of struct muxer_upstream_notif_iter * (weak refs) */
69 GPtrArray
*muxer_upstream_notif_iters_retry
;
71 /* Next thing to return by the "next" method */
72 struct bt_notification_iterator_next_return next_next_return
;
73 int64_t next_next_return_ts_ns
;
75 /* Last time returned in a notification */
76 int64_t last_returned_ts_ns
;
80 struct muxer_upstream_notif_iter
*muxer_notif_iter_add_upstream_notif_iter(
81 struct muxer_notif_iter
*muxer_notif_iter
,
82 struct bt_notification_iterator
*notif_iter
,
83 struct bt_private_port
*priv_port
)
85 struct muxer_upstream_notif_iter
*muxer_upstream_notif_iter
=
86 g_new0(struct muxer_upstream_notif_iter
, 1);
88 if (!muxer_upstream_notif_iter
) {
92 muxer_upstream_notif_iter
->notif_iter
= bt_get(notif_iter
);
93 muxer_upstream_notif_iter
->priv_port
= bt_get(priv_port
);
94 g_ptr_array_add(muxer_notif_iter
->muxer_upstream_notif_iters
,
95 muxer_upstream_notif_iter
);
98 return muxer_upstream_notif_iter
;
102 bool muxer_notif_iter_has_upstream_notif_iter_to_retry(
103 struct muxer_notif_iter
*muxer_notif_iter
)
105 assert(muxer_notif_iter
);
106 return muxer_notif_iter
->muxer_upstream_notif_iters_retry
->len
> 0;
110 void muxer_notif_iter_add_upstream_notif_iter_to_retry(
111 struct muxer_notif_iter
*muxer_notif_iter
,
112 struct muxer_upstream_notif_iter
*muxer_upstream_notif_iter
)
114 assert(muxer_notif_iter
);
115 assert(muxer_upstream_notif_iter
);
116 g_ptr_array_add(muxer_notif_iter
->muxer_upstream_notif_iters_retry
,
117 muxer_upstream_notif_iter
);
121 void destroy_muxer_upstream_notif_iter(
122 struct muxer_upstream_notif_iter
*muxer_upstream_notif_iter
)
124 if (!muxer_upstream_notif_iter
) {
128 bt_put(muxer_upstream_notif_iter
->notif_iter
);
129 bt_put(muxer_upstream_notif_iter
->priv_port
);
130 g_free(muxer_upstream_notif_iter
);
134 bool muxer_notif_iter_has_upstream_notif_iter_on_port(
135 struct muxer_notif_iter
*muxer_notif_iter
,
136 struct bt_private_port
*priv_port
)
141 for (i
= 0; i
< muxer_notif_iter
->muxer_upstream_notif_iters
->len
; i
++) {
142 struct muxer_upstream_notif_iter
*muxer_upstream_notif_iter
=
144 muxer_notif_iter
->muxer_upstream_notif_iters
, i
);
146 if (muxer_upstream_notif_iter
->priv_port
== priv_port
) {
157 int ensure_available_input_port(struct bt_private_component
*priv_comp
)
159 struct muxer_comp
*muxer_comp
=
160 bt_private_component_get_user_data(priv_comp
);
162 GString
*port_name
= NULL
;
163 void *priv_port
= NULL
;
167 if (muxer_comp
->available_input_ports
>= 1) {
171 port_name
= g_string_new("in");
177 g_string_append_printf(port_name
, "%u", muxer_comp
->next_port_num
);
178 priv_port
= bt_private_component_filter_add_input_private_port(
179 priv_comp
, port_name
->str
);
185 muxer_comp
->available_input_ports
++;
186 muxer_comp
->next_port_num
++;
190 g_string_free(port_name
, TRUE
);
198 int remove_default_ports(struct bt_private_component
*priv_comp
)
200 struct bt_private_port
*priv_port
;
203 priv_port
= bt_private_component_filter_get_default_input_private_port(
206 ret
= bt_private_port_remove_from_component(priv_port
);
213 priv_port
= bt_private_component_filter_get_default_output_private_port(
216 ret
= bt_private_port_remove_from_component(priv_port
);
228 int create_output_port(struct bt_private_component
*priv_comp
)
233 priv_port
= bt_private_component_filter_add_output_private_port(
244 void destroy_muxer_comp(struct muxer_comp
*muxer_comp
)
250 if (muxer_comp
->muxer_notif_iters
) {
251 g_ptr_array_free(muxer_comp
->muxer_notif_iters
, TRUE
);
258 enum bt_component_status
muxer_init(
259 struct bt_private_component
*priv_comp
,
260 struct bt_value
*params
, void *init_data
)
263 enum bt_component_status status
= BT_COMPONENT_STATUS_OK
;
264 struct muxer_comp
*muxer_comp
= g_new0(struct muxer_comp
, 1);
270 muxer_comp
->muxer_notif_iters
= g_ptr_array_new();
271 if (!muxer_comp
->muxer_notif_iters
) {
275 muxer_comp
->priv_comp
= priv_comp
;
276 ret
= bt_private_component_set_user_data(priv_comp
, muxer_comp
);
278 ret
= remove_default_ports(priv_comp
);
283 ret
= ensure_available_input_port(priv_comp
);
288 ret
= create_output_port(priv_comp
);
296 destroy_muxer_comp(muxer_comp
);
297 ret
= bt_private_component_set_user_data(priv_comp
, NULL
);
299 status
= BT_COMPONENT_STATUS_ERROR
;
306 void muxer_finalize(struct bt_private_component
*priv_comp
)
308 struct muxer_comp
*muxer_comp
=
309 bt_private_component_get_user_data(priv_comp
);
311 destroy_muxer_comp(muxer_comp
);
315 struct bt_notification_iterator
*create_notif_iter_on_input_port(
316 struct bt_private_port
*priv_port
, int *ret
)
318 struct bt_port
*port
= bt_port_from_private_port(priv_port
);
319 struct bt_notification_iterator
*notif_iter
= NULL
;
320 struct bt_private_connection
*priv_conn
= NULL
;
326 assert(bt_port_is_connected(port
));
327 priv_conn
= bt_private_port_get_private_connection(priv_port
);
333 notif_iter
= bt_private_connection_create_notification_iterator(
347 int get_notif_ts_ns(struct muxer_comp
*muxer_comp
,
348 struct bt_notification
*notif
, int64_t last_returned_ts_ns
,
351 struct bt_clock_class_priority_map
*cc_prio_map
= NULL
;
352 struct bt_ctf_clock_class
*clock_class
= NULL
;
353 struct bt_ctf_clock_value
*clock_value
= NULL
;
354 struct bt_ctf_event
*event
= NULL
;
360 switch (bt_notification_get_type(notif
)) {
361 case BT_NOTIFICATION_TYPE_EVENT
:
363 bt_notification_event_get_clock_class_priority_map(
367 case BT_NOTIFICATION_TYPE_INACTIVITY
:
369 bt_notification_event_get_clock_class_priority_map(
374 * All the other notifications have a higher
377 *ts_ns
= last_returned_ts_ns
;
386 * If the clock class priority map is empty, then we consider
387 * that this notification has no time. In this case it's always
390 if (bt_clock_class_priority_map_get_clock_class_count(cc_prio_map
) == 0) {
391 *ts_ns
= last_returned_ts_ns
;
396 bt_clock_class_priority_map_get_highest_priority_clock_class(
402 if (!bt_ctf_clock_class_get_is_absolute(clock_class
)) {
406 switch (bt_notification_get_type(notif
)) {
407 case BT_NOTIFICATION_TYPE_EVENT
:
408 event
= bt_notification_event_get_event(notif
);
413 clock_value
= bt_ctf_event_get_clock_value(event
,
416 case BT_NOTIFICATION_TYPE_INACTIVITY
:
417 clock_value
= bt_notification_inactivity_get_clock_value(
428 ret
= bt_ctf_clock_value_get_value_ns_from_epoch(clock_value
, ts_ns
);
447 enum bt_notification_iterator_status
448 muxer_notif_iter_youngest_upstream_notif_iter(
449 struct muxer_comp
*muxer_comp
,
450 struct muxer_notif_iter
*muxer_notif_iter
,
451 struct muxer_upstream_notif_iter
**muxer_upstream_notif_iter
,
456 int64_t youngest_ts_ns
= INT64_MAX
;
457 enum bt_notification_iterator_status status
=
458 BT_NOTIFICATION_ITERATOR_STATUS_OK
;
461 assert(muxer_notif_iter
);
462 assert(muxer_upstream_notif_iter
);
463 *muxer_upstream_notif_iter
= NULL
;
465 for (i
= 0; i
< muxer_notif_iter
->muxer_upstream_notif_iters
->len
; i
++) {
466 struct bt_notification
*notif
;
467 struct muxer_upstream_notif_iter
*cur_muxer_upstream_notif_iter
=
468 g_ptr_array_index(muxer_notif_iter
->muxer_upstream_notif_iters
, i
);
471 if (!cur_muxer_upstream_notif_iter
->notif_iter
) {
472 /* This upstream notification iterator is done */
476 notif
= bt_notification_iterator_get_notification(
477 cur_muxer_upstream_notif_iter
->notif_iter
);
479 ret
= get_notif_ts_ns(muxer_comp
, notif
,
480 muxer_notif_iter
->last_returned_ts_ns
, ¬if_ts_ns
);
483 *muxer_upstream_notif_iter
= NULL
;
484 status
= BT_NOTIFICATION_ITERATOR_STATUS_ERROR
;
488 if (notif_ts_ns
<= youngest_ts_ns
) {
489 *muxer_upstream_notif_iter
=
490 cur_muxer_upstream_notif_iter
;
491 youngest_ts_ns
= notif_ts_ns
;
492 *ts_ns
= youngest_ts_ns
;
496 if (!*muxer_upstream_notif_iter
) {
497 status
= BT_NOTIFICATION_ITERATOR_STATUS_END
;
506 int muxer_notif_iter_set_next_next_return(struct muxer_comp
*muxer_comp
,
507 struct muxer_notif_iter
*muxer_notif_iter
)
509 struct muxer_upstream_notif_iter
*muxer_upstream_notif_iter
;
510 struct bt_notification
*notif
= NULL
;
511 enum bt_notification_iterator_status notif_iter_status
;
514 if (muxer_notif_iter_has_upstream_notif_iter_to_retry(muxer_notif_iter
)) {
516 * At least one upstream notification iterator to retry:
519 muxer_notif_iter
->next_next_return
.status
=
520 BT_NOTIFICATION_ITERATOR_STATUS_AGAIN
;
521 BT_PUT(muxer_notif_iter
->next_next_return
.notification
);
526 * Pick the current youngest notification and advance this
527 * upstream notification iterator.
530 muxer_notif_iter_youngest_upstream_notif_iter(muxer_comp
,
531 muxer_notif_iter
, &muxer_upstream_notif_iter
,
532 &muxer_notif_iter
->next_next_return_ts_ns
);
533 if (notif_iter_status
== BT_NOTIFICATION_ITERATOR_STATUS_END
) {
534 /* No more active upstream notification iterator */
535 muxer_notif_iter
->next_next_return
.status
=
536 BT_NOTIFICATION_ITERATOR_STATUS_END
;
537 BT_PUT(muxer_notif_iter
->next_next_return
.notification
);
541 if (notif_iter_status
< 0) {
546 assert(muxer_upstream_notif_iter
);
547 notif
= bt_notification_iterator_get_notification(
548 muxer_upstream_notif_iter
->notif_iter
);
550 muxer_notif_iter
->next_next_return
.status
=
551 BT_NOTIFICATION_ITERATOR_STATUS_OK
;
552 BT_MOVE(muxer_notif_iter
->next_next_return
.notification
, notif
);
553 notif_iter_status
= bt_notification_iterator_next(
554 muxer_upstream_notif_iter
->notif_iter
);
555 if (notif_iter_status
< 0) {
560 if (notif_iter_status
== BT_NOTIFICATION_ITERATOR_STATUS_END
) {
561 /* This upstream notification iterator is done */
562 BT_PUT(muxer_upstream_notif_iter
->notif_iter
);
563 goto ensure_monotonic
;
566 assert(notif_iter_status
== BT_NOTIFICATION_ITERATOR_STATUS_OK
||
567 notif_iter_status
== BT_NOTIFICATION_ITERATOR_STATUS_AGAIN
);
569 if (notif_iter_status
== BT_NOTIFICATION_ITERATOR_STATUS_AGAIN
) {
570 muxer_notif_iter_add_upstream_notif_iter_to_retry(
571 muxer_notif_iter
, muxer_upstream_notif_iter
);
576 * Here we have the next "next" return value. It won't change
577 * until it is returned by the next call to our "next" method.
578 * If its time is less than the time of the last notification
579 * that our "next" method returned, then fail because the
580 * muxer's output wouldn't be monotonic.
582 if (muxer_notif_iter
->next_next_return_ts_ns
<
583 muxer_notif_iter
->last_returned_ts_ns
) {
589 * We are now sure that the next "next" return value will not
590 * change until it is returned by this muxer notification
591 * iterator. It is now safe to set the last returned time
594 muxer_notif_iter
->last_returned_ts_ns
=
595 muxer_notif_iter
->next_next_return_ts_ns
;
602 int muxer_notif_iter_update_upstream_notif_iters(struct muxer_comp
*muxer_comp
,
603 struct muxer_notif_iter
*muxer_notif_iter
)
605 struct bt_component
*comp
= NULL
;
610 comp
= bt_component_from_private_component(muxer_comp
->priv_comp
);
612 ret
= bt_component_filter_get_input_port_count(comp
, &count
);
615 for (i
= 0; i
< count
; i
++) {
616 struct bt_private_port
*priv_port
=
617 bt_private_component_filter_get_input_private_port_at_index(
618 muxer_comp
->priv_comp
, i
);
619 struct bt_port
*port
;
620 struct bt_notification_iterator
*upstream_notif_iter
;
621 enum bt_notification_iterator_status next_status
;
622 struct muxer_upstream_notif_iter
*muxer_upstream_notif_iter
;
626 if (muxer_notif_iter_has_upstream_notif_iter_on_port(
627 muxer_notif_iter
, priv_port
)) {
632 port
= bt_port_from_private_port(priv_port
);
634 if (!bt_port_is_connected(port
)) {
641 upstream_notif_iter
= create_notif_iter_on_input_port(priv_port
,
644 assert(!upstream_notif_iter
);
649 next_status
= bt_notification_iterator_next(
650 upstream_notif_iter
);
651 if (next_status
< 0) {
653 bt_put(upstream_notif_iter
);
658 if (next_status
== BT_NOTIFICATION_ITERATOR_STATUS_END
) {
659 /* Already the end: do not even keep it */
661 bt_put(upstream_notif_iter
);
665 assert(next_status
== BT_NOTIFICATION_ITERATOR_STATUS_OK
||
666 next_status
== BT_NOTIFICATION_ITERATOR_STATUS_AGAIN
);
667 muxer_upstream_notif_iter
=
668 muxer_notif_iter_add_upstream_notif_iter(
669 muxer_notif_iter
, upstream_notif_iter
,
671 if (!muxer_upstream_notif_iter
) {
673 bt_put(upstream_notif_iter
);
677 if (next_status
== BT_NOTIFICATION_ITERATOR_STATUS_AGAIN
) {
678 muxer_notif_iter_add_upstream_notif_iter_to_retry(
679 muxer_notif_iter
, muxer_upstream_notif_iter
);
683 bt_put(upstream_notif_iter
);
699 void destroy_muxer_notif_iter(struct muxer_notif_iter
*muxer_notif_iter
)
701 if (!muxer_notif_iter
) {
705 if (muxer_notif_iter
->muxer_upstream_notif_iters
) {
707 muxer_notif_iter
->muxer_upstream_notif_iters
, TRUE
);
710 if (muxer_notif_iter
->muxer_upstream_notif_iters_retry
) {
712 muxer_notif_iter
->muxer_upstream_notif_iters_retry
,
716 g_free(muxer_notif_iter
);
720 enum bt_notification_iterator_status
muxer_notif_iter_init(
721 struct bt_private_notification_iterator
*priv_notif_iter
,
722 struct bt_private_port
*output_priv_port
)
724 struct muxer_comp
*muxer_comp
= NULL
;
725 struct muxer_notif_iter
*muxer_notif_iter
= NULL
;
726 struct bt_private_component
*priv_comp
= NULL
;
727 enum bt_notification_iterator_status status
=
728 BT_NOTIFICATION_ITERATOR_STATUS_OK
;
731 priv_comp
= bt_private_notification_iterator_get_private_component(
734 muxer_comp
= bt_private_component_get_user_data(priv_comp
);
736 muxer_notif_iter
= g_new0(struct muxer_notif_iter
, 1);
737 if (!muxer_notif_iter
) {
741 muxer_notif_iter
->last_returned_ts_ns
= INT64_MIN
;
742 muxer_notif_iter
->muxer_upstream_notif_iters
=
743 g_ptr_array_new_with_free_func(
744 (GDestroyNotify
) destroy_muxer_upstream_notif_iter
);
745 if (!muxer_notif_iter
->muxer_upstream_notif_iters
) {
749 muxer_notif_iter
->muxer_upstream_notif_iters_retry
= g_ptr_array_new();
750 if (!muxer_notif_iter
->muxer_upstream_notif_iters_retry
) {
755 * Initial upstream notification iterator update: this creates
756 * one upstream notification iterator for each connected port
757 * without an upstream notification iterator (for this muxer
758 * notification iterator).
760 * At this point the next "next" return value is not set yet.
762 ret
= muxer_notif_iter_update_upstream_notif_iters(muxer_comp
,
769 * Set the initial "next" return value.
771 ret
= muxer_notif_iter_set_next_next_return(muxer_comp
,
777 ret
= bt_private_notification_iterator_set_user_data(priv_notif_iter
,
780 g_ptr_array_add(muxer_comp
->muxer_notif_iters
, muxer_notif_iter
);
784 destroy_muxer_notif_iter(muxer_notif_iter
);
785 ret
= bt_private_notification_iterator_set_user_data(priv_notif_iter
,
788 status
= BT_NOTIFICATION_ITERATOR_STATUS_ERROR
;
796 void muxer_notif_iter_finalize(
797 struct bt_private_notification_iterator
*priv_notif_iter
)
799 struct muxer_notif_iter
*muxer_notif_iter
=
800 bt_private_notification_iterator_get_user_data(priv_notif_iter
);
801 struct bt_private_component
*priv_comp
= NULL
;
802 struct muxer_comp
*muxer_comp
= NULL
;
804 priv_comp
= bt_private_notification_iterator_get_private_component(
807 muxer_comp
= bt_private_component_get_user_data(priv_comp
);
810 (void) g_ptr_array_remove_fast(muxer_comp
->muxer_notif_iters
,
812 destroy_muxer_notif_iter(muxer_notif_iter
);
819 struct bt_notification_iterator_next_return
muxer_notif_iter_next(
820 struct bt_private_notification_iterator
*priv_notif_iter
)
822 struct bt_notification_iterator_next_return next_ret
= {
823 .notification
= NULL
,
825 struct muxer_notif_iter
*muxer_notif_iter
=
826 bt_private_notification_iterator_get_user_data(priv_notif_iter
);
827 struct bt_private_component
*priv_comp
= NULL
;
828 struct muxer_comp
*muxer_comp
= NULL
;
832 assert(muxer_notif_iter
);
833 priv_comp
= bt_private_notification_iterator_get_private_component(
836 muxer_comp
= bt_private_component_get_user_data(priv_comp
);
839 /* Are we in an error state set elsewhere? */
840 if (unlikely(muxer_comp
->error
)) {
845 * If we have upstream notification iterators to retry, retry
846 * them now. Each one we find which now has a notification or
847 * is in "end" state, we set it to NULL in this array. Then
848 * we remove all the NULL values from this array.
850 for (i
= 0; i
< muxer_notif_iter
->muxer_upstream_notif_iters_retry
->len
; i
++) {
851 struct muxer_upstream_notif_iter
*muxer_upstream_notif_iter
=
852 g_ptr_array_index(muxer_notif_iter
->muxer_upstream_notif_iters_retry
, i
);
853 enum bt_notification_iterator_status status
;
855 assert(muxer_upstream_notif_iter
->notif_iter
);
856 status
= bt_notification_iterator_next(
857 muxer_upstream_notif_iter
->notif_iter
);
860 * Technically we have a next "next" return
861 * value which is ready for this call, but we're
862 * failing within this call, so discard this
868 if (status
== BT_NOTIFICATION_ITERATOR_STATUS_END
) {
870 * This upstream notification iterator is done.
871 * Set it to NULL so that it's removed later.
873 g_ptr_array_index(muxer_notif_iter
->muxer_upstream_notif_iters_retry
,
875 BT_PUT(muxer_upstream_notif_iter
->notif_iter
);
879 assert(status
== BT_NOTIFICATION_ITERATOR_STATUS_OK
||
880 status
== BT_NOTIFICATION_ITERATOR_STATUS_AGAIN
);
882 if (status
== BT_NOTIFICATION_ITERATOR_STATUS_OK
) {
884 * This upstream notification iterator now has.
885 * a notification. Remove it from this array.
887 g_ptr_array_index(muxer_notif_iter
->muxer_upstream_notif_iters_retry
,
894 * Remove NULL values from the array of upstream notification
895 * iterators to retry.
897 while (g_ptr_array_remove_fast(
898 muxer_notif_iter
->muxer_upstream_notif_iters_retry
, NULL
));
900 /* Take our next "next" next return value */
901 next_ret
= muxer_notif_iter
->next_next_return
;
902 muxer_notif_iter
->next_next_return
.status
=
903 BT_NOTIFICATION_ITERATOR_STATUS_ERROR
;
904 muxer_notif_iter
->next_next_return
.notification
= NULL
;
906 /* Set the next "next" return value */
907 ret
= muxer_notif_iter_set_next_next_return(muxer_comp
,
916 BT_PUT(next_ret
.notification
);
917 next_ret
.status
= BT_NOTIFICATION_ITERATOR_STATUS_ERROR
;
925 void muxer_port_connected(
926 struct bt_private_component
*priv_comp
,
927 struct bt_private_port
*self_private_port
,
928 struct bt_port
*other_port
)
930 struct bt_port
*self_port
=
931 bt_port_from_private_port(self_private_port
);
932 struct muxer_comp
*muxer_comp
=
933 bt_private_component_get_user_data(priv_comp
);
940 if (bt_port_get_type(self_port
) == BT_PORT_TYPE_INPUT
) {
943 /* One less available input port */
944 muxer_comp
->available_input_ports
--;
945 ret
= ensure_available_input_port(priv_comp
);
947 muxer_comp
->error
= true;
952 for (i
= 0; i
< muxer_comp
->muxer_notif_iters
->len
; i
++) {
953 struct muxer_notif_iter
*muxer_notif_iter
=
954 g_ptr_array_index(muxer_comp
->muxer_notif_iters
, i
);
957 * Here we update the list of upstream notification
958 * iterators, but we do NOT call
959 * muxer_notif_iter_set_next_next_return() because we
960 * already have a next "next" return value at this point
961 * (right after the muxer notification iterator
962 * initialization, and always after).
964 ret
= muxer_notif_iter_update_upstream_notif_iters(muxer_comp
,
967 muxer_comp
->error
= true;
977 void muxer_port_disconnected(struct bt_private_component
*priv_comp
,
978 struct bt_private_port
*priv_port
)
980 struct bt_port
*port
= bt_port_from_private_port(priv_port
);
981 struct muxer_comp
*muxer_comp
=
982 bt_private_component_get_user_data(priv_comp
);
987 if (bt_port_get_type(port
) == BT_PORT_TYPE_INPUT
) {
988 /* One more available input port */
989 muxer_comp
->available_input_ports
++;