diff --git a/applications/vision/src/main.cpp b/applications/vision/src/main.cpp
index 77c5a85866729fd7e9db6352f3e4dc06bf53616f..c2860bf5c276d8005e2b55e2210a3439d5cc61aa 100644
--- a/applications/vision/src/main.cpp
+++ b/applications/vision/src/main.cpp
@@ -298,7 +298,7 @@ int main(int argc, char **argv) {
 	root->value("restart", 0);
 
 	// Allow config controlled restart
-	root->on("restart", [root](const ftl::config::Event &e) {
+	root->on("restart", [root]() {
 		auto val = root->get<int>("restart");
 		if (val) {
 			ftl::exit_code = *val;
diff --git a/components/audio/src/speaker.cpp b/components/audio/src/speaker.cpp
index 99bcee9e5a7e601cfdecc7784da6cad103fc6f0d..9560bbed16d9def03c2015437d5d35590510c9ed 100644
--- a/components/audio/src/speaker.cpp
+++ b/components/audio/src/speaker.cpp
@@ -38,7 +38,7 @@ Speaker::Speaker(nlohmann::json &config) : ftl::Configurable(config), buffer_(nu
 	volume_ = 1.0f;
 	active_ = false;
 	extra_delay_ = value("delay",0.0f);
-	on("delay", [this](const ftl::config::Event &e) {
+	on("delay", [this]() {
 		extra_delay_ = value("delay",0.0f);
 	});
 }
diff --git a/components/common/cpp/include/ftl/configurable.hpp b/components/common/cpp/include/ftl/configurable.hpp
index c0b8ae802aeb722a547af95f0b884e780f0cd933..f08f5a72ac31e836972a327fbc1e47eb11a6b1f6 100644
--- a/components/common/cpp/include/ftl/configurable.hpp
+++ b/components/common/cpp/include/ftl/configurable.hpp
@@ -93,19 +93,22 @@ class Configurable {
 	 * @param prop Name of property to watch
 	 * @param callback A function object that will be called on change.
 	 */
-	void on(const std::string &prop, std::function<void(const config::Event&)>);
+	void on(const std::string &prop, std::function<void()>);
 
-	//void on(const std::string &prop, const std::function<void()> &);
+	/**
+	 * Same callback for all properties in set.
+	 */
+	void onAny(const std::unordered_set<std::string> &props, std::function<void()>);
 
 	template <typename T>
 	void on(const std::string &prop, T &v) {
-		on(prop, [&v,this,prop](const config::Event &e) { v = *this->get<T>(prop); });
+		on(prop, [&v,this,prop]() { v = *this->get<T>(prop); });
 	}
 
 	template <typename T>
 	void on(const std::string &prop, T &v, const T &def) {
 		v = this->value(prop, def);
-		on(prop, [&v,this,prop](const config::Event &e) { v = *this->get<T>(prop); });
+		on(prop, [&v,this,prop]() { v = *this->get<T>(prop); });
 	}
 
 	void patchPtr(nlohmann::json &newcfg) { config_ = &newcfg; }
@@ -147,7 +150,7 @@ class Configurable {
 	std::string restore_;
 	std::string defaults_;
 	std::unordered_set<std::string> save_allowed_;
-	std::map<std::string, std::list<std::function<void(const config::Event&)>>> observers_; 
+	std::map<std::string, std::list<std::function<void()>>> observers_; 
 
 	void _trigger(const std::string &name);
 };
diff --git a/components/common/cpp/src/configurable.cpp b/components/common/cpp/src/configurable.cpp
index c947eadada1e6f353b34341a6a3c440d1ccbfbe1..fd8db20e3d5f0a76518847f5e97c6876f8387b8b 100644
--- a/components/common/cpp/src/configurable.cpp
+++ b/components/common/cpp/src/configurable.cpp
@@ -136,7 +136,7 @@ void Configurable::_trigger(const string &name) {
 	if (ix != observers_.end()) {
 		for (auto &f : (*ix).second) {
 			try {
-				f({this, name});
+				f();
 			} catch(...) {
 				LOG(ERROR) << "Exception in event handler for '" << name << "'";
 			}
@@ -144,7 +144,13 @@ void Configurable::_trigger(const string &name) {
 	}
 }
 
-void Configurable::on(const string &prop, function<void(const ftl::config::Event&)> f) {
+void Configurable::onAny(const std::unordered_set<string> &props, function<void()> f) {
+	for (const auto &p : props) {
+		on(p, f);
+	}
+}
+
+void Configurable::on(const string &prop, function<void()> f) {
 	auto ix = observers_.find(prop);
 	if (ix == observers_.end()) {
 		observers_[prop] = {f};
diff --git a/components/common/cpp/src/configuration.cpp b/components/common/cpp/src/configuration.cpp
index e987b6afac423cc0d35f11d4501bc5f81e4737ac..327bfd03ba7585b7b2efd6120f9b79eb15422422 100644
--- a/components/common/cpp/src/configuration.cpp
+++ b/components/common/cpp/src/configuration.cpp
@@ -886,9 +886,9 @@ Configurable *ftl::config::configure(int argc, char **argv, const std::string &r
 	if (rootcfg->get<std::string>("branch")) {
 		ftl::branch_name = *rootcfg->get<std::string>("branch");
 	}
-	rootcfg->on("branch", [](const ftl::config::Event &e) {
-		if (e.entity->get<std::string>("branch")) {
-			ftl::branch_name = *e.entity->get<std::string>("branch");
+	rootcfg->on("branch", [rootcfg]() {
+		if (rootcfg->get<std::string>("branch")) {
+			ftl::branch_name = *rootcfg->get<std::string>("branch");
 		}
 	});
 
diff --git a/components/common/cpp/test/configurable_unit.cpp b/components/common/cpp/test/configurable_unit.cpp
index ed5a1a73c5870b1aabebd417c4f05af8c5bca7ae..ec5668c43521d5838c510a515febcc924e0a79c8 100644
--- a/components/common/cpp/test/configurable_unit.cpp
+++ b/components/common/cpp/test/configurable_unit.cpp
@@ -47,7 +47,7 @@ SCENARIO( "Configurable::on()" ) {
 		Configurable cfg(json);
 		bool trig = false;
 
-		cfg.on("test", [&trig](const ftl::config::Event &e) {
+		cfg.on("test", [&trig]() {
 			trig = true;
 		});
 
@@ -63,10 +63,10 @@ SCENARIO( "Configurable::on()" ) {
 		bool trig1 = false;
 		bool trig2 = false;
 
-		cfg.on("test", [&trig1](const ftl::config::Event &e) {
+		cfg.on("test", [&trig1]() {
 			trig1 = true;
 		});
-		cfg.on("test", [&trig2](const ftl::config::Event &e) {
+		cfg.on("test", [&trig2]() {
 			trig2 = true;
 		});
 
diff --git a/components/operators/src/aruco.cpp b/components/operators/src/aruco.cpp
index 7c7259ef2011ce9dea0a25807603068c8f3b5064..871e5812adf2927d864ff5640f50def31983444b 100644
--- a/components/operators/src/aruco.cpp
+++ b/components/operators/src/aruco.cpp
@@ -55,7 +55,7 @@ ArUco::ArUco(ftl::Configurable *cfg) : ftl::operators::Operator(cfg) {
 	channel_in_ = Channel::Colour;
 	channel_out_ = Channel::Shapes3D;
 
-	cfg->on("dictionary", [this,cfg](const ftl::config::Event &e) {
+	cfg->on("dictionary", [this,cfg]() {
 		dictionary_ = cv::aruco::getPredefinedDictionary(cfg->value("dictionary", 0));
 	});
 }
diff --git a/components/operators/src/depth.cpp b/components/operators/src/depth.cpp
index 107d92564406ca27846d95e7bccb56917a872f79..33af310458d24d110a8e721e46022376d02fcb3d 100644
--- a/components/operators/src/depth.cpp
+++ b/components/operators/src/depth.cpp
@@ -59,10 +59,10 @@ DepthBilateralFilter::DepthBilateralFilter(ftl::Configurable* cfg) :
 	max_disc_ = cfg->value("max_discontinuity", 0.1f);
 	channel_ = Channel::Depth;
 
-	cfg->on("edge_discontinuity", [this](const ftl::config::Event &e) {
+	cfg->on("edge_discontinuity", [this]() {
 		edge_disc_ = config()->value("edge_discontinuity", 0.04f);
 	});
-	cfg->on("max_discontinuity", [this](const ftl::config::Event &e) {
+	cfg->on("max_discontinuity", [this]() {
 		max_disc_ = config()->value("max_discontinuity", 0.1f);
 	});
 
@@ -82,10 +82,10 @@ DepthBilateralFilter::DepthBilateralFilter(ftl::Configurable* cfg, const std::tu
 	max_disc_ = cfg->value("max_discontinuity", 0.1f);
 	channel_ = std::get<0>(p);
 
-	cfg->on("edge_discontinuity", [this](const ftl::config::Event &e) {
+	cfg->on("edge_discontinuity", [this]() {
 		edge_disc_ = config()->value("edge_discontinuity", 0.04f);
 	});
-	cfg->on("max_discontinuity", [this](const ftl::config::Event &e) {
+	cfg->on("max_discontinuity", [this]() {
 		max_disc_ = config()->value("max_discontinuity", 0.1f);
 	});
 
diff --git a/components/operators/src/detectandtrack.cpp b/components/operators/src/detectandtrack.cpp
index a690e1ade6c60dc0c0a1aa9037dce414889381c2..4e9b1b7294bc168957bc63206d4601ef424f45e6 100644
--- a/components/operators/src/detectandtrack.cpp
+++ b/components/operators/src/detectandtrack.cpp
@@ -28,7 +28,7 @@ bool DetectAndTrack::init() {
 	fname_ = config()->value<string>("filename", FTL_LOCAL_DATA_ROOT "/haarcascades/haarcascade_frontalface_default.xml");
 	debug_ = config()->value<bool>("debug", false);
 
-	config()->on("debug", [this](const ftl::config::Event &e) {
+	config()->on("debug", [this]() {
 		debug_ = config()->value<bool>("debug", false);
 	});
 
diff --git a/components/operators/src/disparity/fixstars_sgm.cpp b/components/operators/src/disparity/fixstars_sgm.cpp
index 0e48629fc2f76d259ca5411d24136d278a5b2f6b..0274022737726a8d6a94c5bcc8124c82a8d4dd17 100644
--- a/components/operators/src/disparity/fixstars_sgm.cpp
+++ b/components/operators/src/disparity/fixstars_sgm.cpp
@@ -87,7 +87,7 @@ FixstarsSGM::FixstarsSGM(ftl::Configurable* cfg) :
 		LOG(WARNING) << "Invalid value for max_disp, using default value (256)";
 	}
 
-	cfg->on("P1", [this, cfg](const ftl::config::Event&) {
+	cfg->on("P1", [this, cfg]() {
 		int P1 = cfg->value("P1", 0);
 		if (P1 <= 0) {
 			LOG(WARNING) << "Invalid value for P1 (" << P1 << ")";
@@ -98,7 +98,7 @@ FixstarsSGM::FixstarsSGM(ftl::Configurable* cfg) :
 		}
 	});
 
-	cfg->on("P2", [this, cfg](const ftl::config::Event&) {
+	cfg->on("P2", [this, cfg]() {
 		int P2 = cfg->value("P2", 0);
 		if (P2 < P1_) {
 			LOG(WARNING) << "Invalid value for P2 (" << P2 << ")";
@@ -109,7 +109,7 @@ FixstarsSGM::FixstarsSGM(ftl::Configurable* cfg) :
 		}
 	});
 
-	cfg->on("uniqueness", [this, cfg](const ftl::config::Event&) {
+	cfg->on("uniqueness", [this, cfg]() {
 		double uniqueness = cfg->value("uniqueness", 0.0);
 		if (uniqueness < 0.0 || uniqueness > 1.0) {
 			LOG(WARNING) << "Invalid value for uniqueness (" << uniqueness << ")";
@@ -122,11 +122,11 @@ FixstarsSGM::FixstarsSGM(ftl::Configurable* cfg) :
 
 	updateP2Parameters();
 
-	cfg->on("canny_low", [this, cfg](const ftl::config::Event&) {
+	cfg->on("canny_low", [this, cfg]() {
 		updateP2Parameters();
 	});
 
-	cfg->on("canny_high", [this, cfg](const ftl::config::Event&) {
+	cfg->on("canny_high", [this, cfg]() {
 		updateP2Parameters();
 	});
 }
diff --git a/components/operators/src/disparity/optflow_smoothing.cpp b/components/operators/src/disparity/optflow_smoothing.cpp
index 897b67a7fcbac032d9fe8ea888cc13a165d31bb7..c69b0727beda8ceb22580609ed8f7181a22d40f9 100644
--- a/components/operators/src/disparity/optflow_smoothing.cpp
+++ b/components/operators/src/disparity/optflow_smoothing.cpp
@@ -47,7 +47,7 @@ void OpticalFlowTemporalSmoothing::_init(ftl::Configurable* cfg) {
 
 	threshold_ = cfg->value("threshold", 5.0f);
 
-	cfg->on("threshold", [this](const ftl::config::Event&) {
+	cfg->on("threshold", [this]() {
 		float threshold = config()->value("threshold", 5.0f);
 		if (threshold < 0.0) {
 			LOG(WARNING) << "invalid threshold " << threshold << ", value must be positive";
@@ -58,7 +58,7 @@ void OpticalFlowTemporalSmoothing::_init(ftl::Configurable* cfg) {
 		}
 	});
 
-	cfg->on("history_size", [this, &cfg](const ftl::config::Event&) {
+	cfg->on("history_size", [this, &cfg]() {
 		int n_max = cfg->value("history_size", 7);
 
 		if (n_max < 1) {
diff --git a/components/operators/src/operator.cpp b/components/operators/src/operator.cpp
index 5c729697c1ebbc6a34d44a2350330d1f1acddc7e..339ba27f81bb32f05c54fe66df0ded78792ca566 100644
--- a/components/operators/src/operator.cpp
+++ b/components/operators/src/operator.cpp
@@ -12,7 +12,7 @@ using ftl::rgbd::Source;
 Operator::Operator(ftl::Configurable *config) : config_(config) {
 	enabled_ = config_->value("enabled", true);
 
-	config_->on("enabled", [this](const ftl::config::Event &e) {
+	config_->on("enabled", [this]() {
 		enabled_ = config_->value("enabled", true);
 	});
 }
diff --git a/components/renderers/cpp/src/CUDARender.cpp b/components/renderers/cpp/src/CUDARender.cpp
index 55487c6dc01660627e93bacb397801fab1bc83a2..2f753365358ca49a8913ee874087b5374270724c 100644
--- a/components/renderers/cpp/src/CUDARender.cpp
+++ b/components/renderers/cpp/src/CUDARender.cpp
@@ -62,27 +62,27 @@ CUDARender::CUDARender(nlohmann::json &config) : ftl::render::FSRenderer(config)
 
 	on("touch_sensitivity", touch_dist_, 0.04f);
 
-	on("clipping_enabled", [this](const ftl::config::Event &e) {
+	on("clipping_enabled", [this]() {
 		clipping_ = value("clipping_enabled", true);
 	});
 
 	norm_filter_ = value("normal_filter", -1.0f);
-	on("normal_filter", [this](const ftl::config::Event &e) {
+	on("normal_filter", [this]() {
 		norm_filter_ = value("normal_filter", -1.0f);
 	});
 
 	backcull_ = value("back_cull", true);
-	on("back_cull", [this](const ftl::config::Event &e) {
+	on("back_cull", [this]() {
 		backcull_ = value("back_cull", true);
 	});
 
 	mesh_ = value("meshing", true);
-	on("meshing", [this](const ftl::config::Event &e) {
+	on("meshing", [this]() {
 		mesh_ = value("meshing", true);
 	});
 
 	background_ = parseCVColour(value("background", std::string("#4c4c4c")));
-	on("background", [this](const ftl::config::Event &e) {
+	on("background", [this]() {
 		background_ = parseCVColour(value("background", std::string("#4c4c4c")));
 	});
 
diff --git a/components/rgbd-sources/src/source.cpp b/components/rgbd-sources/src/source.cpp
index 45018ee89619feeafb410a5518330cb350cc7f91..4a4d5e92549042e606f9241e687b817205387e20 100644
--- a/components/rgbd-sources/src/source.cpp
+++ b/components/rgbd-sources/src/source.cpp
@@ -35,7 +35,7 @@ Source::Source(ftl::config::json_t &cfg) : Configurable(cfg) {
 	is_retrieving = false;
 	reset();
 
-	on("uri", [this](const ftl::config::Event &e) {
+	on("uri", [this]() {
 		LOG(INFO) << "URI change for source: " << getURI();
 		reset();
 	});
diff --git a/components/rgbd-sources/src/sources/middlebury/middlebury_source.cpp b/components/rgbd-sources/src/sources/middlebury/middlebury_source.cpp
index 656310c26a96730de4dec8cd37b72ae592bc9a9d..eee884d2f9e62c6c8a42b98d681b19b2463ac14b 100644
--- a/components/rgbd-sources/src/sources/middlebury/middlebury_source.cpp
+++ b/components/rgbd-sources/src/sources/middlebury/middlebury_source.cpp
@@ -91,20 +91,20 @@ MiddleburySource::MiddleburySource(ftl::rgbd::Source *host, const string &dir)
 	host_->getConfig()["doffs"] = params_.doffs;
 
 	// Add event handlers to allow calibration changes...
-	host_->on("baseline", [this](const ftl::config::Event &e) {
+	host_->on("baseline", [this]() {
 		params_.baseline = host_->value("baseline", params_.baseline);
 	});
 
-	host_->on("focal", [this](const ftl::config::Event &e) {
+	host_->on("focal", [this]() {
 		params_.fx = host_->value("focal", params_.fx);
 		params_.fy = params_.fx;
 	});
 
-	host_->on("doffs", [this](const ftl::config::Event &e) {
+	host_->on("doffs", [this]() {
 		params_.doffs = host_->value("doffs", params_.doffs);
 	});
 
-	host_->on("centre_x", [this](const ftl::config::Event &e) {
+	host_->on("centre_x", [this]() {
 		params_.cx = host_->value("centre_x", params_.cx);
 	});
 
diff --git a/components/rgbd-sources/src/sources/screencapture/screencapture.cpp b/components/rgbd-sources/src/sources/screencapture/screencapture.cpp
index 5c9ca286b84726e7e5673d554207b822bc06b28d..87b34497b397f30860d72b29ad2f255e0541c173 100644
--- a/components/rgbd-sources/src/sources/screencapture/screencapture.cpp
+++ b/components/rgbd-sources/src/sources/screencapture/screencapture.cpp
@@ -180,7 +180,7 @@ ScreenCapture::ScreenCapture(ftl::rgbd::Source *host)
 	//state_.setPose(matrix(cv::Vec3d(0.0, 3.14159, 0.0), cv::Vec3d(0.0,0.0,params_.maxDepth+offsetz)));
 	pose_ = matrix(cv::Vec3d(0.0, 3.14159, 0.0), cv::Vec3d(0.0,0.0,params_.maxDepth+offsetz));
 
-	host_->on("size", [this](const ftl::config::Event &e) {
+	host_->on("size", [this]() {
 		float offsetz = host_->value("offset_z",0.0f);
 		params_.maxDepth = host_->value("size", 1.0f);
 		//state_.getLeft() = params_;
@@ -188,7 +188,7 @@ ScreenCapture::ScreenCapture(ftl::rgbd::Source *host)
 		do_update_params_ = true;
 	});
 
-	host_->on("offset_z", [this](const ftl::config::Event &e) {
+	host_->on("offset_z", [this]() {
 		float offsetz = host_->value("offset_z",0.0f);
 		params_.maxDepth = host_->value("size", 1.0f);
 		//state_.getLeft() = params_;
@@ -196,15 +196,15 @@ ScreenCapture::ScreenCapture(ftl::rgbd::Source *host)
 		do_update_params_ = true;
 	});
 
-	host_->on("offset_x", [this](const ftl::config::Event &e) {
+	host_->on("offset_x", [this]() {
 		offset_x_ = host_->value("offset_x", 0);
 	});
 
-	host_->on("offset_y", [this](const ftl::config::Event &e) {
+	host_->on("offset_y", [this]() {
 		offset_y_ = host_->value("offset_y", 0);
 	});
 
-	host_->on("enable_touch", [this](const ftl::config::Event &e) {
+	host_->on("enable_touch", [this]() {
 		do_update_params_ = true;
 	});
 }
diff --git a/components/rgbd-sources/src/sources/stereovideo/pylon.cpp b/components/rgbd-sources/src/sources/stereovideo/pylon.cpp
index 591ed6b6bffeff48a696d9a9cac29a0af2e8a29a..d9d270cdeb718ba9a4ec5c698a5e1d9e26fcd79e 100644
--- a/components/rgbd-sources/src/sources/stereovideo/pylon.cpp
+++ b/components/rgbd-sources/src/sources/stereovideo/pylon.cpp
@@ -100,7 +100,7 @@ PylonDevice::PylonDevice(nlohmann::json &config)
 	right_hm_ = cv::cuda::HostMem(height_, width_, CV_8UC4);
 	hres_hm_ = cv::cuda::HostMem(fullheight_, fullwidth_, CV_8UC4);
 
-	on("exposure", [this](const ftl::config::Event &e) {
+	on("exposure", [this]() {
 		if (lcam_->GetDeviceInfo().GetModelName() != "Emulation") {
 			lcam_->ExposureTime.SetValue(value("exposure", 24000.0f));  // Exposure time in microseconds
 		}
diff --git a/components/rgbd-sources/src/sources/stereovideo/stereovideo.cpp b/components/rgbd-sources/src/sources/stereovideo/stereovideo.cpp
index 9b67820a9467b1dec1a013122088bfe863626371..e0385eb5cc646b700d85225f56943ebc39f1a87e 100644
--- a/components/rgbd-sources/src/sources/stereovideo/stereovideo.cpp
+++ b/components/rgbd-sources/src/sources/stereovideo/stereovideo.cpp
@@ -175,16 +175,16 @@ void StereoVideoSource::init(const string &file) {
 	LOG(INFO) << "StereoVideo source ready...";
 	ready_ = true;
 
-	host_->on("size", [this](const ftl::config::Event &e) {
+	host_->on("size", [this]() {
 		do_update_params_ = true;
 	});
 
-	host_->on("rectify", [this](const ftl::config::Event &e) {
+	host_->on("rectify", [this]() {
 		calibration_.enabled = host_->value("rectify", true);
 		do_update_params_ = true;
 	});
 
-	host_->on("offset_z", [this](const ftl::config::Event &e) {
+	host_->on("offset_z", [this]() {
 		do_update_params_ = true;
 	});
 }
diff --git a/components/streams/src/filestream.cpp b/components/streams/src/filestream.cpp
index 90cf549ab31bfe989df6c9b3653527a0ec31b8ad..b887e028a0a1895d351ebb7052c979f1dfd7f131 100644
--- a/components/streams/src/filestream.cpp
+++ b/components/streams/src/filestream.cpp
@@ -17,7 +17,7 @@ File::File(nlohmann::json &config) : Stream(config), ostream_(nullptr), istream_
 	checked_ = false;
 	save_data_ = value("save_data", false);
 
-	on("save_data", [this](const ftl::config::Event &e) {
+	on("save_data", [this]() {
 		save_data_ = value("save_data", false);
 	});
 }
@@ -35,7 +35,7 @@ File::File(nlohmann::json &config, std::ofstream *os) : Stream(config), ostream_
 	checked_ = false;
 	save_data_ = value("save_data", false);
 
-	on("save_data", [this](const ftl::config::Event &e) {
+	on("save_data", [this]() {
 		save_data_ = value("save_data", false);
 	});
 }
diff --git a/components/streams/src/receiver.cpp b/components/streams/src/receiver.cpp
index 20067b95525c7dbea313eff3653933de9e2fe72e..b1bd910450b26094b271af903859857689634a5c 100644
--- a/components/streams/src/receiver.cpp
+++ b/components/streams/src/receiver.cpp
@@ -44,7 +44,7 @@ Receiver::Receiver(nlohmann::json &config, ftl::data::Pool *p) : ftl::Configurab
 		}
 	});*/
 
-	on("frame_mask", [this](const ftl::config::Event &e) {
+	on("frame_mask", [this]() {
 		frame_mask_ = value("frame_mask", 0xFFFFFFFFu);
 	});
 }
diff --git a/components/streams/src/renderer.cpp b/components/streams/src/renderer.cpp
index b7716965a53d2add52d71a65b02ddda03770aac6..5da8355ed26927dbf3b9839e5359ed2dea4198fb 100644
--- a/components/streams/src/renderer.cpp
+++ b/components/streams/src/renderer.cpp
@@ -17,7 +17,7 @@ Source::Source(nlohmann::json &config, ftl::stream::Feed *feed)
 : ftl::Configurable(config), feed_(feed), impl_(nullptr) {
 	reset();
 
-	on("uri", [this](const ftl::config::Event &e) {
+	on("uri", [this]() {
 		LOG(INFO) << "URI change for renderer: " << getURI();
 		reset();
 	});
diff --git a/components/streams/src/renderers/openvr_render.cpp b/components/streams/src/renderers/openvr_render.cpp
index 5c515e7c15068ff4acaf16069670bcae8b4cc0b7..fade788777e9f5f43cee4c35c10cfc35212c5141 100644
--- a/components/streams/src/renderers/openvr_render.cpp
+++ b/components/streams/src/renderers/openvr_render.cpp
@@ -48,7 +48,7 @@ OpenVRRender::OpenVRRender(ftl::render::Source *host, ftl::stream::Feed *feed)
 		filter_ = feed_->filter({Channel::Colour, Channel::Depth});
 	}
 
-	host_->on("source", [this](const ftl::config::Event &e) {
+	host_->on("source", [this]() {
 		std::string source = host_->value("source", std::string(""));
 
 		if (source.size() > 0) {
diff --git a/components/streams/src/renderers/screen_render.cpp b/components/streams/src/renderers/screen_render.cpp
index bc78d4216292d2aa024e813e5a9620a8dfd5fb85..b59860b003fd21cac69d5e495abf9a4cc4154a80 100644
--- a/components/streams/src/renderers/screen_render.cpp
+++ b/components/streams/src/renderers/screen_render.cpp
@@ -33,13 +33,7 @@ ScreenRender::ScreenRender(ftl::render::Source *host, ftl::stream::Feed *feed)
 	intrinsics_ = ftl::create<ftl::Configurable>(host_, "intrinsics");
 	refresh_calibration_ = false;
 
-	intrinsics_->on("focal", [this](const ftl::config::Event &e) {
-		refresh_calibration_ = true;
-	});
-	intrinsics_->on("width", [this](const ftl::config::Event &e) {
-		refresh_calibration_ = true;
-	});
-	intrinsics_->on("height", [this](const ftl::config::Event &e) {
+	intrinsics_->onAny({"focal","width","height"}, [this]() {
 		refresh_calibration_ = true;
 	});
 
@@ -52,7 +46,7 @@ ScreenRender::ScreenRender(ftl::render::Source *host, ftl::stream::Feed *feed)
 		filter_ = feed_->filter({Channel::Colour, Channel::Depth});
 	}
 
-	host_->on("source", [this](const ftl::config::Event &e) {
+	host_->on("source", [this]() {
 		std::string source = host_->value("source", std::string(""));
 
 		if (source.size() > 0) {
diff --git a/components/streams/src/sender.cpp b/components/streams/src/sender.cpp
index 7811101be3ddc663fb9e8c23c0e5ed1713122e29..b6b807080180cc046a4900c2309f7a47fd891624 100644
--- a/components/streams/src/sender.cpp
+++ b/components/streams/src/sender.cpp
@@ -29,7 +29,7 @@ Sender::Sender(nlohmann::json &config) : ftl::Configurable(config), stream_(null
 	add_iframes_ = value("iframes", 50);
 	timestamp_ = -1;
 
-	on("iframes", [this](const ftl::config::Event &e) {
+	on("iframes", [this]() {
 		add_iframes_ = value("iframes", 50);
 	});
 }