in Cthulhu/include/cthulhu/ContextImpl.h [313:376]
MultiSubscriber Context::subscribe(
const std::array<StreamID, N>& streamIDs,
const std::function<void(const T&...)>& callback,
const std::function<bool(const U&...)>& configCallback,
MultiSubscriberOptions options) const {
// Create Aligner
auto aligner = details::alignerFromOptions(options.alignerType, std::move(options.alignerPtr));
// Get Types and Validate
std::array<uint32_t, N> types;
details::SampleTypesStatic<T...>::template getTypes<0>(types);
std::array<bool, N> basicStreams;
for (unsigned long i = 0; i < N; ++i) {
auto type = Framework::instance().typeRegistry()->findTypeID(types[i]);
if (!type) {
auto str = "Attempted to lookup unregistered typeID: " + std::to_string(types[i]);
XR_LOGCE("Cthulhu", "{}", str);
throw std::runtime_error(str);
}
basicStreams[i] = type->isBasic();
}
// Create Callbacks and Register in Aligner
std::function<void(const std::vector<StreamSample>&, const T&...)> callbackAppended =
[callback](const std::vector<StreamSample>&, const T&... args) -> void { callback(args...); };
AlignerSampleCallback cb = details::generateAlignerCallback<0>(callbackAppended);
aligner->setCallback(cb);
if (configCallback != nullptr) {
std::function<bool(const std::vector<StreamConfig>&, const U&...)> configCallbackAppended =
[configCallback](const std::vector<StreamConfig>&, const U&... args) -> bool {
return configCallback(args...);
};
AlignerConfigCallback ccb =
details::generateAlignerConfigCallback<0>(configCallbackAppended, basicStreams);
aligner->setConfigCallback(ccb);
}
// Get Streams from Registry and Load in Aligner
std::vector<StreamIDView> streamIDsVec;
streamIDsVec.reserve(N);
for (unsigned long i = 0; i < N; i++) {
StreamID streamID = applyNamespace(streamIDs[i]);
auto type = Framework::instance().typeRegistry()->findTypeID(types[i]);
StreamDescription desc{streamID, types[i]};
auto si = Framework::instance().streamRegistry()->registerStream(desc);
if (types[i] != si->description().type()) {
// Type mismatch detected
XR_LOGCW("Cthulhu", "Type mismatch detected [{}, {}]", types[i], si->description().type());
return MultiSubscriber(streamIDsVec);
}
streamIDsVec.push_back(StreamIDView(si->description().id()));
aligner->registerConsumer(si, i);
}
aligner->finalize();
// Return Node
if (ctx_ == nullptr) {
const auto err = "Attempted to register multi subscriber against null context";
XR_LOGCE("Cthulhu", "{}", err);
throw std::runtime_error(err);
}
ctx_->registerSubscriber(streamIDsVec);
return MultiSubscriber(streamIDsVec, std::move(aligner));
};