diff --git a/daemon/README.md b/daemon/README.md
index e442d6c..4415aaf 100644
--- a/daemon/README.md
+++ b/daemon/README.md
@@ -185,7 +185,8 @@ Example
"sap_interval": 30,
"mac_addr": "01:00:5e:01:00:01",
"ip_addr": "127.0.0.1",
- "node_id": "AES67 daemon ubuntu-d9aca383"
+ "node_id": "AES67 daemon ubuntu-d9aca383",
+ "ptp_status_script": "./scripts/ptp_status.sh"
}
where:
@@ -221,7 +222,7 @@ where:
> The specific multicast RTP address is the base address plus the source id number.
> For example if the base address is 239.2.0.1 and source id is 1 the RTP source address used is 239.2.0.2.
-> **rtp_port**
+> **rtp\_port**
> JSON number specifying the RTP port used by the sources.
> **ptp\_domain**
@@ -267,6 +268,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.
+> **ptp\_status\_script**
+> JSON string specifying the path to the script executed in background when the PTP slave clock status changes.
+> The PTP clock status is passed as first parameter to the script and it can be *unlocked*, *locking* or *locked*.
+
### JSON PTP Config ###
Example
diff --git a/daemon/browser.cpp b/daemon/browser.cpp
index 3842704..420e01d 100644
--- a/daemon/browser.cpp
+++ b/daemon/browser.cpp
@@ -101,9 +101,9 @@ bool Browser::worker() {
duration_cast(steady_clock::now() - startup_).count();
auto upd_source{*it};
if ((last_seen - upd_source.last_seen) != 0) {
- upd_source.announce_period = last_seen - upd_source.last_seen;
- upd_source.last_seen = last_seen;
- sources_.replace(it, upd_source);
+ upd_source.announce_period = last_seen - upd_source.last_seen;
+ upd_source.last_seen = last_seen;
+ sources_.replace(it, upd_source);
}
} else {
BOOST_LOG_TRIVIAL(info) << "browser:: removing SAP source " << it->id
diff --git a/daemon/config.cpp b/daemon/config.cpp
index 9889958..c364a93 100644
--- a/daemon/config.cpp
+++ b/daemon/config.cpp
@@ -36,7 +36,8 @@
using namespace boost::asio;
-std::shared_ptr Config::parse(const std::string& filename) {
+std::shared_ptr Config::parse(const std::string& filename,
+ bool driver_restart) {
Config config;
std::ifstream jsonstream(filename);
@@ -104,20 +105,43 @@ std::shared_ptr Config::parse(const std::string& filename) {
}
config.config_filename_ = filename;
- config.need_restart_ = false;
+ config.daemon_restart_ = false;
+ config.driver_restart_ = driver_restart;
return std::make_shared(config);
}
-bool Config::save(const Config& config, bool need_restart) {
- std::ofstream js(config_filename_);
- if (!js) {
- BOOST_LOG_TRIVIAL(fatal)
- << "Config:: cannot save to file " << config_filename_;
- return false;
+bool Config::save(const Config& config) {
+ if (*this != config) {
+ std::ofstream js(config_filename_);
+ if (!js) {
+ BOOST_LOG_TRIVIAL(fatal)
+ << "Config:: cannot save to file " << config_filename_;
+ return false;
+ }
+ js << config_to_json(config);
+
+ driver_restart_ =
+ get_tic_frame_size_at_1fs() != config.get_tic_frame_size_at_1fs() ||
+ get_max_tic_frame_size() != config.get_max_tic_frame_size() ||
+ get_interface_name() != config.get_interface_name();
+
+ daemon_restart_ = driver_restart_ ||
+ get_http_port() != config.get_http_port() ||
+ get_rtsp_port() != config.get_rtsp_port() ||
+ get_http_base_dir() != config.get_http_base_dir() ||
+ get_rtp_mcast_base() != config.get_rtp_mcast_base() ||
+ get_sap_mcast_addr() != config.get_sap_mcast_addr() ||
+ get_rtp_port() != config.get_rtp_port() ||
+ get_status_file() != config.get_status_file() ||
+ get_mdns_enabled() != config.get_mdns_enabled();
+
+ if (!daemon_restart_)
+ *this = config;
+
+ BOOST_LOG_TRIVIAL(info) << "Config:: file saved";
+ } else {
+ BOOST_LOG_TRIVIAL(info) << "Config:: unchanged";
}
- js << config_to_json(config);
- BOOST_LOG_TRIVIAL(info) << "Config:: file saved";
- need_restart_ = need_restart;
return true;
}
diff --git a/daemon/config.hpp b/daemon/config.hpp
index 7b74d0c..6502071 100644
--- a/daemon/config.hpp
+++ b/daemon/config.hpp
@@ -27,9 +27,10 @@
class Config {
public:
/* save new config to json file */
- bool save(const Config& config, bool need_restart = true);
+ bool save(const Config& config);
/* build config from json file */
- static std::shared_ptr parse(const std::string& filename);
+ static std::shared_ptr parse(const std::string& filename,
+ bool driver_restart);
/* attributes retrieved from config json */
uint16_t get_http_port() const { return http_port_; };
@@ -57,9 +58,13 @@ class Config {
const std::string& get_mac_addr_str() const { return mac_str_; };
uint32_t get_ip_addr() const { return ip_addr_; };
const std::string& get_ip_addr_str() const { return ip_str_; };
- bool get_need_restart() const { return need_restart_; };
+ bool get_daemon_restart() const { return daemon_restart_; };
+ bool get_driver_restart() const { return driver_restart_; };
bool get_mdns_enabled() const { return mdns_enabled_; };
int get_interface_idx() { return interface_idx_; };
+ const std::string& get_ptp_status_script() const {
+ return ptp_status_script_;
+ }
void set_http_port(uint16_t http_port) { http_port_ = http_port; };
void set_rtsp_port(uint16_t rtsp_port) { rtsp_port_ = rtsp_port; };
@@ -109,6 +114,35 @@ class Config {
};
void set_mdns_enabled(bool enabled) { mdns_enabled_ = enabled; };
void set_interface_idx(int index) { interface_idx_ = index; };
+ void set_ptp_status_script(const std::string& script) {
+ ptp_status_script_ = script;
+ };
+ void set_driver_restart(bool restart) { driver_restart_ = restart; }
+
+ friend bool operator!=(const Config& lhs, const Config& rhs) {
+ return lhs.get_http_port() != rhs.get_http_port() ||
+ lhs.get_rtsp_port() != rhs.get_rtsp_port() ||
+ lhs.get_http_base_dir() != rhs.get_http_base_dir() ||
+ lhs.get_log_severity() != rhs.get_log_severity() ||
+ lhs.get_playout_delay() != rhs.get_playout_delay() ||
+ lhs.get_tic_frame_size_at_1fs() != rhs.get_tic_frame_size_at_1fs() ||
+ lhs.get_max_tic_frame_size() != rhs.get_max_tic_frame_size() ||
+ lhs.get_sample_rate() != rhs.get_sample_rate() ||
+ lhs.get_rtp_mcast_base() != rhs.get_rtp_mcast_base() ||
+ lhs.get_sap_mcast_addr() != rhs.get_sap_mcast_addr() ||
+ lhs.get_rtp_port() != rhs.get_rtp_port() ||
+ lhs.get_ptp_domain() != rhs.get_ptp_domain() ||
+ lhs.get_ptp_dscp() != rhs.get_ptp_dscp() ||
+ lhs.get_sap_interval() != rhs.get_sap_interval() ||
+ lhs.get_syslog_proto() != rhs.get_syslog_proto() ||
+ lhs.get_syslog_server() != rhs.get_syslog_server() ||
+ lhs.get_status_file() != rhs.get_status_file() ||
+ lhs.get_interface_name() != rhs.get_interface_name() ||
+ lhs.get_mdns_enabled() != rhs.get_mdns_enabled();
+ };
+ friend bool operator==(const Config& lhs, const Config& rhs) {
+ return !(lhs != rhs);
+ };
private:
/* from json */
@@ -131,6 +165,7 @@ class Config {
std::string status_file_{"./status.json"};
std::string interface_name_{"eth0"};
bool mdns_enabled_{true};
+ std::string ptp_status_script_;
/* set during init */
std::array mac_addr_{0, 0, 0, 0, 0, 0};
@@ -140,8 +175,10 @@ class Config {
int interface_idx_;
std::string config_filename_;
+ /* reconfig needs driver restart */
+ bool driver_restart_{true};
/* reconfig needs daemon restart */
- bool need_restart_{false};
+ bool daemon_restart_{false};
};
#endif
diff --git a/daemon/daemon.conf b/daemon/daemon.conf
index 95f3343..7a02015 100644
--- a/daemon/daemon.conf
+++ b/daemon/daemon.conf
@@ -16,6 +16,7 @@
"syslog_proto": "none",
"syslog_server": "255.255.255.254:1234",
"status_file": "./status.json",
+ "interface_name": "lo",
"mdns_enabled": true,
- "interface_name": "lo"
+ "ptp_status_script": "./scripts/ptp_status.sh"
}
diff --git a/daemon/driver_handler.cpp b/daemon/driver_handler.cpp
index dd6b82a..0ba8690 100644
--- a/daemon/driver_handler.cpp
+++ b/daemon/driver_handler.cpp
@@ -130,7 +130,7 @@ bool DriverHandler::event_receiver() {
return true;
}
-bool DriverHandler::terminate() {
+bool DriverHandler::terminate(const Config& /* config */) {
if (running_) {
running_ = false;
client_u2k_.terminate();
diff --git a/daemon/driver_handler.hpp b/daemon/driver_handler.hpp
index b7957f7..501ab05 100644
--- a/daemon/driver_handler.hpp
+++ b/daemon/driver_handler.hpp
@@ -40,10 +40,10 @@ class DriverHandler {
DriverHandler(){};
DriverHandler(const DriverHandler&) = delete;
DriverHandler& operator=(const DriverHandler&) = delete;
- virtual ~DriverHandler() { terminate(); };
+ virtual ~DriverHandler(){};
virtual bool init(const Config& config);
- virtual bool terminate();
+ virtual bool terminate(const Config& config);
protected:
virtual void send_command(enum MT_ALSA_msg_id id,
diff --git a/daemon/driver_manager.cpp b/daemon/driver_manager.cpp
index 9a1be6f..9715db0 100644
--- a/daemon/driver_manager.cpp
+++ b/daemon/driver_manager.cpp
@@ -81,20 +81,28 @@ bool DriverManager::init(const Config& config) {
ptp_config.ui8Domain = config.get_ptp_domain();
ptp_config.ui8DSCP = config.get_ptp_dscp();
- bool res = hello() || start() || reset() ||
- set_interface_name(config.get_interface_name()) ||
- set_ptp_config(ptp_config) ||
- set_tic_frame_size_at_1fs(config.get_tic_frame_size_at_1fs()) ||
- set_playout_delay(config.get_playout_delay()) ||
- set_max_tic_frame_size(config.get_max_tic_frame_size());
+ if (hello())
+ return false;
+
+ bool res(false);
+ if (config.get_driver_restart()) {
+ res = start() || reset() ||
+ set_interface_name(config.get_interface_name()) ||
+ set_ptp_config(ptp_config) ||
+ set_tic_frame_size_at_1fs(config.get_tic_frame_size_at_1fs()) ||
+ set_playout_delay(config.get_playout_delay()) ||
+ set_max_tic_frame_size(config.get_max_tic_frame_size());
+ }
return !res;
}
-bool DriverManager::terminate() {
- stop();
+bool DriverManager::terminate(const Config& config) {
+ if (config.get_driver_restart()) {
+ stop();
+ }
bye();
- return DriverHandler::terminate();
+ return DriverHandler::terminate(config);
}
std::error_code DriverManager::hello() {
diff --git a/daemon/driver_manager.hpp b/daemon/driver_manager.hpp
index 938c2e2..fda9c8d 100644
--- a/daemon/driver_manager.hpp
+++ b/daemon/driver_manager.hpp
@@ -33,7 +33,7 @@ class DriverManager : public DriverHandler {
// driver interface
bool init(const Config& config) override;
- bool terminate() override;
+ bool terminate(const Config& config) override;
std::error_code ping(); // unused, return error
std::error_code set_ptp_config(const TPTPConfig& config);
diff --git a/daemon/http_server.cpp b/daemon/http_server.cpp
index b8e36da..2a9e005 100644
--- a/daemon/http_server.cpp
+++ b/daemon/http_server.cpp
@@ -115,6 +115,30 @@ bool HttpServer::init() {
svr_.Post("/api/config", [this](const Request& req, Response& res) {
try {
Config config = json_to_config(req.body, *config_);
+
+ if (config_->get_syslog_proto() != config.get_syslog_proto() ||
+ config_->get_syslog_server() != config.get_syslog_server() ||
+ config_->get_log_severity() != config.get_log_severity()) {
+ log_init(config);
+ }
+ std::error_code ret;
+ if (config_->get_playout_delay() != config.get_playout_delay()) {
+ ret = session_manager_->set_driver_config("playout_delay",
+ config.get_playout_delay());
+ }
+ if (config_->get_sample_rate() != config.get_sample_rate()) {
+ ret = session_manager_->set_driver_config("sample_rate",
+ config.get_sample_rate());
+ }
+ if (config_->get_ptp_domain() != config.get_ptp_domain() ||
+ config_->get_ptp_dscp() != config.get_ptp_dscp()) {
+ PTPConfig ptpConfig{config.get_ptp_domain(), config.get_ptp_dscp()};
+ ret = session_manager_->set_ptp_config(ptpConfig);
+ }
+ if (ret) {
+ set_error(ret, "failed to set config", res);
+ return;
+ }
if (!config_->save(config)) {
set_error(500, "failed to save config", res);
return;
@@ -153,7 +177,7 @@ bool HttpServer::init() {
Config config(*config_);
config.set_ptp_domain(ptpConfig.domain);
config.set_ptp_dscp(ptpConfig.dscp);
- if (!config_->save(config, false)) {
+ if (!config_->save(config)) {
set_error(500, "failed to save config", res);
return;
}
diff --git a/daemon/interface.cpp b/daemon/interface.cpp
index 2211621..f5f9fb5 100644
--- a/daemon/interface.cpp
+++ b/daemon/interface.cpp
@@ -115,7 +115,6 @@ int get_interface_index(const std::string& interface_name) {
return ifr.ifr_ifindex;
}
-
std::pair, std::string> get_mac_from_arp_cache(
const std::string& interface_name,
const std::string& ip) {
@@ -155,7 +154,6 @@ std::pair, std::string> get_mac_from_arp_cache(
return {mac, ""};
}
-
bool ping(const std::string& ip) {
static uint16_t sequence_number(0);
uint16_t identifier(0xABAB);
@@ -182,7 +180,6 @@ bool ping(const std::string& ip) {
return true;
}
-
bool echo_try_connect(const std::string& ip) {
ip::tcp::iostream s;
BOOST_LOG_TRIVIAL(debug) << "echo_connect:: connecting to " << ip;
diff --git a/daemon/json.cpp b/daemon/json.cpp
index 649ef29..68a16c7 100644
--- a/daemon/json.cpp
+++ b/daemon/json.cpp
@@ -104,6 +104,8 @@ std::string config_to_json(const Config& config) {
<< ",\n \"ip_addr\": \"" << escape_json(config.get_ip_addr_str()) << "\""
<< ",\n \"node_id\": \"" << escape_json(get_node_id(config.get_ip_addr()))
<< "\""
+ << ",\n \"ptp_status_script\": \""
+ << escape_json(config.get_ptp_status_script()) << "\""
<< "\n}\n";
return ss.str();
}
@@ -158,8 +160,8 @@ std::string sink_to_json(const StreamSink& sink) {
std::string sink_status_to_json(const SinkStreamStatus& status) {
std::stringstream ss;
ss << "{";
- ss << " \n \"sink_flags\":\n {" << std::boolalpha
- << " \n \"rtp_seq_id_error\": " << status.is_rtp_seq_id_error
+ ss << "\n \"sink_flags\":\n {" << std::boolalpha
+ << " \n \"rtp_seq_id_error\": " << status.is_rtp_seq_id_error
<< ", \n \"rtp_ssrc_error\": " << status.is_rtp_ssrc_error
<< ", \n \"rtp_payload_type_error\": "
<< status.is_rtp_payload_type_error
@@ -320,6 +322,9 @@ Config json_to_config_(std::istream& js, Config& config) {
} else if (key == "syslog_server") {
config.set_syslog_server(
remove_undesired_chars(val.get_value()));
+ } else if (key == "ptp_status_script") {
+ config.set_ptp_status_script(
+ remove_undesired_chars(val.get_value()));
} else if (key == "mac_addr" || key == "ip_addr" || key == "node_id") {
/* ignored */
} else {
diff --git a/daemon/main.cpp b/daemon/main.cpp
index 88299cd..58fa162 100644
--- a/daemon/main.cpp
+++ b/daemon/main.cpp
@@ -35,7 +35,7 @@ namespace po = boost::program_options;
namespace postyle = boost::program_options::command_line_style;
namespace logging = boost::log;
-static std::string version("bondagit-1.4");
+static std::string version("bondagit-1.5");
static std::atomic terminate = false;
void termination_handler(int signum) {
@@ -53,15 +53,16 @@ const std::string& get_version() {
}
int main(int argc, char* argv[]) {
- int rc = EXIT_SUCCESS;
+ int rc(EXIT_SUCCESS);
po::options_description desc("Options");
- desc.add_options()
- ("version,v", "Print daemon version and exit")
- ("config,c", po::value()->default_value("/etc/daemon.conf"),
- "daemon configuration file")
- ("http_port,p", po::value(), "HTTP server port")
- ("help,h", "Print this help message");
+ desc.add_options()("version,v", "Print daemon version and exit")(
+ "config,c", po::value()->default_value("/etc/daemon.conf"),
+ "daemon configuration file")("http_port,p", po::value(),
+ "HTTP server port")("help,h",
+ "Print this help "
+ "message");
int unix_style = postyle::unix_style | postyle::short_allow_next;
+ bool driver_restart(true);
po::variables_map vm;
try {
@@ -98,7 +99,7 @@ int main(int argc, char* argv[]) {
while (!is_terminated() && rc == EXIT_SUCCESS) {
/* load configuration from file */
- auto config = Config::parse(filename);
+ auto config = Config::parse(filename, driver_restart);
if (config == nullptr) {
return EXIT_FAILURE;
}
@@ -165,7 +166,8 @@ int main(int argc, char* argv[]) {
break;
}
- if (config->get_need_restart()) {
+ driver_restart = config->get_driver_restart();
+ if (config->get_daemon_restart()) {
BOOST_LOG_TRIVIAL(warning) << "main:: config changed, restarting ...";
break;
}
@@ -205,7 +207,7 @@ int main(int argc, char* argv[]) {
}
/* stop driver manager */
- if (!driver->terminate()) {
+ if (!driver->terminate(*config)) {
throw std::runtime_error(
std::string("DriverManager:: terminate failed"));
}
diff --git a/daemon/mdns_client.cpp b/daemon/mdns_client.cpp
index 96e9621..224e7f4 100644
--- a/daemon/mdns_client.cpp
+++ b/daemon/mdns_client.cpp
@@ -25,7 +25,6 @@
#include "rtsp_client.hpp"
#include "mdns_client.hpp"
-
#ifdef _USE_AVAHI_
void MDNSClient::resolve_callback(AvahiServiceResolver* r,
AvahiIfIndex interface,
diff --git a/daemon/mdns_server.cpp b/daemon/mdns_server.cpp
index 2bf3341..9611d3d 100644
--- a/daemon/mdns_server.cpp
+++ b/daemon/mdns_server.cpp
@@ -25,7 +25,6 @@
#include "utils.hpp"
#include "mdns_server.hpp"
-
#ifdef _USE_AVAHI_
struct AvahiLockGuard {
AvahiLockGuard() = delete;
diff --git a/daemon/rtsp_server.cpp b/daemon/rtsp_server.cpp
index a35c509..c695245 100644
--- a/daemon/rtsp_server.cpp
+++ b/daemon/rtsp_server.cpp
@@ -15,7 +15,6 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
-
#include "utils.hpp"
#include "rtsp_server.hpp"
diff --git a/daemon/scripts/ptp_status.sh b/daemon/scripts/ptp_status.sh
new file mode 100755
index 0000000..679dd62
--- /dev/null
+++ b/daemon/scripts/ptp_status.sh
@@ -0,0 +1,11 @@
+#!/bin/bash
+
+if [ $1 == "locked" ]; then
+ echo "$0 >> PTP locked";
+ #speaker-test -D plughw:RAVENNA -r 48000 -c 2 -t sine &
+elif [ $1 == "locking" ]; then
+ echo "$0 >> PTP locking";
+elif [ $1 == "unlocked" ]; then
+ echo "$0 >> PTP unlocked";
+ #killall -9 speaker-test
+fi
diff --git a/daemon/session_manager.cpp b/daemon/session_manager.cpp
index 2c00a0e..f6a5a91 100644
--- a/daemon/session_manager.cpp
+++ b/daemon/session_manager.cpp
@@ -19,6 +19,7 @@
#define CPPHTTPLIB_PAYLOAD_MAX_LENGTH 4096 // max for SDP file
+#include
#include
#include
@@ -479,7 +480,7 @@ std::error_code SessionManager::add_source(const StreamSource& source) {
info.stream.m_ui32CRTP_stream_info_sizeof = sizeof(info.stream);
strncpy(info.stream.m_cName, source.name.c_str(),
sizeof(info.stream.m_cName) - 1);
- info.stream.m_ucDSCP = source.dscp; // IPv4 DSCP
+ info.stream.m_ucDSCP = source.dscp; // IPv4 DSCP
info.stream.m_byPayloadType = source.payload_type;
info.stream.m_byWordLength = get_codec_word_lenght(source.codec);
info.stream.m_byNbOfChannels = source.map.size();
@@ -513,13 +514,16 @@ std::error_code SessionManager::add_source(const StreamSource& source) {
info.stream.m_ui8DestMAC);
info.stream.m_byTTL = source.ttl;
} else {
- auto mac_addr = get_mac_from_arp_cache(config_->get_interface_name(),
+ auto mac_addr = get_mac_from_arp_cache(
+ config_->get_interface_name(),
ip::address_v4(info.stream.m_ui32DestIP).to_string());
int retry = 3;
while (!mac_addr.second.length() && retry--) {
// if not in cache already try to populate the MAC cache
- (void)echo_try_connect(ip::address_v4(info.stream.m_ui32DestIP).to_string());
- mac_addr = get_mac_from_arp_cache(config_->get_interface_name(),
+ (void)echo_try_connect(
+ ip::address_v4(info.stream.m_ui32DestIP).to_string());
+ mac_addr = get_mac_from_arp_cache(
+ config_->get_interface_name(),
ip::address_v4(info.stream.m_ui32DestIP).to_string());
}
if (!mac_addr.second.length()) {
@@ -625,8 +629,8 @@ std::string SessionManager::get_source_sdp_(uint32_t id,
if (IN_MULTICAST(info.stream.m_ui32DestIP)) {
ss << "/" << static_cast(info.stream.m_byTTL);
}
- ss << "\na=rtpmap:" << static_cast(info.stream.m_byPayloadType) << " "
- << info.stream.m_cCodec << "/" << sample_rate << "/"
+ ss << "\na=rtpmap:" << static_cast(info.stream.m_byPayloadType)
+ << " " << info.stream.m_cCodec << "/" << sample_rate << "/"
<< static_cast(info.stream.m_byNbOfChannels) << "\n"
<< "a=sync-time:0\n"
<< "a=framecount:" << info.stream.m_ui32MaxSamplesPerPacket << "\n"
@@ -902,6 +906,19 @@ std::error_code SessionManager::get_sink_status(
return ret;
}
+std::error_code SessionManager::set_driver_config(const std::string& name,
+ uint32_t value) const {
+ if (name == "sample_rate")
+ return driver_->set_sample_rate(value);
+ else if (name == "tic_frame_size_at_1fs")
+ return driver_->set_tic_frame_size_at_1fs(value);
+ else if (name == "set_max_tic_frame_size")
+ return driver_->set_max_tic_frame_size(value);
+ else if (name == "playout_delay")
+ return driver_->set_playout_delay(value);
+ return DriverErrc::unknown;
+}
+
std::error_code SessionManager::set_ptp_config(const PTPConfig& config) {
TPTPConfig ptp_config;
ptp_config.ui8Domain = config.domain;
@@ -1002,9 +1019,31 @@ void SessionManager::on_update_sources() {
g_session_version++;
}
-void SessionManager::on_ptp_status_locked() const {
- // set sample rate, this may require seconds
- (void)driver_->set_sample_rate(driver_->get_current_sample_rate());
+void SessionManager::on_ptp_status_changed(const std::string& status) const {
+ if (status == "locked") {
+ // set sample rate, this may require seconds
+ (void)driver_->set_sample_rate(driver_->get_current_sample_rate());
+ }
+
+ static std::string g_ptp_status;
+
+ if (g_ptp_status != status && !config_->get_ptp_status_script().empty()) {
+ pid_t pid = fork();
+ if (pid == 0) {
+ /* child */
+ int fdlimit = (int)sysconf(_SC_OPEN_MAX);
+ /* close all partent's fds */
+ for (int i = STDERR_FILENO + 1; i < fdlimit; i++)
+ close(i);
+
+ char* argv_list[] = {const_cast(config_->get_ptp_status_script().c_str()),
+ const_cast(status.c_str()), NULL};
+
+ execv(config_->get_ptp_status_script().c_str(), argv_list);
+ exit(0);
+ }
+ g_ptp_status = status;
+ }
}
using namespace std::chrono;
@@ -1043,7 +1082,7 @@ bool SessionManager::worker() {
pui64GMID[5], pui64GMID[6], pui64GMID[7]);
bool ptp_changed_gmid = false;
- bool ptp_changed_to_locked = false;
+ std::string ptp_status_changed_to;
// update PTP clock status
ptp_mutex_.lock();
// update status
@@ -1069,15 +1108,13 @@ bool SessionManager::worker() {
BOOST_LOG_TRIVIAL(info)
<< "session_manager:: new PTP clock status " << new_ptp_status;
ptp_status_.status = new_ptp_status;
- if (new_ptp_status == "locked") {
- ptp_changed_to_locked = true;
- }
+ ptp_status_changed_to = new_ptp_status;
}
// end update PTP clock status
ptp_mutex_.unlock();
- if (ptp_changed_to_locked) {
- on_ptp_status_locked();
+ if (!ptp_status_changed_to.empty()) {
+ on_ptp_status_changed(ptp_status_changed_to);
}
if (ptp_changed_gmid ||
@@ -1085,10 +1122,10 @@ bool SessionManager::worker() {
/* master clock id changed or sample rate changed
* we need to update all the sources */
if (sample_rate != driver_->get_current_sample_rate()) {
- sample_rate = driver_->get_current_sample_rate();
- // set driver sample rate
- (void)driver_->set_sample_rate(sample_rate);
- }
+ sample_rate = driver_->get_current_sample_rate();
+ // set driver sample rate
+ (void)driver_->set_sample_rate(sample_rate);
+ }
on_update_sources();
}
}
diff --git a/daemon/session_manager.hpp b/daemon/session_manager.hpp
index 7dedd34..b580b14 100644
--- a/daemon/session_manager.hpp
+++ b/daemon/session_manager.hpp
@@ -151,6 +151,8 @@ class SessionManager {
uint8_t get_sink_id(const std::string& name) const;
std::error_code set_ptp_config(const PTPConfig& config);
+ std::error_code set_driver_config(const std::string& name,
+ uint32_t value) const;
void get_ptp_config(PTPConfig& config) const;
void get_ptp_status(PTPStatus& status) const;
@@ -169,7 +171,7 @@ class SessionManager {
void on_add_sink(const StreamSink& sink, const StreamInfo& info);
void on_remove_sink(const StreamInfo& info);
- void on_ptp_status_locked() const;
+ void on_ptp_status_changed(const std::string& status) const;
void on_update_sources();
diff --git a/daemon/tests/daemon.conf b/daemon/tests/daemon.conf
index 9ab940d..f4d2d72 100644
--- a/daemon/tests/daemon.conf
+++ b/daemon/tests/daemon.conf
@@ -20,5 +20,6 @@
"mdns_enabled": true,
"mac_addr": "00:00:00:00:00:00",
"ip_addr": "127.0.0.1",
- "node_id": "AES67 daemon 007f0100"
+ "node_id": "AES67 daemon 007f0100",
+ "ptp_status_script": ""
}
diff --git a/daemon/tests/daemon_test.cpp b/daemon/tests/daemon_test.cpp
index b13568a..d633c13 100644
--- a/daemon/tests/daemon_test.cpp
+++ b/daemon/tests/daemon_test.cpp
@@ -392,6 +392,7 @@ BOOST_AUTO_TEST_CASE(get_config) {
auto syslog_proto = pt.get("syslog_proto");
auto syslog_server = pt.get("syslog_server");
auto status_file = pt.get("status_file");
+ auto ptp_status_script = pt.get("ptp_status_script");
auto interface_name = pt.get("interface_name");
auto mac_addr = pt.get("mac_addr");
auto ip_addr = pt.get("ip_addr");
@@ -413,6 +414,7 @@ BOOST_AUTO_TEST_CASE(get_config) {
BOOST_CHECK_MESSAGE(interface_name == "lo", "config as excepcted");
BOOST_CHECK_MESSAGE(mac_addr == "00:00:00:00:00:00", "config as excepcted");
BOOST_CHECK_MESSAGE(ip_addr == "127.0.0.1", "config as excepcted");
+ BOOST_CHECK_MESSAGE(ptp_status_script == "", "config as excepcted");
}
BOOST_AUTO_TEST_CASE(get_ptp_status) {
diff --git a/test/daemon.conf b/test/daemon.conf
index 0a118dc..3d3131f 100644
--- a/test/daemon.conf
+++ b/test/daemon.conf
@@ -20,5 +20,6 @@
"mdns_enabled": false,
"mac_addr": "00:00:00:00:00:00",
"ip_addr": "127.0.0.1",
- "node_id": "AES67 daemon 007f0100"
+ "node_id": "AES67 daemon 007f0100",
+ "ptp_status_script": ""
}
diff --git a/webui/src/Config.jsx b/webui/src/Config.jsx
index 3bd7f56..2019c9e 100644
--- a/webui/src/Config.jsx
+++ b/webui/src/Config.jsx
@@ -135,7 +135,7 @@ class Config extends Component {
this.state.sapMcastAddr,
this.state.sapInterval,
this.state.mdnsEnabled)
- .then(response => toast.success('Config updated, daemon restart ...'));
+ .then(response => toast.success('Applying new configuration ...'));
}
render() {