RAVENNAKIT
Loading...
Searching...
No Matches
ravenna_node.hpp
Go to the documentation of this file.
1// SPDX-License-Identifier: AGPL-3.0-or-later
2/*
3 * Project: RAVENNAKIT (RAVENNA / AES67 / ST2110-30 SDK)
4 * Copyright (c) 2024-2025 Sound on Digital
5 *
6 * This file is part of RAVENNAKIT.
7 *
8 * RAVENNAKIT is dual-licensed:
9 * 1) Under the terms of the GNU Affero General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version (the "AGPL License"); and
12 * 2) Under a commercial license from Sound on Digital, for customers who
13 * cannot (or do not wish to) comply with the AGPL License terms.
14 *
15 * If you obtained this file under the AGPL License, you may redistribute it
16 * and/or modify it under the terms of the AGPL License. See the LICENSE
17 * file in the project root for details.
18 *
19 * For commercial licensing, support, and other inquiries, please visit:
20 *
21 * https://ravennakit.com
22 *
23 */
24
25#pragma once
26
27#include "ravenna_browser.hpp"
29#include "ravenna_receiver.hpp"
30#include "ravenna_sender.hpp"
40
41#include <string>
42
43namespace rav {
44
49 public:
63
68 public:
69 ~Subscriber() override = default;
70
75 virtual void ravenna_node_configuration_updated(const Configuration& configuration) {
76 std::ignore = configuration;
77 }
78
84 virtual void ravenna_receiver_added(const RavennaReceiver& receiver) {
85 std::ignore = receiver;
86 }
87
93 virtual void ravenna_receiver_removed(const Id receiver_id) {
94 std::ignore = receiver_id;
95 }
96
102 virtual void ravenna_sender_added(const RavennaSender& sender) {
103 std::ignore = sender;
104 }
105
111 virtual void ravenna_sender_removed(const Id sender_id) {
112 std::ignore = sender_id;
113 }
114
120 std::ignore = config;
121 }
122
128 virtual void nmos_node_status_changed(const nmos::Node::Status status, const nmos::Node::StatusInfo& registry_info) {
129 std::ignore = status;
130 std::ignore = registry_info;
131 }
132
138 std::ignore = config;
139 }
140 };
141
142 explicit RavennaNode();
144
145 // MARK: Receivers
146
152 [[nodiscard]] std::future<tl::expected<Id, std::string>> create_receiver(RavennaReceiver::Configuration initial_config);
153
159 [[nodiscard]] std::future<void> remove_receiver(Id receiver_id);
160
167 [[nodiscard]] std::future<tl::expected<void, std::string>>
169
176 [[nodiscard]] std::future<void> subscribe_to_receiver(Id receiver_id, RavennaReceiver::Subscriber* subscriber);
177
184 [[nodiscard]] std::future<void> unsubscribe_from_receiver(Id receiver_id, RavennaReceiver::Subscriber* subscriber);
185
189 [[nodiscard]] std::optional<uint32_t> read_data_realtime(
190 Id receiver_id, uint8_t* buffer, size_t buffer_size, std::optional<uint32_t> at_timestamp, std::optional<uint32_t> require_delay
191 );
192
196 [[nodiscard]] std::optional<uint32_t> read_audio_data_realtime(
197 Id receiver_id, AudioBufferView<float>& output_buffer, std::optional<uint32_t> at_timestamp, std::optional<uint32_t> require_delay
198 );
199
205 std::future<tl::expected<sdp::SessionDescription, std::string>> get_sdp_for_sender(Id sender_id);
206
213 [[nodiscard]] std::future<std::optional<sdp::SessionDescription>> get_sdp_for_receiver(Id receiver_id);
214
222 [[nodiscard]] std::future<std::optional<std::string>> get_sdp_text_for_receiver(Id receiver_id);
223
224 // MARK: Senders
225
230 [[nodiscard]] std::future<tl::expected<Id, std::string>> create_sender(RavennaSender::Configuration initial_config);
231
237 [[nodiscard]] std::future<void> remove_sender(Id sender_id);
238
245 [[nodiscard]] std::future<tl::expected<void, std::string>>
247
254 [[nodiscard]] std::future<void> subscribe_to_sender(Id sender_id, RavennaSender::Subscriber* subscriber);
255
262 [[nodiscard]] std::future<void> unsubscribe_from_sender(Id sender_id, RavennaSender::Subscriber* subscriber);
263
267 [[nodiscard]] bool send_data_realtime(Id sender_id, BufferView<const uint8_t> buffer, uint32_t timestamp);
268
272 [[nodiscard]] bool send_audio_data_realtime(Id sender_id, const AudioBufferView<const float>& buffer, uint32_t timestamp);
273
274 // MARK: PTP
275
281 [[nodiscard]] std::future<void> subscribe_to_ptp_instance(ptp::Instance::Subscriber* subscriber);
282
288 [[nodiscard]] std::future<void> unsubscribe_from_ptp_instance(ptp::Instance::Subscriber* subscriber);
289
295 [[nodiscard]] std::future<tl::expected<void, std::string>> set_ptp_instance_configuration(ptp::Instance::Configuration update);
296
297 // MARK: NMOS
298
304 [[nodiscard]] std::future<tl::expected<void, std::string>> set_nmos_configuration(nmos::Node::Configuration update);
305
309 std::future<boost::uuids::uuid> get_nmos_device_id();
310
311 // MARK: RavennaNode
312
318 [[nodiscard]] std::future<void> subscribe(Subscriber* subscriber);
319
325 [[nodiscard]] std::future<void> unsubscribe(Subscriber* subscriber);
326
332 [[nodiscard]] std::future<void> set_network_interface_config(NetworkInterfaceConfig interface_config);
333
339 std::future<void> set_configuration(Configuration config);
340
344 [[nodiscard]] bool is_maintenance_thread() const;
345
349 [[nodiscard]] std::future<boost::json::object> to_boost_json();
350
356 [[nodiscard]] std::future<tl::expected<void, std::string>> restore_from_boost_json(const boost::json::value& json);
357
372 template<typename CompletionToken>
373 [[nodiscard]] auto dispatch(CompletionToken&& token) {
374 return boost::asio::dispatch(io_context_, token);
375 }
376
391 template<typename CompletionToken>
392 [[nodiscard]] auto post(CompletionToken&& token) {
393 return boost::asio::post(io_context_, token);
394 }
395
396 private:
397 boost::asio::io_context io_context_;
398 Configuration configuration_;
399 rtp::AudioReceiver rtp_receiver_ {io_context_};
400 rtp::AudioSender rtp_sender_ {io_context_};
401 std::atomic<bool> keep_going_ {true};
402 std::thread network_thread_;
403 std::thread maintenance_thread_;
404 std::thread::id maintenance_thread_id_;
405 Id::Generator id_generator_;
406
407 RavennaBrowser browser_ {io_context_};
408 RavennaRtspClient rtsp_client_ {io_context_, browser_};
409 std::vector<std::unique_ptr<RavennaReceiver>> receivers_;
410
411 std::unique_ptr<dnssd::Advertiser> advertiser_;
412 rtsp::Server rtsp_server_;
413 ptp::Instance ptp_instance_;
414 std::vector<std::unique_ptr<RavennaSender>> senders_;
415
416 nmos::Node nmos_node_ {io_context_, ptp_instance_};
417 nmos::Device nmos_device_;
418
419 SubscriberList<Subscriber> subscribers_;
420 NetworkInterfaceConfig network_interface_config_;
421
422 uint32_t generate_unique_session_id() const;
423 void do_maintenance() const;
424 void update_ravenna_browser();
425};
426
430std::string to_string(const RavennaNode::Configuration& configuration);
431
432} // namespace rav
433
439#define RAV_ASSERT_NODE_MAINTENANCE_THREAD(node) RAV_ASSERT((node).is_maintenance_thread(), "Not on maintenance thread")
A non-owning view of a non-interleaved audio buffer.
A class similar to std::string_view but for raw data buffers.
A class which represents a unique identifier.
Definition id.hpp:38
Baseclass for other classes which need updates on discovered nodes and sessions.
Base class for classes which want to receive updates from the ravenna node.
virtual void network_interface_config_updated(const NetworkInterfaceConfig &config)
Called when the network interface configuration is updated.
~Subscriber() override=default
virtual void ravenna_receiver_added(const RavennaReceiver &receiver)
Called when a receiver is added to the node, or when subscribing.
virtual void ravenna_receiver_removed(const Id receiver_id)
Called when a receiver is removed from the node.
virtual void ravenna_sender_added(const RavennaSender &sender)
Called when a sender is added to the node, or when subscribing.
virtual void nmos_node_config_updated(const nmos::Node::Configuration &config)
Called when the NMOS configuration is updated.
virtual void ravenna_sender_removed(const Id sender_id)
Called when a sender is removed from the node.
virtual void ravenna_node_configuration_updated(const Configuration &configuration)
Called when the configuration of the RavennaNode is updated.
virtual void nmos_node_status_changed(const nmos::Node::Status status, const nmos::Node::StatusInfo &registry_info)
Called when the NMOS node state changed.
std::future< void > subscribe_to_sender(Id sender_id, RavennaSender::Subscriber *subscriber)
Adds a subscriber to the sender with the given id.
auto post(CompletionToken &&token)
Schedules some work on the maintenance thread using asio::post.
std::future< tl::expected< void, std::string > > update_sender_configuration(Id sender_id, RavennaSender::Configuration config)
Updates the configuration of the sender with the given id.
std::future< void > unsubscribe_from_receiver(Id receiver_id, RavennaReceiver::Subscriber *subscriber)
Removes a subscriber from the receiver with the given id.
std::optional< uint32_t > read_audio_data_realtime(Id receiver_id, AudioBufferView< float > &output_buffer, std::optional< uint32_t > at_timestamp, std::optional< uint32_t > require_delay)
Reads the data from the receiver with the given id.
std::future< boost::uuids::uuid > get_nmos_device_id()
std::future< void > remove_sender(Id sender_id)
Removes the sender with the given id.
std::future< void > subscribe(Subscriber *subscriber)
Adds a subscriber to the node.
std::future< void > set_configuration(Configuration config)
Sets the configuration for this node, state will be updated accordingly.
std::future< void > subscribe_to_ptp_instance(ptp::Instance::Subscriber *subscriber)
Adds a subscriber to the PTP instance.
std::future< std::optional< std::string > > get_sdp_text_for_receiver(Id receiver_id)
Get the SDP text for the receiver with the given id.
auto dispatch(CompletionToken &&token)
Schedules some work on the maintenance thread using boost::asio::dispatch.
std::future< void > remove_receiver(Id receiver_id)
Removes the receiver with the given id.
std::future< void > subscribe_to_receiver(Id receiver_id, RavennaReceiver::Subscriber *subscriber)
Adds a subscriber to the receiver with the given id.
std::future< void > set_network_interface_config(NetworkInterfaceConfig interface_config)
Sets the network interfaces to use.
bool send_audio_data_realtime(Id sender_id, const AudioBufferView< const float > &buffer, uint32_t timestamp)
Schedules audio data for sending.
bool is_maintenance_thread() const
std::future< void > unsubscribe_from_sender(Id sender_id, RavennaSender::Subscriber *subscriber)
Removes a subscriber from the sender with the given id.
std::future< tl::expected< sdp::SessionDescription, std::string > > get_sdp_for_sender(Id sender_id)
Get the SDP for the sender with the given id.
std::future< void > unsubscribe(Subscriber *subscriber)
Removes a subscriber from the node.
std::future< tl::expected< void, std::string > > set_nmos_configuration(nmos::Node::Configuration update)
Sets the configuration of the NMOS node.
std::optional< uint32_t > read_data_realtime(Id receiver_id, uint8_t *buffer, size_t buffer_size, std::optional< uint32_t > at_timestamp, std::optional< uint32_t > require_delay)
Reads data from the buffer at the given timestamp.
std::future< boost::json::object > to_boost_json()
std::future< tl::expected< Id, std::string > > create_sender(RavennaSender::Configuration initial_config)
Creates a sender for the given session.
std::future< void > unsubscribe_from_ptp_instance(ptp::Instance::Subscriber *subscriber)
Removes a subscriber from the PTP instance.
std::future< tl::expected< void, std::string > > set_ptp_instance_configuration(ptp::Instance::Configuration update)
Sets the configuration of the PTP instance.
std::future< std::optional< sdp::SessionDescription > > get_sdp_for_receiver(Id receiver_id)
Get the SDP for the receiver with the given id.
std::future< tl::expected< Id, std::string > > create_receiver(RavennaReceiver::Configuration initial_config)
Creates a new receiver for the given session.
std::future< tl::expected< void, std::string > > update_receiver_configuration(Id receiver_id, RavennaReceiver::Configuration config)
Updates the configuration of the receiver with the given id.
bool send_data_realtime(Id sender_id, BufferView< const uint8_t > buffer, uint32_t timestamp)
Schedules data for sending.
std::future< tl::expected< void, std::string > > restore_from_boost_json(const boost::json::value &json)
Restores the node from a JSON representation.
Baseclass for other classes which want to receive changes to the stream.
const char * to_string(const AudioEncoding encoding)
Holds the configuration of the node.
bool enable_dnssd_session_discovery
When true, the RAVENNA node will discover sessions (streams) using dns-sd.
bool enable_dnssd_node_discovery
When true, the RAVENNA node will discover other nodes using dns-sd.
bool enable_dnssd_session_advertisement
When true, the RAVENNA node will advertise senders using dns-sd.
Defines the configuration for the receiver.
The configuration of the NMOS node.
Definition nmos_node.hpp:66
Defines the configuration of the PTP instance (of parameters which need to be persisted).