- int ret = 0;
- struct bt_notification *packet_end_notif = NULL;
-
- if (!is_subscribed_to_notification_type(iterator,
- BT_NOTIFICATION_TYPE_PACKET_END)) {
- BT_LOGV("Not adding \"push packet end notification\" action: "
- "notification iterator is not subscribed: addr=%p",
- iterator);
- goto end;
- }
-
- assert(packet);
- packet_end_notif = bt_notification_packet_end_create(packet);
- if (!packet_end_notif) {
- BT_LOGE_STR("Cannot create packet end notification.");
- goto error;
- }
-
- add_action_push_notif(iterator, packet_end_notif);
- BT_LOGV("Added \"push packet end notification\" action: "
- "packet-addr=%p", packet);
- goto end;
-
-error:
- ret = -1;
-
-end:
- bt_put(packet_end_notif);
- return ret;
-}
-
-static
-void add_action_set_stream_state_is_ended(
- struct bt_notification_iterator *iterator,
- struct stream_state *stream_state)
-{
- struct action action = {
- .type = ACTION_TYPE_SET_STREAM_STATE_IS_ENDED,
- .payload.set_stream_state_is_ended = {
- .stream_state = stream_state,
- },
- };
-
- assert(stream_state);
- add_action(iterator, &action);
- BT_LOGV("Added \"set stream state's ended\" action: "
- "stream-state-addr=%p", stream_state);
-}
-
-static
-void add_action_set_stream_state_cur_packet(
- struct bt_notification_iterator *iterator,
- struct stream_state *stream_state,
- struct bt_ctf_packet *packet)
-{
- struct action action = {
- .type = ACTION_TYPE_SET_STREAM_STATE_CUR_PACKET,
- .payload.set_stream_state_cur_packet = {
- .stream_state = stream_state,
- .packet = bt_get(packet),
- },
- };
-
- assert(stream_state);
- add_action(iterator, &action);
- BT_LOGV("Added \"set stream state's current packet\" action: "
- "stream-state-addr=%p, packet-addr=%p",
- stream_state, packet);
-}
-
-static
-int ensure_stream_state_exists(struct bt_notification_iterator *iterator,
- struct bt_notification *stream_begin_notif,
- struct bt_ctf_stream *notif_stream,
- struct stream_state **stream_state)
-{
- int ret = 0;
-
- if (!notif_stream) {
- /*
- * The notification does not reference any stream: no
- * need to get or create a stream state.
- */
- goto end;
- }
-
- *stream_state = g_hash_table_lookup(iterator->stream_states,
- notif_stream);
- if (!*stream_state) {
- /*
- * This iterator did not bump into this stream yet:
- * create a stream state and a "stream begin"
- * notification.
- */
- struct action action = {
- .type = ACTION_TYPE_ADD_STREAM_STATE,
- .payload.add_stream_state = {
- .stream = bt_get(notif_stream),
- .stream_state = NULL,
- },
- };
-
- *stream_state = create_stream_state(notif_stream);
- if (!stream_state) {
- BT_LOGE_STR("Cannot create stream state.");
- goto error;
- }
-
- action.payload.add_stream_state.stream_state =
- *stream_state;
- add_action(iterator, &action);
-
- if (stream_begin_notif) {
- add_action_push_notif(iterator, stream_begin_notif);
- } else {
- ret = add_action_push_notif_stream_begin(iterator,
- notif_stream);
- if (ret) {
- BT_LOGE_STR("Cannot add \"push stream beginning notification\" action.");
- goto error;
- }
- }
- }
-
- goto end;
-
-error:
- destroy_stream_state(*stream_state);
- ret = -1;
-
-end:
- return ret;
-}
-
-static
-int handle_packet_switch(struct bt_notification_iterator *iterator,
- struct bt_notification *packet_begin_notif,
- struct bt_ctf_packet *new_packet,
- struct stream_state *stream_state)
-{
- int ret = 0;
-
- if (stream_state->cur_packet == new_packet) {
- goto end;
- }
-
- BT_LOGV("Handling packet switch: "
- "cur-packet-addr=%p, new-packet-addr=%p",
- stream_state->cur_packet, new_packet);
-
- if (stream_state->cur_packet) {
- /* End of the current packet */
- ret = add_action_push_notif_packet_end(iterator,
- stream_state->cur_packet);
- if (ret) {
- BT_LOGE_STR("Cannot add \"push packet end notification\" action.");
- goto error;
- }
- }
-
- /* Beginning of the new packet */
- if (packet_begin_notif) {
- add_action_push_notif(iterator, packet_begin_notif);
- } else if (new_packet) {
- ret = add_action_push_notif_packet_begin(iterator,
- new_packet);
- if (ret) {
- BT_LOGE_STR("Cannot add \"push packet beginning notification\" action.");
- goto error;
- }
- }
-
- add_action_set_stream_state_cur_packet(iterator, stream_state,
- new_packet);
- goto end;
-
-error:
- ret = -1;
-
-end:
- return ret;
-}
-
-static
-int handle_notif_stream_begin(
- struct bt_notification_iterator *iterator,
- struct bt_notification *notif,
- struct bt_ctf_stream *notif_stream)
-{
- int ret = 0;
- struct stream_state *stream_state;
-
- assert(notif->type == BT_NOTIFICATION_TYPE_STREAM_BEGIN);
- assert(notif_stream);
- ret = ensure_stream_state_exists(iterator, notif, notif_stream,
- &stream_state);
- if (ret) {
- BT_LOGE_STR("Cannot ensure that stream state exists.");
- goto error;
- }
-
- goto end;
-
-error:
- ret = -1;
-
-end:
- return ret;
-}
-
-static
-int handle_notif_stream_end(
- struct bt_notification_iterator *iterator,
- struct bt_notification *notif,
- struct bt_ctf_stream *notif_stream)
-{
- int ret = 0;
- struct stream_state *stream_state;
-
- assert(notif->type == BT_NOTIFICATION_TYPE_STREAM_END);
- assert(notif_stream);
- ret = ensure_stream_state_exists(iterator, NULL, notif_stream,
- &stream_state);
- if (ret) {
- BT_LOGE_STR("Cannot ensure that stream state exists.");
- goto error;
- }
-
- ret = handle_packet_switch(iterator, NULL, NULL, stream_state);
- if (ret) {
- BT_LOGE_STR("Cannot handle packet switch.");
- goto error;
+ enum bt_notification_iterator_status status;
+ struct bt_notification_iterator_output_port *out_port_iter =
+ (void *) iterator;
+ enum bt_graph_status graph_status;
+
+ BT_ASSERT_PRE_NON_NULL(iterator, "Notification iterator");
+ BT_ASSERT_PRE_NON_NULL(user_notif, "Notification");
+ BT_ASSERT_PRE(iterator->type ==
+ BT_NOTIFICATION_ITERATOR_TYPE_OUTPUT_PORT,
+ "Notification iterator was not created from an output port: "
+ "%!+i", iterator);
+ BT_LIB_LOGD("Getting next output port notification iterator's notification: %!+i",
+ iterator);
+ graph_status = bt_graph_consume_sink_no_check(
+ out_port_iter->graph, out_port_iter->colander);
+ switch (graph_status) {
+ case BT_GRAPH_STATUS_CANCELED:
+ BT_ASSERT(!out_port_iter->notif);
+ status = BT_NOTIFICATION_ITERATOR_STATUS_CANCELED;
+ break;
+ case BT_GRAPH_STATUS_AGAIN:
+ BT_ASSERT(!out_port_iter->notif);
+ status = BT_NOTIFICATION_ITERATOR_STATUS_AGAIN;
+ break;
+ case BT_GRAPH_STATUS_END:
+ BT_ASSERT(!out_port_iter->notif);
+ status = BT_NOTIFICATION_ITERATOR_STATUS_END;
+ break;
+ case BT_GRAPH_STATUS_NOMEM:
+ BT_ASSERT(!out_port_iter->notif);
+ status = BT_NOTIFICATION_ITERATOR_STATUS_NOMEM;
+ break;
+ case BT_GRAPH_STATUS_OK:
+ BT_ASSERT(out_port_iter->notif);
+ status = BT_NOTIFICATION_ITERATOR_STATUS_OK;
+ *user_notif = out_port_iter->notif;
+ out_port_iter->notif = NULL;
+ break;
+ default:
+ /* Other errors */
+ status = BT_NOTIFICATION_ITERATOR_STATUS_ERROR;