diff --git a/README.md b/README.md index 78a291f..b3b0757 100644 --- a/README.md +++ b/README.md @@ -50,7 +50,7 @@ The daemon can be cross-compiled for multiple platforms and implements the follo * control and configuration of up to 64 multicast and unicast sources and sinks using the ALSA RAVENNA/AES67 driver via netlink * session handling and SDP parsing and creation * HTTP REST API for the daemon control and configuration -* SAP sources discovery and advertisement compatible with AES67 standard +* SAP sources discovery, update and advertisement compatible with AES67 standard * mDNS sources discovery and advertisement (using Linux Avahi) compatible with Ravenna standard * RTSP client and server to retrieve, return and update SDP files via DESCRIBE and ANNOUNCE methods according to Ravenna standard * IGMP handling for SAP, PTP and RTP sessions diff --git a/daemon/README.md b/daemon/README.md index b16a126..08b7c05 100644 --- a/daemon/README.md +++ b/daemon/README.md @@ -12,6 +12,7 @@ The daemon is responsible for: * mDNS sources discovery and advertisement (using Linux Avahi) compatible with Ravenna standard * RTSP client and server to retrieve, return and update SDP files via DESCRIBE and ANNOUNCE methods according to Ravenna standard * IGMP handling for SAP, PTP and RTP sessions +* automatic update of Sinks based on discovered mDNS/SAP remote sources ## Configuration file ## @@ -187,7 +188,8 @@ Example "ip_addr": "127.0.0.1", "node_id": "AES67 daemon d9aca383", "custom_node_id": "", - "ptp_status_script": "./scripts/ptp_status.sh" + "ptp_status_script": "./scripts/ptp_status.sh", + "auto_sinks_update": true } where: @@ -269,6 +271,10 @@ where: > JSON string specifying the unique node identifier used to identify mDNS, SAP and SDP services announced by the daemon. > **_NOTE:_** This parameter is read-only and cannot be set. The server will determine the node id at startup time. +> **mauto\_sinks\_update** +> JSON boolean specifying whether to enable or disable the automatic update of the configured Sinks. +> **_NOTE:_** When enabled the daemon will automatically update the configured Sinks according to the discovered remote sources via SAP and mDNS/RTSP updates. The SDP Originator (o=) is used to match a Sink with the remote source/s. + > **custom\_node\_id** > JSON string specifying a custom node identifier used to identify mDNS, SAP and SDP services announced by the daemon. > When this parameter is empty the *node_id* is automatically generated by the daemon based on the current IP address. diff --git a/daemon/config.hpp b/daemon/config.hpp index 003ee69..7ad5344 100644 --- a/daemon/config.hpp +++ b/daemon/config.hpp @@ -54,6 +54,7 @@ class Config { const std::string& get_config_filename() const { return config_filename_; }; const std::string& get_custom_node_id() const { return custom_node_id_; }; std::string get_node_id() const; + bool get_auto_sinks_update() const { return auto_sinks_update_; }; /* attributes set during init */ const std::array& get_mac_addr() const { return mac_addr_; }; @@ -122,6 +123,9 @@ class Config { void set_custom_node_id(const std::string& node_id) { custom_node_id_ = node_id; }; + void set_auto_sinks_update(bool auto_sinks_update) { + auto_sinks_update_ = auto_sinks_update; + }; void set_driver_restart(bool restart) { driver_restart_ = restart; } friend bool operator!=(const Config& lhs, const Config& rhs) { @@ -144,6 +148,7 @@ class Config { lhs.get_status_file() != rhs.get_status_file() || lhs.get_interface_name() != rhs.get_interface_name() || lhs.get_mdns_enabled() != rhs.get_mdns_enabled() || + lhs.get_auto_sinks_update() != rhs.get_auto_sinks_update() || lhs.get_custom_node_id() != rhs.get_custom_node_id(); }; friend bool operator==(const Config& lhs, const Config& rhs) { @@ -174,6 +179,7 @@ class Config { std::string ptp_status_script_; std::string custom_node_id_; std::string node_id_; + bool auto_sinks_update_{true}; /* set during init */ std::array mac_addr_{0, 0, 0, 0, 0, 0}; diff --git a/daemon/daemon.conf b/daemon/daemon.conf index b049a64..58e1cec 100644 --- a/daemon/daemon.conf +++ b/daemon/daemon.conf @@ -19,5 +19,6 @@ "interface_name": "lo", "mdns_enabled": true, "custom_node_id": "", - "ptp_status_script": "./scripts/ptp_status.sh" + "ptp_status_script": "./scripts/ptp_status.sh", + "auto_sinks_update": true } diff --git a/daemon/json.cpp b/daemon/json.cpp index fbbdf87..a395976 100644 --- a/daemon/json.cpp +++ b/daemon/json.cpp @@ -99,13 +99,16 @@ std::string config_to_json(const Config& config) { << ",\n \"interface_name\": \"" << escape_json(config.get_interface_name()) << "\"" << ",\n \"mdns_enabled\": " << std::boolalpha << config.get_mdns_enabled() - << ",\n \"custom_node_id\": \"" << escape_json(config.get_custom_node_id()) << "\"" + << ",\n \"custom_node_id\": \"" + << escape_json(config.get_custom_node_id()) << "\"" << ",\n \"node_id\": \"" << escape_json(config.get_node_id()) << "\"" << ",\n \"ptp_status_script\": \"" << escape_json(config.get_ptp_status_script()) << "\"" - << ",\n \"mac_addr\": \"" << escape_json(config.get_mac_addr_str()) << "\"" + << ",\n \"mac_addr\": \"" << escape_json(config.get_mac_addr_str()) + << "\"" << ",\n \"ip_addr\": \"" << escape_json(config.get_ip_addr_str()) << "\"" - << "\n}\n"; + << ",\n \"auto_sinks_update\": " << std::boolalpha + << config.get_auto_sinks_update() << "\n}\n"; return ss.str(); } @@ -327,6 +330,8 @@ Config json_to_config_(std::istream& js, Config& config) { } else if (key == "custom_node_id") { config.set_custom_node_id( remove_undesired_chars(val.get_value())); + } else if (key == "auto_sinks_update") { + config.set_auto_sinks_update(val.get_value()); } else if (key == "mac_addr" || key == "ip_addr" || key == "node_id") { /* ignored */ } else { diff --git a/daemon/session_manager.cpp b/daemon/session_manager.cpp index 706f273..6ead695 100644 --- a/daemon/session_manager.cpp +++ b/daemon/session_manager.cpp @@ -1055,11 +1055,13 @@ std::list SessionManager::get_updated_sinks( } void SessionManager::update_sinks(const std::list& sources_list) { - auto sinks_list = get_updated_sinks(sources_list); - for (auto& sink : sinks_list) { - // Re-add sink with new SDP, since the sink.id is the same there will be - // an update - add_sink(sink); + if (config_->get_auto_sinks_update()) { + auto sinks_list = get_updated_sinks(sources_list); + for (auto& sink : sinks_list) { + // Re-add sink with new SDP, since the sink.id is the same there will be + // an update + add_sink(sink); + } } } diff --git a/daemon/tests/daemon.conf b/daemon/tests/daemon.conf index 853fd97..7831362 100644 --- a/daemon/tests/daemon.conf +++ b/daemon/tests/daemon.conf @@ -18,9 +18,10 @@ "status_file": "", "interface_name": "lo", "mdns_enabled": true, - "mac_addr": "00:00:00:00:00:00", - "ip_addr": "127.0.0.1", "custom_node_id": "test node", "node_id": "test node", - "ptp_status_script": "" + "ptp_status_script": "", + "mac_addr": "00:00:00:00:00:00", + "ip_addr": "127.0.0.1", + "auto_sinks_update": true } diff --git a/daemon/tests/daemon_test.cpp b/daemon/tests/daemon_test.cpp index bb7501f..1b6ddad 100644 --- a/daemon/tests/daemon_test.cpp +++ b/daemon/tests/daemon_test.cpp @@ -398,6 +398,7 @@ BOOST_AUTO_TEST_CASE(get_config) { auto interface_name = pt.get("interface_name"); auto mac_addr = pt.get("mac_addr"); auto ip_addr = pt.get("ip_addr"); + auto auto_sinks_update = pt.get("auto_sinks_update"); BOOST_CHECK_MESSAGE(http_port == 9999, "config as excepcted"); // BOOST_CHECK_MESSAGE(log_severity == 5, "config as excepcted"); BOOST_CHECK_MESSAGE(playout_delay == 0, "config as excepcted"); @@ -419,6 +420,7 @@ BOOST_AUTO_TEST_CASE(get_config) { BOOST_CHECK_MESSAGE(ptp_status_script == "", "config as excepcted"); BOOST_CHECK_MESSAGE(node_id == "test node", "config as excepcted"); BOOST_CHECK_MESSAGE(custom_node_id == "test node", "config as excepcted"); + BOOST_CHECK_MESSAGE(auto_sinks_update == true, "config as excepcted"); } BOOST_AUTO_TEST_CASE(get_ptp_status) { diff --git a/test/daemon.conf b/test/daemon.conf index 279bae0..bf88a92 100644 --- a/test/daemon.conf +++ b/test/daemon.conf @@ -22,5 +22,6 @@ "ip_addr": "127.0.0.1", "node_id": "AES67 daemon 007f0100", "custom_node_id": "", - "ptp_status_script": "" + "ptp_status_script": "", + "auto_sinks_update": true } diff --git a/webui/src/Config.jsx b/webui/src/Config.jsx index ecc6513..fab35e9 100644 --- a/webui/src/Config.jsx +++ b/webui/src/Config.jsx @@ -59,7 +59,8 @@ class Config extends Component { ipAddr: '', errors: 0, isConfigLoading: false, - isVersionLoading: false + isVersionLoading: false, + autoSinksUpdate: false }; this.onSubmit = this.onSubmit.bind(this); this.inputIsValid = this.inputIsValid.bind(this); @@ -104,6 +105,7 @@ class Config extends Component { macAddr: data.mac_addr, ipAddr: data.ip_addr, nodeId: data.node_id, + autoSinksUpdate: data.auto_sinks_update, isConfigLoading: false })) .catch(err => this.setState({isConfigLoading: false})); @@ -139,7 +141,8 @@ class Config extends Component { this.state.sapMcastAddr, this.state.sapInterval, this.state.mdnsEnabled, - this.state.customNodeId) + this.state.customNodeId, + this.state.autoSinksUpdate) .then(response => toast.success('Applying new configuration ...')); } @@ -226,6 +229,10 @@ class Config extends Component { this.setState({mdnsEnabled: e.target.checked})} checked={this.state.mdnsEnabled ? true : undefined}/> + + + this.setState({autoSinksUpdate: e.target.checked})} checked={this.state.autoSinksUpdate ? true : undefined}/> + diff --git a/webui/src/Services.js b/webui/src/Services.js index 35ffab6..d3a6174 100644 --- a/webui/src/Services.js +++ b/webui/src/Services.js @@ -84,7 +84,7 @@ export default class RestAPI { }); } - static setConfig(log_severity, syslog_proto, syslog_server, rtp_mcast_base, rtp_port, rtsp_port, playout_delay, tic_frame_size_at_1fs, sample_rate, max_tic_frame_size, sap_mcast_addr, sap_interval, mdns_enabled, custom_node_id) { + static setConfig(log_severity, syslog_proto, syslog_server, rtp_mcast_base, rtp_port, rtsp_port, playout_delay, tic_frame_size_at_1fs, sample_rate, max_tic_frame_size, sap_mcast_addr, sap_interval, mdns_enabled, custom_node_id, auto_sinks_update) { return this.doFetch(config, { body: JSON.stringify({ log_severity: parseInt(log_severity, 10), @@ -100,7 +100,8 @@ export default class RestAPI { sap_mcast_addr: sap_mcast_addr, sap_interval: parseInt(sap_interval, 10), custom_node_id: custom_node_id, - mdns_enabled: mdns_enabled + mdns_enabled: mdns_enabled, + auto_sinks_update: auto_sinks_update }), method: 'POST' }).catch(err => {